• 贪吃蛇


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <memory.h>
      4 #include <time.h>
      5 #include <signal.h>
      6 
      7 #define WIDTH 10
      8 #define HEIGHT 10
      9 #define SUCCESS 0
     10 #define FAILURE 1
     11 #define EATEN_FOOD 2
     12 #define GAME_OVER 3
     13 
     14 const int width = WIDTH;
     15 const int height = HEIGHT;
     16 static int area[WIDTH][HEIGHT];
     17 
     18 #define CHECK_FALSE_RET(expr, ret) if(!(expr)) return ret;
     19 
     20 #define LOG(format, ...) //printf(format, ##__VA_ARGS__)
     21 
     22 typedef enum Direct {
     23     NO_DIRECT,
     24     UP,
     25     DOWN,
     26     LEFT,
     27     RIGHT
     28 }Direct;
     29 
     30 typedef struct Point {
     31     int x;
     32     int y;
     33     Point *next;
     34 }Point;
     35 
     36 typedef struct Snake {
     37     Point *head;
     38     Point *tail;
     39     int length;
     40     Direct direct;
     41 }Snake;
     42 
     43 Point* NewPoint()
     44 {
     45     Point *np = (Point*)malloc(sizeof(Point));
     46     if(np != NULL)
     47     {
     48         memset(np, 0, sizeof(Point));
     49     }
     50     return np;
     51 }
     52 
     53 Point* NewPointWithParam(int x, int y)
     54 {
     55     Point *np = NewPoint();
     56     if(np != NULL)
     57     {
     58         np->x = x;
     59         np->y = y;
     60     }
     61     return np;
     62 }
     63 
     64 Direct DecideForwardDirect(Snake *snake, Point *food)
     65 {
     66     if(snake == NULL || food == NULL)
     67     {
     68         LOG("[error]: DecideForwardDirect failed. snake=NULL|food=NULL
    ");
     69          return NO_DIRECT;
     70     }
     71     Direct dir = NO_DIRECT;
     72     Point *head = snake->head;
     73     if(head == NULL) 
     74     {
     75         LOG("[error]: DecideForwardDirect failed. head=NULL
    ");
     76         return NO_DIRECT;
     77     }
     78     
     79     switch(snake->direct)
     80     {
     81         case UP:
     82             if(head->x == 0) dir = RIGHT;
     83             else if(head->x == width-2) dir = LEFT;
     84             break;
     85         case DOWN:
     86             if(head->x == width - 1)
     87             {
     88                 if(head->y == height - 1) dir = LEFT;
     89                 else dir = DOWN;
     90             }
     91             break;
     92         case LEFT:
     93             if(head->x == 0) dir = UP;
     94             else dir = LEFT;
     95             break;
     96         case RIGHT:
     97             if(head->y == 0 && head->x == width - 1) dir = DOWN;
     98             else if(head->y != 0 && head->x == width - 2) dir = UP;
     99             else dir = RIGHT;
    100             break;
    101         default:
    102             break;
    103     }
    104     snake->direct = dir;
    105     return dir;
    106 }
    107 
    108 Point *CreateOneFood(Snake *snake)
    109 {    
    110     if(snake == NULL) return NULL;
    111  
    112     Point *np = NULL;
    113     Point *food = NULL;
    114     int unusedNum = width*height - snake->length;
    115     int randPos;
    116     int x, y;
    117     int foodX = -1, foodY = -1;
    118     memset(area, 0, width*height*sizeof(int));
    119     np = snake->head;
    120     while(np != NULL)
    121     {
    122         area[np->x][np->y] = 1;
    123         np = np->next;
    124     }
    125     randPos = rand() % unusedNum;
    126     for(x=0; x<width; x++)
    127     {
    128         if(randPos < 0) break;
    129         for(y=0; y<height; y++)
    130         {
    131             if(area[x][y] == 0) randPos--;
    132             if(randPos < 0)
    133             {
    134                 foodX = x;
    135                 foodY = y;
    136                 break;
    137             }
    138         }
    139     }
    140 
    141     if((foodX >= 0 && foodX < width) && (foodY >= 0 && foodY < height))
    142     {
    143         food = NewPointWithParam(foodX, foodY);
    144     }
    145     
    146     return food;
    147 }
    148 
    149 int FortainEatFood(Snake *snake, Point *food)
    150 {
    151     if(snake == NULL || food == NULL) return FAILURE;
    152     food->next = snake->head;
    153     snake->head = food;
    154     if(snake->tail == NULL) snake->tail = food;
    155     snake->length++;
    156     return SUCCESS;
    157 }
    158 
    159 Point *GetPreviousTail(Snake *snake)
    160 {
    161     if(snake == NULL) return NULL;
    162     Point *np = snake->head;
    163      while(np->next != snake->tail && np->next != NULL) np = np->next;
    164     if(np->next == NULL) return NULL;
    165     return np;
    166 }
    167 
    168 
    169 int FortainForward(Snake *snake, Direct dir, Point *food)
    170 {
    171     if(snake == NULL) return FAILURE;
    172     if(dir == NO_DIRECT) return FAILURE;
    173     if(food == NULL) return FAILURE;
    174     Point *preTail;
    175     preTail = GetPreviousTail(snake);
    176     if(preTail == NULL) return FAILURE;
    177     int currX = snake->head->x;
    178     int currY = snake->head->y;
    179     int nextX = currX;
    180     int nextY = currY;
    181     
    182     switch(dir)
    183     {
    184         case UP:
    185             nextY = currY - 1;
    186             break;
    187         case DOWN:
    188             nextY = currY + 1;
    189             break;
    190         case LEFT:
    191             nextX = currX - 1;
    192             break;
    193         case RIGHT:
    194             nextX = currX + 1;
    195         default:
    196             break;
    197     }
    198     if(nextX == food->x && nextY == food->y)
    199     {
    200         FortainEatFood(snake, food);
    201         return EATEN_FOOD;
    202     }
    203     else
    204     {
    205         snake->tail->x = nextX;
    206         snake->tail->y = nextY;
    207         snake->tail->next = snake->head;
    208         snake->head = snake->tail;
    209         snake->tail = preTail;
    210         snake->tail->next = NULL;
    211     }
    212     
    213     return SUCCESS;
    214 }
    215 
    216 int FortainGameInit(Snake *snake)
    217 {
    218     if(snake == NULL) return FAILURE;
    219     Point *np1 = NewPointWithParam(width-1, height-1);
    220     Point *np2 = NewPointWithParam(width-2, height-1);
    221     Point *np3 = NewPointWithParam(width-3, height-1);
    222     if(np1 == NULL || np2 == NULL || np3 == NULL) return FAILURE;
    223     
    224     FortainEatFood(snake, np1);
    225     FortainEatFood(snake, np2);
    226     FortainEatFood(snake, np3);
    227 
    228     snake->direct = LEFT;
    229     return SUCCESS;
    230 }
    231 
    232 int FortainGameCheck(Snake *snake)
    233 {
    234     if(snake == NULL) return FAILURE;
    235     memset(area, 0, width*height*sizeof(int));
    236     Point *np = snake->head;
    237     while(np != NULL)
    238     {
    239         CHECK_FALSE_RET(np->x >= 0, FAILURE);
    240         CHECK_FALSE_RET(np->x < width, FAILURE);
    241         CHECK_FALSE_RET(np->y >= 0, FAILURE);
    242         CHECK_FALSE_RET(np->y < height, FAILURE);
    243 
    244         CHECK_FALSE_RET(area[np->x][np->y] == 0, GAME_OVER);
    245         area[np->x][np->y] = 1;
    246         np = np->next;
    247     }
    248     CHECK_FALSE_RET(snake->length != width*height, GAME_OVER);
    249     return SUCCESS;
    250 }
    251 
    252 void FortainGameMain()
    253 {
    254     Snake snake;
    255     Point *food;
    256     int ret;
    257     int count = 0;
    258     Direct dir;
    259 
    260     memset(&snake, 0, sizeof(Snake));
    261     ret = FortainGameInit(&snake);
    262     if(ret == FAILURE) 
    263     {
    264         LOG("[error]: GameInit failed!
    ");
    265         return;
    266     }
    267     LOG("[info]: GameInit done! length=%d
    ", snake.length);
    268     
    269     Point *np = snake.head;
    270     while(np != NULL)
    271     {
    272         LOG("x=%d,y=%d,next=%x
    ", np->x, np->y, np->next);
    273         np = np->next;
    274     }
    275     
    276     food = CreateOneFood(&snake);
    277     if(food == NULL) LOG("[error]: CreateFood failed!
    ");
    278     else LOG("[info]: CreateFood success! P(%d, %d)
    ", food->x, food->y);
    279     while(true)
    280     {
    281         dir = DecideForwardDirect(&snake, food);
    282         LOG("[info]: DecideDirect, dir=%d
    ", dir);
    283         ret = FortainForward(&snake, dir, food);
    284         LOG("[info]: Forward, dir=%d, food=(%d,%d), head=(%d,%d), length=%d
    ", dir, food->x, food->y, snake.head->x, snake.head->y, snake.length);
    285         if(ret == FAILURE)
    286         {
    287             LOG("[error]: Forward failed.dir|%d,length|%d.
    ", dir, snake.length);
    288             break;
    289         }
    290         else if(ret == EATEN_FOOD)
    291         {
    292             LOG("[info]: Eat food. length|%d
    ", snake.length);
    293             if(snake.length < width*height)
    294             {
    295                 food = CreateOneFood(&snake);
    296                 if(food == NULL)
    297                 {
    298                     LOG("[error]: CreateFood failed!
    ");
    299                     break;
    300                 }
    301                 else LOG("[info]: CreateFood success! P(%d, %d)
    ", food->x, food->y);
    302             }
    303         }
    304         ret = FortainGameCheck(&snake);
    305         if(ret == FAILURE)
    306         {
    307             LOG("[error]: GameCheck failed!
    ");
    308             break;
    309         }
    310         else if(ret == GAME_OVER)
    311         {
    312             printf("[info]: Game over!!! length=%d, count=%d
    ", snake.length, count);
    313             break;
    314         }
    315         count++;
    316     }
    317 }
    318 
    319 void SignHandler(int sign)
    320 {
    321     switch(sign)
    322     {
    323         case SIGABRT:
    324             printf("signal: SIGABRT. 
     程序异常终止。
    ");
    325             break;
    326         case SIGFPE:
    327             printf("signal: SIGFPE. 
     算术运算出错,如除数为 0 或溢出(不一定是浮点运算)。
    ");
    328             break;
    329         case SIGILL:
    330             printf("signal: SIGILL. 
     非法函数映象,如非法指令,通常是由于代码中的某个变体或者尝试执行数据导致的。
    ");
    331             break;
    332         case SIGINT:
    333             printf("signal: SIGINT. 
     中断信号,如 ctrl-C,通常由用户生成。
    ");
    334             break;
    335         case SIGSEGV:
    336             printf("signal: SIGSEGV. 
     非法访问存储器,如访问不存在的内存单元。
    ");
    337             break;
    338         case SIGTERM:
    339             printf("signal: SIGTERM. 
     发送给本程序的终止请求信号。
    ");
    340             break;
    341     }
    342 }
    343 
    344 int main()
    345 {
    346     signal(SIGABRT, SignHandler);
    347     signal(SIGFPE, SignHandler);
    348     signal(SIGILL, SignHandler);
    349     signal(SIGINT, SignHandler);
    350     signal(SIGSEGV, SignHandler);
    351     signal(SIGTERM, SignHandler);
    352     for(int i=0; i<100; i++)
    353     {
    354         clock_t start = clock();
    355         srand(time(NULL));
    356         FortainGameMain();
    357         printf("Time: %d ms
    ", clock()-start);
    358     }
    359     return 0;
    360 }
  • 相关阅读:
    try? try! try do catch try 使用详解
    Swift Write to file 到电脑桌面
    NSLayoutConstraint 使用详解 VFL使用介绍
    automaticallyAdjustsScrollViewInsets 详解
    Swift 给UITableView 写extension 时 报错 does not conform to protocol 'UITableViewDataSource'
    OC Swift中检查代码行数
    Swift中 @objc 使用介绍
    SWift中 '?' must be followed by a call, member lookup, or subscript 错误解决方案
    Swift 中 insetBy(dx: CGFloat, dy: CGFloat) -> CGRect 用法详解
    求1000之内所有“完数”(注:C程序设计(第四版) 谭浩强/著 P141-9)
  • 原文地址:https://www.cnblogs.com/rmthy/p/6404980.html
Copyright © 2020-2023  润新知