作者: dave_cn 发表于 2010-07-18 21:20 原文链接 阅读: 148 评论: 2
转载请注明出处。http://www.cnblogs.com/dave_cn/
本程序需要ncurses库,ubuntu下安装ncurses可以执行下面命令:
sudo apt-get install libncurses5-dev
关于ncurses的用法,读者可以Google之。
程序运行的效果如下:
其中包含两个窗口,一个为game窗口,一个为日志窗口。
代码如下:
1 /**
3 * author: dave_cn
4 * date : 2010/7/14
5 * info :
6 * @ ...... food
7 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <ncurses.h>
15
16 #define TBool int
17 #define True 1
18 #define False 0
19 #define SHAPE_FOOD '@'
20 #define SHAPE_SNAKE '*'
21 #define GAMEWIN_YLEN 15
22 #define GAMEWIN_XLEN 60
23 #define LOGWIN_YLEN 7
24 #define LOGWIN_XLEN (GAMEWIN_XLEN)
25 #define LOGBUF_NUM (LOGWIN_YLEN-2)
26 #define LOGBUF_LEN (GAMEWIN_XLEN-2)
27 #define MAXLEVEL 12
28
29 #define GetSnakeTail(s) ((s)->head->front)
30
31 WINDOW *logwin;
32 #define INITRUNLOG() logwin = newlogw()
33 #define RUNLOG(str) runlog(logwin, str)
34 #define DESTROYRUNLOG() delwin(logwin)
35
36 int g_level;
37
38 enum TDirection {
39 DIR_UP,
40 DIR_DOWN,
41 DIR_LEFT,
42 DIR_RIGHT
43 };
44
45 struct TFood {
46 int y;
47 int x;
48 };
49
50 struct TSnakeNode {
51 int y;
52 int x;
53 struct TSnakeNode *front;
54 };
55
56 struct TSnake {
57 int length;
58 struct TSnakeNode *head;
59 enum TDirection dir;
60 };
61
62 int refreshgamew(WINDOW *win, struct TSnake *psnake);
63 void movesnake(struct TSnake *psnake);
64 int checksnake(struct TFood *pfood, struct TSnake *psnake);
65 void snakegrowup(struct TFood *pfood, struct TSnake *psnake);
66 void gameover(WINDOW *win, char *str);
67 struct TSnakeNode *newsnakenode(struct TSnakeNode **ppsnode, int y, int x);
68 WINDOW* newgamew();
69 struct TSnake* initsnake();
70 void destroysnake(struct TSnake *psnake);
71 void drawsnakew(WINDOW *win, struct TSnake *psnake);
72 void drawfoodw(WINDOW *win, struct TFood *pfood, struct TSnake *psnake);
73 TBool checkfood(struct TFood *pfood, struct TSnake *psnake);
74 WINDOW* newlogw();
75 void runlog(WINDOW *win, char *str);
76 void cleanline(WINDOW *win, int y, int x);
77
78 int main()
79 {
80 initscr();
81 raw();
82 noecho();
83 keypad(stdscr, TRUE);
84 curs_set(0);
85 refresh();
86
87 g_level = 1;
88 INITRUNLOG();
89 RUNLOG(" Press 'q' or 'Q' to quit.");
90 RUNLOG(" Press 'w/s/a/d' or 'W/S/A/D' to move the snake.");
91 RUNLOG("Info:");
92
93 WINDOW *gwin = newgamew();
94 struct TSnake *psnake = initsnake();
95 drawsnakew(gwin, psnake);
96
97 while (refreshgamew(gwin, psnake) >= 0) ;
98
99 getch();
100
101 destroysnake(psnake);
102 delwin(gwin);
103 DESTROYRUNLOG();
104 endwin();
105
106 return 0;
107 }
108
109 int refreshgamew(WINDOW *win, struct TSnake *psnake)
110 {
111 static TBool ffood = False;
112 struct TFood pfood;
113
114 if (!ffood) {
115 drawfoodw(win, &pfood, psnake);
116 ffood = True;
117 }
118
119 int key = -1;
120
121 fd_set set;
122 FD_ZERO(&set);
123 FD_SET(0, &set);
124
125 struct timeval timeout;
126 timeout.tv_sec = 0;
127 timeout.tv_usec= (6 - (int)(g_level/3)) * 100*1000;
128
129 if (select(1, &set, NULL, NULL, &timeout) < 0)
130 return -1;
131
132 if (FD_ISSET(0, &set)) {
133 while ((key = getch()) == -1) ;
134
135 switch (key) {
136 case 'w':
137 case 'W':
138 (psnake->dir == DIR_DOWN) ? : (psnake->dir = DIR_UP);
139 break;
140
141 case 's':
142 case 'S':
143 (psnake->dir == DIR_UP) ? : (psnake->dir = DIR_DOWN);
144 break;
145
146 case 'a':
147 case 'A':
148 (psnake->dir == DIR_RIGHT) ? : (psnake->dir = DIR_LEFT);
149 break;
150
151 case 'd':
152 case 'D':
153 (psnake->dir == DIR_LEFT) ? : (psnake->dir = DIR_RIGHT);
154 break;
155
156 case 'q':
157 case 'Q':
158 RUNLOG("Quit Game!");
159 gameover(win, "Quit Game!");
160 return -1;
161
162 default:
163 break;
164 }
165 }
166
167 movesnake(psnake);
168 drawsnakew(win, psnake);
169 switch (checksnake(&pfood, psnake)) {
170 case 0:
171 break;
172
173 case 1:
174 ffood = False;
175 if (++g_level > MAXLEVEL) {
176 RUNLOG("Win!!!");
177 gameover(win, "Win!!!");
178 return -1;
179 }
180 mvwprintw(win, GAMEWIN_YLEN-1, 2, " Level: %d ", g_level);
181 mvwprintw(win, GAMEWIN_YLEN-1, 30, " Speed: %d ", (int)(g_level/3));
182 wrefresh(win);
183 RUNLOG("Level UP!");
184 snakegrowup(&pfood, psnake);
185 break;
186
187 default:
188 RUNLOG("Game over!");
189 gameover(win, "Game over!");
190 return -1;
191 }
192
193 return 1;
194 }
195
196 /**
197 * stuct TSnake是一个倒置的首尾相连的链表,head->front指向snake的尾部
198 * 如: [a]<-[b]<-[c]<-[d] a为head
199 * | ^ snake移动的时候,只用head指向d,
200 * `--------------' 并且修改d的(y,x)为snake头移动到的位置.
201 */
202 void movesnake(struct TSnake *psnake)
203 {
204 int hy = psnake->head->y;
205 int hx = psnake->head->x;
206
207 psnake->head = GetSnakeTail(psnake);
208
209 switch (psnake->dir) {
210 case DIR_UP:
211 psnake->head->y = hy - 1;
212 psnake->head->x = hx;
213 break;
214
215 case DIR_DOWN:
216 psnake->head->y = hy + 1;
217 psnake->head->x = hx;
218 break;
219
220 case DIR_LEFT:
221 psnake->head->y = hy;
222 psnake->head->x = hx - 1;
223 break;
224
225 case DIR_RIGHT:
226 psnake->head->y = hy;
227 psnake->head->x = hx + 1;
228 break;
229
230 default:
231 break;
232 }
233 }
234
235 int checksnake(struct TFood *pfood, struct TSnake *psnake)
236 {
237 if ( psnake->head->y <= 0 || psnake->head->y >= GAMEWIN_YLEN
238 || psnake->head->x <= 0 || psnake->head->x >= GAMEWIN_XLEN)
239 {
240 return -1;
241 }
242
243 struct TSnakeNode *pnode = GetSnakeTail(psnake);
244 int i = 0;
245 for (; i < psnake->length - 1; ++i, pnode = pnode->front)
246 if (psnake->head->y == pnode->y && psnake->head->x == pnode->x)
247 return -1;
248
249 if (psnake->head->y == pfood->y && psnake->head->x == pfood->x)
250 return 1;
251
252 return 0;
253 }
254
255 void snakegrowup(struct TFood *pfood, struct TSnake *psnake)
256 {
257 struct TSnakeNode *pnode = (struct TSnakeNode *)malloc(sizeof(struct TSnakeNode));
258
259 switch (psnake->dir) {
260 case DIR_UP:
261 pnode->y = psnake->head->y - 1;
262 pnode->x = psnake->head->x;
263 break;
264
265 case DIR_DOWN:
266 pnode->y = psnake->head->y + 1;
267 pnode->x = psnake->head->x;
268 break;
269
270 case DIR_LEFT:
271 pnode->y = psnake->head->y;
272 pnode->x = psnake->head->x - 1;
273 break;
274
275 case DIR_RIGHT:
276 pnode->y = psnake->head->y;
277 pnode->x = psnake->head->x + 1;
278 break;
279
280 default:
281 break;
282 }
283
284 pnode->front = GetSnakeTail(psnake);
285 psnake->head->front = pnode;
286 psnake->head = pnode;
287 ++psnake->length;
288 }
289
290 void gameover(WINDOW *win, char *str)
291 {
292 mvwprintw(win, (int)(GAMEWIN_YLEN/2), (GAMEWIN_XLEN/2 - strlen(str)/2), str);
293 mvwprintw(win, (int)(GAMEWIN_YLEN/2 + 1), 20, "Press any key to quit...");
294 wrefresh(win);
295 }
296
297 WINDOW* newgamew()
298 {
299 WINDOW *win = newwin(GAMEWIN_YLEN, GAMEWIN_XLEN, 1, 3);
300 box(win, 0, 0);
301 mvwprintw(win, 0, 2, " GAME ");
302 mvwprintw(win, GAMEWIN_YLEN-1, 2, " Level: %d ", g_level);
303 mvwprintw(win, GAMEWIN_YLEN-1, 30, " Speed: %d ", (int)(g_level/3));
304 wrefresh(win);
305
306 return win;
307 }
308
309 struct TSnake* initsnake()
310 {
311 struct TSnake *psnake = (struct TSnake *)malloc(sizeof(struct TSnake));
312
313 psnake->dir = DIR_LEFT;
314 psnake->length = 4;
315
316 newsnakenode (
317 &newsnakenode (
318 &newsnakenode (
319 &newsnakenode( &psnake->head, 4, 50 )->front, 4, 53
320 )->front, 4, 52
321 )->front, 4, 51
322 )->front = psnake->head;
323
324 return psnake;
325 }
326
327 struct TSnakeNode *newsnakenode(struct TSnakeNode **ppsnode, int y, int x)
328 {
329 *ppsnode = (struct TSnakeNode *)malloc(sizeof(struct TSnakeNode));
330 (*ppsnode)->y = y;
331 (*ppsnode)->x = x;
332 (*ppsnode)->front = NULL;
333
334 return *ppsnode;
335 }
336
337 void destroysnake(struct TSnake *psnake)
338 {
339 struct TSnakeNode *psnode = GetSnakeTail(psnake);
340 struct TSnakeNode *ptmp = NULL;
341
342 int i = 0;
343 for (; i < psnake->length; ++i) {
344 ptmp = psnode;
345 psnode = psnode->front;
346 free(ptmp);
347 }
348
349 free(psnake);
350 psnake = NULL;
351 }
352
353 void drawsnakew(WINDOW *win, struct TSnake *psnake)
354 {
355 static int taily = 0;
356 static int tailx = 0;
357 if (taily != 0 && tailx != 0) {
358 mvwaddch(win, taily, tailx, ' ');
359 }
360
361 struct TSnakeNode *psnode = GetSnakeTail(psnake);
362
363 int i = 0;
364 for (; i < psnake->length; ++i) {
365 mvwaddch(win, psnode->y, psnode->x, SHAPE_SNAKE);
366 psnode = psnode->front;
367 }
368
369 taily = GetSnakeTail(psnake)->y;
370 tailx = GetSnakeTail(psnake)->x;
371
372 wrefresh(win);
373 }
374
375 void drawfoodw(WINDOW *win, struct TFood *pfood, struct TSnake *psnake)
376 {
377 do {
378 pfood->y = random() % (GAMEWIN_YLEN - 1) + 1;
379 pfood->x = random() % (GAMEWIN_XLEN - 1) + 1;
380 } while (False == checkfood(pfood, psnake));
381 checkfood(pfood, psnake);
382
383 mvwaddch(win, pfood->y, pfood->x, SHAPE_FOOD);
384 wrefresh(win);
385 }
386
387 TBool checkfood(struct TFood *pfood, struct TSnake *psnake)
388 {
389 struct TSnakeNode *pnode = GetSnakeTail(psnake);
390
391 int i = 0;
392 for (; i < psnake->length; ++i, pnode = pnode->front)
393 if (pfood->y == pnode->y && pfood->x == pnode->x)
394 return False;
395
396 return True;
397 }
398
399 WINDOW* newlogw()
400 {
401 WINDOW *win = newwin(LOGWIN_YLEN, LOGWIN_XLEN, GAMEWIN_YLEN + 2, 3);
402 box(win, 0, 0);
403 mvwprintw(win, 0, 2, " LOG ");
404 wrefresh(win);
405
406 return win;
407 }
408
409 void runlog(WINDOW *win, char *str)
410 {
411 static char logbuf[LOGBUF_NUM][LOGBUF_LEN] = {0};
412 static int index = 0;
413
414 strcpy(logbuf[index], str);
415
416 int i = 0;
417 for (; i < LOGBUF_NUM; ++i) {
418 cleanline(win, i+1, 1);
419 mvwprintw(win, i+1, 1, logbuf[(index+i) % LOGBUF_NUM]);
420 wrefresh(win);
421 }
422
423 index = (index + LOGBUF_NUM - 1) % LOGBUF_NUM;
424 }
425
426 void cleanline(WINDOW *win, int y, int x)
427 {
428 char EMPTYLINE[LOGBUF_LEN] = {0};
429 memset(EMPTYLINE, ' ', LOGBUF_LEN-1);
430
431 mvwprintw(win, y, x, EMPTYLINE);
432 wrefresh(win);
433 }
我在ubuntu10.04下面测试过。
编译方法:
cc -o snake filename.c -lncurses
评论: 2 查看评论 发表评论
百度期待您的加盟
最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)
编辑推荐:揭秘Facebook背后的那些软件
网站导航:博客园首页 个人主页 新闻 闪存 小组 博问 社区 知识库