c实现终端中的贪食蛇(2)
修复了前一篇的bug, 可以算是完整版.
没有设立game over的条件(容易, 但不想做这个), 实现了自己咬断自己的功能~
上代码~
1 #include <stdlib.h> 2 #include <curses.h> 3 #include <signal.h> 4 #include <sys/time.h> 5 6 #define WIDTH 70 7 #define LENGTH 30 8 #define MSEC 200 /* mseconds to refresh screen */ 9 10 typedef struct food { 11 int x; 12 int y; 13 } food; 14 15 typedef struct snack { 16 int x; 17 int y; 18 struct snack* next; 19 } snack; 20 21 food* fd; 22 snack* tail; 23 snack* head; 24 char direction; 25 26 void show(); 27 int set_timer(); 28 void init_game(); 29 void set_food(); 30 void get_order(); 31 void update_snack(); 32 void set_frame(); 33 void free_tail(); 34 35 void show() { 36 update_snack(); 37 erase(); 38 39 set_frame(); 40 /* show food */ 41 move(fd->x, fd->y); 42 printw("o"); 43 /* show snack */ 44 snack* p; 45 for (p = tail; p != NULL; p = p->next) { 46 move(p->x, p->y); 47 printw("@"); 48 } 49 50 refresh(); 51 } 52 53 int set_timer() { 54 long usec = MSEC * 1000; 55 56 struct itimerval my_timerval; 57 my_timerval.it_interval.tv_sec = 0; 58 my_timerval.it_interval.tv_usec = usec; 59 my_timerval.it_value.tv_sec = 0; 60 my_timerval.it_value.tv_usec = usec; 61 62 return setitimer(ITIMER_REAL, &my_timerval, 0); 63 } 64 65 void init_game() { 66 cbreak(); 67 noecho(); 68 curs_set(0); 69 srand(time(0)); 70 71 direction = 'w'; 72 tail = (snack*) malloc(sizeof(snack)); 73 head = (snack*) malloc(sizeof(snack)); 74 fd = (food*) malloc(sizeof(food)); 75 /* set_snack */ 76 tail->x = LENGTH / 2; 77 tail->y = WIDTH / 2; 78 tail->next = NULL; 79 head = tail; 80 81 set_food(); 82 set_timer(); 83 } 84 85 void set_food() { 86 int x0, y0; 87 /* 88 x0 = rand() % LENGTH; 89 y0 = rand() % WIDTH; 90 */ 91 int in_snack = 0; 92 do { 93 x0 = rand() % LENGTH; 94 y0 = rand() % WIDTH; 95 96 snack* p; 97 for (p = tail; p != NULL; p = p->next) { 98 if ((x0 == p->x) && (y0 == p->y)) { 99 in_snack = 1; 100 break; 101 } 102 } 103 } while (in_snack); 104 105 fd->x = x0; 106 fd->y = y0; 107 } 108 109 void get_order() { 110 char ch; 111 112 while (1) { 113 ch = getchar(); 114 if (('w' == direction) || ('s' == direction)) { 115 switch (ch) { 116 case 'a': 117 direction = 'a'; 118 break; 119 case 'd': 120 direction = 'd'; 121 break; 122 default: 123 break; 124 } 125 } else { 126 switch (ch) { 127 case 'w': 128 direction = 'w'; 129 break; 130 case 's': 131 direction = 's'; 132 break; 133 default: 134 break; 135 } 136 } 137 } 138 } 139 140 void update_snack() { 141 head->next = (snack*) malloc(sizeof(snack)); 142 int temp_x = head->x; 143 int temp_y = head->y; 144 145 head = head->next; 146 head->x = temp_x; 147 head->y = temp_y; 148 head->next = NULL; 149 switch (direction) { 150 case 'w': 151 head->x -= 1; 152 break; 153 case 'a': 154 head->y -= 1; 155 break; 156 case 's': 157 head->x += 1; 158 break; 159 case 'd': 160 head->y += 1; 161 break; 162 default: 163 break; 164 } 165 if (head->x < 0) { 166 head->x += (LENGTH + 1); 167 } else if (head->x > LENGTH) { 168 head->x = head->x % LENGTH; 169 } 170 if (head->y < 0) { 171 head->y += (WIDTH + 1); 172 } else if (head->y >WIDTH) { 173 head->y = head->y % WIDTH; 174 } 175 176 if ((head->x != fd->x) || (head->y != fd->y)) { 177 free_tail(); 178 } else { /* meet food */ 179 set_food(); 180 } 181 182 snack* p; 183 for (p = tail; p != head; p = p->next) { 184 if ((p->x == head->x) && (p->y == head->y)) { 185 while (tail != p->next) 186 free_tail(); /* delete tail to p->next */ 187 } 188 } 189 } 190 191 void set_frame() { 192 int i, j; 193 194 for (i = 0; i <= LENGTH; i++) { 195 move(i, 0); 196 printw("|"); 197 move(i, WIDTH); 198 printw("|"); 199 } 200 for (j = 0; j <= WIDTH; j++) { 201 move(0, j); 202 printw("_"); 203 move(LENGTH, j); 204 printw("_"); 205 } 206 } 207 208 void free_tail() { 209 snack* temp; 210 temp = tail; 211 tail = tail->next; 212 free(temp); 213 temp = NULL; 214 } 215 216 int main() { 217 initscr(); 218 init_game(); 219 signal(SIGALRM, show); 220 get_order(); 221 endwin(); 222 223 return 0; 224 }