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