ubuntu下写的,在linux shell可运行 ,想编译请安装
libncurses5-dbg libncurses5-dev
使用参数 : g++ -lcurses snake.c 编译
方向键使用vim 默认的hjkl进行移动,可以熟悉vim的方向键
菜单中 L 是确定 ,游戏中q是退出
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <curses.h>
5 #include <time.h>
6
7 #define LEFT 3
8 #define RIGHT 1
9 #define UP 2
10 #define DOWN 0
11
12 //snake length
13 #define N 800
14
15 struct node {
16 int x, y;
17 node *next;
18 node() {
19 next = NULL;
20 } node(int a, int b) {
21 x = a;
22 y = b;
23 next = NULL;
24 }
25 };
26
27 struct node snake[N];
28 struct node food;
29 node *fr = &snake[0], *to = &snake[2]; //头尾
30
31 inline void message(int x, int y, char t)
32 {
33 move(x, y);
34 addch(t);
35 }
36
37 int SPEED; //速度
38 int dir[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
39
40 int acc = 0;
41 int pre;
42 int top;
43 int n = 20, m = 60;
44 int score;
45 bool first_time;
46 timespec delay;
47 timespec dummy;
48
49 void genFood()
50 {
51 int i;
52 bool flag;
53 do {
54 flag = false;
55 food.x = rand() % (n - 2) + 1;
56 food.y = rand() % (m - 2) + 1;
57
58 for (i = 0; i < top; i++) {
59 if (food.x == snake[i].x || food.y == snake[i].y) {
60 flag = true; break;
61 }
62 }
63 } while (flag);
64 }
65
66 void handle_crash()
67 {
68 clear();
69 move(n / 2 + 1, 20);
70 printw("You Crashed");
71 move(n / 2 + 2, 20);
72 printw("Score: %d", score);
73
74 first_time = true;
75 refresh();
76 sleep(2);
77 clear();
78 }
79
80 void init()//初始游戏
81 {
82 snake[0] = node(10, 10);
83 snake[1] = node(10, 11);
84 snake[2] = node(10, 12);
85
86 snake[0].next = &snake[1];
87 snake[1].next = &snake[2];
88 snake[2].next = NULL;
89
90 score = 0;
91 SPEED = 30;
92 top = 3;
93 pre = 0;
94 fr = &snake[0];
95 to = &snake[2];
96
97 genFood();
98 }
99
100 bool game() // 游戏函数
101 {
102
103 int i, j, k;
104 int t;
105 bool crash;
106 bool flag = true;
107
108 node *temp;
109
110 clear();
111 nodelay(stdscr, true);
112
113 if (first_time) {
114 init();
115 first_time = false;
116 }
117
118 for (i = 1; i < m; i++) {
119 message(n, i, '-');
120 message(0, i, '-');
121 }
122 for (i = 1; i < n; i++) {
123 message(i, m, '|');
124 message(i, 0, '|');
125 }
126
127 while (1) {
128 delay.tv_nsec = 10000000 * SPEED;
129 t = getch();
130 switch (t) {
131 case 'h': t = LEFT; break;
132 case 'j': t = DOWN; break;
133 case 'k': t = UP; break;
134 case 'l': t = RIGHT; break;
135 case 'q': return false; break;
136 }
137
138 //erase
139 message(fr->x, fr->y, ' ');
140
141 if (flag) {
142 if (t >= 0 && t <= 3 && !(abs(t - pre) == 2)) { // 转向
143 fr->x = to->x + dir[t][0];
144 fr->y = to->y + dir[t][1];
145 temp = fr;
146 fr = fr->next;
147 temp->next = NULL;
148 to->next = temp;
149 to = temp;
150 pre = t;
151 } else {
152 fr->x = to->x + dir[pre][0];
153 fr->y = to->y + dir[pre][1];
154 temp = fr;
155 fr = fr->next;
156 temp->next = NULL;
157 to->next = temp;
158 to = temp;
159 }
160 } else {
161 if (t >= 0 && t <= 3 && !(abs(t - pre) == 2)) { // 转向
162 snake[top] = (*to);
163 to->next = &snake[top];
164 to = &snake[top++];
165 to->x = to->x + dir[t][0];
166 to->y = to->y + dir[t][1];
167 pre = t;
168 } else {
169 snake[top] = (*to);
170 to->next = &snake[top];
171 to = &snake[top++];
172 to->x = to->x + dir[pre][0];
173 to->y = to->y + dir[pre][1];
174 }
175 flag = true;
176 }
177
178 if (to->x == food.x && to->y == food.y) {
179 score += 50 - SPEED;
180 genFood();
181 flag = false;
182 if (acc++ > 3) acc = 0;
183
184 SPEED--;
185 }
186
187 if (1) //debug
188 {
189 move(n + 1, 0);
190 printw("score: %d\n", score);
191 printw("x:%d\ty:%d\n", to->x, to->y);
192 printw("x:%d\ty:%d\n", food.x, food.y);
193
194 }
195
196 crash = false;
197 if (to->x >= n || to->y >= m || to->x <= 0 || to->y <= 0) //撞墙
198 crash = true;
199 if (!crash) { //自撞
200 for (node * now = fr; now != to; now = now->next) {
201 if (now->x == to->x && now->y == to->y) {
202 crash = true;
203 break;
204 }
205 }
206 }
207
208 if (crash) { //撞上
209 handle_crash();
210 break;
211 }
212
213 message(food.x, food.y, '@');
214 for (i = 0; i < top; i++)
215 message(snake[i].x, snake[i].y, '*');
216
217 move(to->x, to->y); //移动到蛇头
218 refresh();
219 nanosleep(&delay, &dummy);//休眠一定时间
220 }
221
222 nodelay(stdscr, false);
223 return true;
224 }
225
226 bool menu()//菜单
227 {
228 const int M = 3;
229 char str[M][20] = {
230 "Start a new game",
231 "Continue",
232 "Quit"
233 };
234 int coor[M][2] = {
235 {3, 2},
236 {5, 2},
237 {7, 2}
238 };
239
240 int now = 0;
241 int t;
242 first_time = true;
243 while (1) {
244 switch (t) {
245 case 'j': //上
246 {
247 now++;
248 if (first_time && now == 1) now = 2;
249 if (now >= M) now = M - 1;
250 break;
251 }
252 case 'k': //下
253 {
254 now--;
255 if (first_time && now == 1) now = 0;
256 if (now < 0) now = 0;
257 break;
258 }
259 case 'l': //右
260 {
261 switch (now) {
262 case 0: first_time = true; game(); break;
263 case 1: game(); break;
264 case 2: return true; break;
265
266 }
267 now =0;
268 break;
269 }
270 }
271
272 move(coor[0][0], coor[0][1]); printw("%s", str[0]);
273 if (!first_time) {
274 move(coor[1][0], coor[1][1]); printw("%s", str[1]); }
275 move(coor[2][0], coor[2][1]); printw("%s", str[2]);
276
277 attron(A_STANDOUT); //反色
278 move(coor[now][0], coor[now][1]); printw("%s", str[now]);
279 attroff(A_STANDOUT);
280
281 refresh();
282 t = getch();
283
284 }
285 return false;
286 }
287
288 int main()
289 {
290 initscr();
291 srand((unsigned int)time(NULL));
292 delay.tv_sec = 0;
293
294 crmode(); //模式调整
295 noecho();
296 keypad(stdscr, TRUE);
297
298 menu();//主过程
299
300 refresh();
301 endwin();
302 exit(EXIT_SUCCESS);
303 }
304