作者: 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 /**
2
* Snake
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
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