C++控制台貪吃蛇代碼,控制台貪吃蛇代碼
游戲截圖:

以下是3個代碼文件:
Snake_Class.h文件:
1 #ifndef SNAKE
2 #define SNAKE
3
4 #include<windows.h>
5 #include<vector>
6 #include<string>
7
8 //標記界面和菜單項的ID
9 enum ID_ { ID_1=1, ID_2, ID_3, ID_4, ID_5, ID_6, ID_7 };
10
11 //標記初級,中級,高級三種游戲等級
12 enum Rank_ { first=150, middle=100, high=50 };
13
14
15 //貪吃蛇結構 http://www.cnblogs.com/sosoft/
16 struct Snake_data{
17 bool state ; //標記蛇狀態
18 UINT Snake_size; //標記蛇長度
19 std::vector<COORD> Snake_coord; //蛇的當前坐標
20 COORD food_coord; //食物坐標
21 UINT rank; //標記等級
22 UINT mark; //分數
23 UINT key; //記錄按鍵方向
24 ID_ ID_interface; //標記當前停留界面ID
25 short ID_option ; //標記被選中菜單的ID
26 bool Flag; //標記刷新
27 };
28
29 //貪吃蛇類
30 class Snake_class{
31 public:
32 Snake_class(){}
33 Snake_class(Snake_data *data): pSnake(data){}
34 void ShowMenu(); //顯示菜單
35 void StartGame() ; //開始游戲
36 void ShowPause(); //顯示暫停界面
37 void SaveRecord(); //保存記錄
38 void ShowRank(); //顯示等級
39 void ShowRecord(); //顯示存檔記錄列表
40 bool Read( size_t ); //讀取記錄
41 void ShowArmory(); //顯示英雄榜
42 void Die(); //死亡界面
43 size_t Create_file(); //存儲文件
44 private:
45 void JudgeDie(); //判斷死亡
46 bool Jesus(); //上榜判斷
47 void ShowSnake( COORD& ); //顯示蛇
48 void ShowPointer( COORD,std::string ); //顯示指針
49 void Show_not(); //顯示無數據
50 Snake_data *pSnake;
51 };
52
53
54
55 #endif;
Snake_class.cpp:
1 #include"Snake_Class.h"
2 #include<iostream>
3 #include<fstream>
4 #include<ctime>
5 #include<cstdlib>
6
7 //獲取緩沖區句柄
8 static const HANDLE handle = GetStdHandle( STD_OUTPUT_HANDLE );
9 static CONSOLE_SCREEN_BUFFER_INFO info ;
10 //保存蛇的記錄數據文件
11 static const char *Snake_Record[] = { "d://SnakeRecord//Snake1.txt",
12 "d://SnakeRecord//Snake2.txt",
13 "d://SnakeRecord//Snake3.txt",
14 "d://SnakeRecord//Snake4.txt",
15 "d://SnakeRecord//Snake5.txt" };
16
17 static const char *S_Armory[] = { "d://SnakeRecord//Armory1.txt",
18 "d://SnakeRecord//Armory2.txt",
19 "d://SnakeRecord//Armory3.txt" };
20 //顯示主菜單(完成已測試)
21 void Snake_class::ShowMenu(){
22 //獲取緩沖區相關信息
23 GetConsoleScreenBufferInfo( handle, &info );
24 char *str[] = {"開 始 游 戲",
25 "難 度 等 級",
26 "讀 取 存 檔",
27 "英 雄 榜",
28 "退 出 游 戲"};
29 //輸出菜單選項
30 short y = 3;
31 COORD cd = { info.srWindow.Right/2 - 5, y };
32 for( size_t n=0;n<sizeof(str)/sizeof(*str);++n ){
33 SetConsoleCursorPosition( handle, cd );
34 std::cout<<*(str+n);
35 cd.Y += 2;
36 }
37 //判斷指針指向哪個菜單選項
38 cd.X -= 2;
39 cd.Y = y;
40 switch( pSnake->ID_option ){
41 case ID_1:
42 break;
43 case ID_2:
44 cd.Y = y+2; break;
45 case ID_3:
46 cd.Y = y+4; break;
47 case ID_4:
48 cd.Y = y+6; break;
49 case ID_5:
50 cd.Y = y+8; break;
51 }
52 ShowPointer( cd,pSnake->Flag?std::string(" "):std::string("><") );
53 }
54
55 //開始游戲(完成待測試)
56 void Snake_class::StartGame(){
57 COORD cd;
58 //判斷是否已有食物
59 if( !pSnake->food_coord.X ){
60 srand((unsigned int)time(NULL));
61 while(1){
62 //限制食物出現的坐標不與圍牆相同
63 ++( cd.X = rand()%78 );
64 ++( cd.Y = rand()%18 );
65 //判斷食物坐標是否與蛇身吻合
66 std::vector<COORD>::iterator ite;
67 for( ite=pSnake->Snake_coord.begin(); ite!=pSnake->Snake_coord.end(); ++ite ){
68 if( ite->X == cd.X && ite->Y == cd.Y )
69 break;
70 }
71 if( ite == pSnake->Snake_coord.end() ){
72 pSnake->food_coord.X = cd.X ;
73 pSnake->food_coord.Y = cd.Y ;
74 break;
75 }
76 }
77 }
78 SetConsoleCursorPosition( handle, pSnake->food_coord );
79 std::cout<<"*";
80 //判定按鍵方向
81 cd.X = pSnake->Snake_coord.begin()->X;
82 cd.Y = pSnake->Snake_coord.begin()->Y ;
83 switch( pSnake->key ){
84 case VK_UP:
85 --cd.Y; break;
86 case VK_DOWN:
87 ++cd.Y; break;
88 case VK_LEFT:
89 --cd.X; break;
90 case VK_RIGHT:
91 ++cd.X; break;
92 }
93 ShowSnake( cd );
94 JudgeDie();
95 }
96
97 //顯示暫停界面(完成已測試)
98 void Snake_class::ShowPause(){
99 COORD cd = { info.srWindow.Right/2-10, info.srWindow.Bottom/5 };
100 SetConsoleCursorPosition( handle, cd );
101 std::cout<<"游 戲 暫 停 中 ......";
102 char *str[] = { "繼 續 游 戲",
103 "保 存 游 戲",
104 "退 出 游 戲" };
105 //輸出菜單選項
106 short X = info.srWindow.Right/3;
107 cd.X = X/2-5 ;
108 cd.Y = info.srWindow.Bottom/3*2-4;
109 for( size_t i=0;i<sizeof(str)/sizeof(*str);++i ){
110 SetConsoleCursorPosition( handle, cd );
111 std::cout<<*(str+i);
112 cd.X += X;
113 }
114
115 //判斷指針應指向的菜單選項
116 switch( pSnake->ID_option ){
117 case ID_1:
118 cd.X = X/2-7; break;
119 case ID_2:
120 cd.X = X/2+X-7; break;
121 case ID_3:
122 cd.X = X/2+2*X-7; break;
123 }
124 ShowPointer( cd,pSnake->Flag?std::string(" "):std::string("><") );
125 }
126
127 //保存記錄(完成未測試)
128 void Snake_class::SaveRecord(){
129 std::ofstream outopen;
130 outopen.open( *( Snake_Record + Create_file() ) );
131 if( !outopen ){
132 std::cerr<<"\n打開文件失敗!\n";
133 exit(0);
134 }
135 //保存記錄到文件中,前面加"0"是為了後面檢測是否文件為空使用
136 outopen<<"0 "<<pSnake->Snake_size<<" ";
137 for(std::vector<COORD>::iterator ite=pSnake->Snake_coord.begin();
138 ite!=pSnake->Snake_coord.end();++ite )
139 outopen<<ite->X<<" "<<ite->Y<<" ";
140 outopen<<pSnake->rank<<" "<<pSnake->mark<<" "<<pSnake->key;
141 outopen.close();
142 //輸出保存成功
143 COORD cd = { info.srWindow.Right/2-4, info.srWindow.Bottom/3*2-1 };
144 SetConsoleCursorPosition( handle, cd );
145 std::cout<<"保存成功!\a";
146 }
147
148 //顯示等級(已測試)
149 void Snake_class::ShowRank(){
150 COORD cd = { info.srWindow.Right/2-6, info.srWindow.Bottom/3+2 };
151 char *str[] = { "初 級",
152 "中 級",
153 "高 級" };
154 for( size_t i=0;i<sizeof(str)/sizeof(*str);++i ){
155 SetConsoleCursorPosition( handle, cd );
156 std::cout<<*(str+i);
157 cd.Y += 2;
158 }
159 //判斷指針所停留的選項
160 cd.X -= 2;
161 cd.Y = info.srWindow.Bottom/3+2;
162 switch( pSnake->ID_option ){
163 case ID_1:
164 break;
165 case ID_2:
166 cd.Y += 2; break;
167 case ID_3:
168 cd.Y += 4; break;
169 }
170 ShowPointer( cd,pSnake->Flag?std::string(" "):std::string("><") );
171 }
172
173 //顯示存檔記錄(已測試)
174 void Snake_class::ShowRecord(){
175 COORD cd = { info.srWindow.Right/2-12, 8 };
176 //輸出記錄
177 std::ifstream inopen;
178 SetConsoleCursorPosition( handle, cd );
179 for( size_t i=0;i<sizeof(Snake_Record)/sizeof(*Snake_Record);++i ){
180 inopen.open( *(Snake_Record+i) );
181 if( !inopen || (inopen.get() == EOF && i==0) ){
182 Show_not();
183 pSnake->ID_option = ID_7;//第7個選項標記,在按回車時檢測下
184 return;
185 }
186 if( inopen.get() != EOF ){
187 UINT _rank, _mark;
188 inopen>>_mark;
189 ++(_mark *= 2);
190 while( _mark-- )
191 inopen>>_rank;
192 inopen>>_mark;
193 switch( _rank ){
194 case first:
195 std::cout<<"初級"; break;
196 case middle:
197 std::cout<<"中級"; break;
198 case high:
199 std::cout<<"高級"; break;
200 }
201 std::cout<<"\t\t\t "<<_mark;
202 }else
203 std::cout<<" ---\t\t\t ---";
204
205 cd.Y += 2;
206 SetConsoleCursorPosition( handle, cd );
207 inopen.close();
208 inopen.clear();//重置流狀態
209 }
210 std::cout<<"\t 返 回 菜 單";
211 cd.X = info.srWindow.Right/2-4;
212 cd.Y = 4;
213 SetConsoleCursorPosition( handle, cd );
214 std::cout<<"存 檔 記 錄";
215 cd.X -=10;
216 cd.Y +=2;
217 SetConsoleCursorPosition( handle, cd );
218 std::cout<<"游戲等級\t\t當前分數";
219 //輸出指針
220 cd.X = info.srWindow.Right/2-14;
221 cd.Y = 8;
222 switch( pSnake->ID_option ){
223 case ID_1:
224 break;
225 case ID_2:
226 cd.Y +=2; break;
227 case ID_3:
228 cd.Y +=4; break;
229 case ID_4:
230 cd.Y +=6; break;
231 case ID_5:
232 cd.Y +=8; break;
233 case ID_6:
234 cd.Y +=10;break;
235 }
236 ShowPointer( cd,pSnake->Flag?std::string(" "):std::string("><") );
237 }
238
239 //讀取記錄
240 bool Snake_class::Read( size_t i ){
241 std::ifstream inopen( *(Snake_Record+i) );
242 if( inopen.get() == EOF ){
243 std::cout<<"\a";
244 inopen.close();
245 return false;
246 }
247 inopen>>pSnake->Snake_size;
248 COORD cd;
249 pSnake->Snake_coord.clear();
250 for( int n=1;n<=pSnake->Snake_size;++n ){
251 inopen>>cd.X>>cd.Y ;
252 pSnake->Snake_coord.push_back( cd );
253 }
254 inopen>>pSnake->rank>>pSnake->mark>>pSnake->key;
255 inopen.close();
256 inopen.clear();
257 return true;
258 }
259
260 //顯示英雄榜(未測試)
261 void Snake_class::ShowArmory(){
262 short nt=0;
263 COORD cd = { info.srWindow.Right/3, info.srWindow.Bottom/3 };
264 std::ifstream inopen;
265 for( size_t i=0;i<sizeof(S_Armory)/sizeof(*S_Armory);++i ){
266 UINT _rank=0, _mark=0;
267 inopen.open( *(S_Armory+i) );
268 if( !inopen ){
269 ++nt;
270 continue;
271 }
272 inopen>>_rank>>_mark;
273 switch( _rank ){
274 case first:
275 SetConsoleCursorPosition( handle, cd );
276 std::cout<<"小牛 :初級\t\t "<<_mark;
277 break;
278 case middle:
279 cd.Y +=2;
280 SetConsoleCursorPosition( handle, cd );
281 std::cout<<"中牛 :中級\t\t "<<_mark;
282 break;
283 case high:
284 cd.Y +=2;
285 SetConsoleCursorPosition( handle, cd );
286 std::cout<<"大牛 :高級\t\t "<<_mark;
287 break;
288 }
289 inopen.close();
290 inopen.clear();
291 }
292 if( nt == 3 ){
293 Show_not();
294 return;
295 }
296 cd.X = info.srWindow.Right/2-3;
297 cd.Y = 4;
298 SetConsoleCursorPosition( handle, cd );
299 std::cout<<"英 雄 榜";
300 cd.X -=10;
301 cd.Y +=2;
302 SetConsoleCursorPosition( handle,cd );
303 std::cout<<"\t等 級\t\t分 數";
304 cd.Y = info.srWindow.Bottom-7;
305 SetConsoleCursorPosition( handle, cd );
306 std::cout<<"按回車返回主菜單........";
307 }
308
309 //死亡界面(未測試)
310 void Snake_class::Die(){
311 COORD cd = { info.srWindow.Right/2-10, info.srWindow.Bottom/5 };
312 SetConsoleCursorPosition( handle, cd );
313 std::cout<<" 您 已 x_x 了 !";
314 char *str[] = { "返 回 菜 單",
315 "退 出 游 戲" };
316 //輸出菜單選項
317 short X = info.srWindow.Right/2;
318 cd.X = X/2-5 ;
319 cd.Y = info.srWindow.Bottom/3*2-4;
320 for( size_t i=0;i<sizeof(str)/sizeof(*str);++i ){
321 SetConsoleCursorPosition( handle, cd );
322 std::cout<<*(str+i);
323 cd.X += X;
324 }
325
326 //判斷指針應指向的菜單選項
327 switch( pSnake->ID_option ){
328 case ID_1:
329 cd.X = X/2-7; break;
330 case ID_2:
331 cd.X = X/2+X-7; break;
332 }
333 ShowPointer( cd,pSnake->Flag?std::string(" "):std::string("><") );
334 if( Jesus() ){
335 cd.X = X/2;
336 cd.Y = info.srWindow.Bottom/3;
337 SetConsoleCursorPosition( handle, cd );
338 std::cout<<"喲...這分? ╮(╯▽╰)╭ 也能上榜。。。!";
339 cd.Y +=2;
340 SetConsoleCursorPosition( handle, cd );
341 std::cout<<"上榜等級:";
342 switch( pSnake->rank ){
343 case first:
344 std::cout<<"初級"; break;
345 case middle:
346 std::cout<<"中級"; break;
347 case high:
348 std::cout<<"高級"; break;
349 }
350 std::cout<<"\t上榜分數:"<<pSnake->mark;
351 }
352 }
353
354 //存儲記錄文件(完成未測試)
355 size_t Snake_class::Create_file(){
356 std::ifstream inopen;
357 size_t fn=0, fc=0, iend = sizeof(Snake_Record)/sizeof(*Snake_Record);
358 //判斷文件是否存在或文件已被存滿
359 for( size_t i=0;i<iend;++i ){
360 inopen.open( *(Snake_Record+i) );
361 if( !inopen ) ++fn;
362 else if( inopen.get() == EOF ){
363 inopen.close();
364 return i;
365 }
366 else { ++fc; inopen.close(); }
367 }
368 if( fn == iend || fc == iend ){
369 std::ofstream outopen;
370 //創建文本
371 for( size_t i=0;i<iend;++i ){
372 outopen.open( *(Snake_Record+i) );
373 outopen.close();
374 }
375 }
376 //返回打開成功的文件索引
377 return 0 ;
378 }
379
380 //判斷死亡(未測試)
381 void Snake_class::JudgeDie(){
382 std::vector<COORD>::iterator hbeg = pSnake->Snake_coord.begin(),
383 beg = hbeg+1;
384 while( beg != pSnake->Snake_coord.end() ){
385 if( beg->X == hbeg->X && beg->Y == hbeg->Y ){
386 pSnake->state = FALSE;
387 return;
388 }
389 ++beg;
390 }
391 COORD cd;
392 if(hbeg->X <= 0 || hbeg->Y <= 0 ||
393 hbeg->X >=info.srWindow.Right || hbeg->Y >= info.srWindow.Bottom-5 ){
394 if( pSnake->Snake_size < 40 ){
395 pSnake->state = FALSE;
396 return;
397 }
398 //如果達到了40級可以穿牆
399 switch( pSnake->key ){
400 case VK_UP:
401 cd.X = pSnake->Snake_coord.begin()->X ;
402 cd.Y = info.srWindow.Bottom-6;
403 break;
404 case VK_DOWN:
405 cd.X = pSnake->Snake_coord.begin()->X ;
406 cd.Y = 1;
407 break;
408 case VK_LEFT:
409 cd.X = info.srWindow.Right-1;
410 cd.Y = pSnake->Snake_coord.begin()->Y ;
411 break;
412 case VK_RIGHT:
413 cd.X = 1;
414 cd.Y = pSnake->Snake_coord.begin()->Y ;
415 break;
416 }
417 ShowSnake( cd );
418 }
419 }
420
421 //上榜判斷(未測試)
422 bool Snake_class::Jesus(){
423 std::ifstream inopen;
424 size_t i;
425 //判斷相應等級打開相應文件
426 switch( pSnake->rank ){
427 case first:
428 i=0; break;
429 case middle:
430 i=1; break;
431 case high:
432 i=2; break;
433 }
434 inopen.open( *(S_Armory+i) );
435 if( inopen ){
436 UINT _mark;
437 inopen>>_mark>>_mark;
438 if( _mark >= pSnake->mark ){
439 inopen.close();
440 return FALSE;
441 }
442 }
443 std::ofstream outopen( *(S_Armory+i) );//創建文件並輸入
444 if( !outopen ){
445 std::cerr<<"打開英雄榜文件出錯"<<std::endl;
446 exit(0);
447 }
448 outopen<<pSnake->rank<<" "<<pSnake->mark;
449 outopen.close();
450 return TRUE;
451 }
452 //顯示蛇(未測試)
453 void Snake_class::ShowSnake( COORD& cd){
454 if( cd.X == pSnake->food_coord.X && cd.Y == pSnake->food_coord.Y ){
455 //在最後添加一個坐標
456 pSnake->Snake_coord.push_back( *(pSnake->Snake_coord.rbegin()) );
457 pSnake->food_coord.X = pSnake->food_coord.Y = 0;//標志食物已被吃掉
458 ++pSnake->mark;
459 ++pSnake->Snake_size;
460 }
461 COORD cod;
462 cod.X = (pSnake->Snake_coord.rbegin())->X ;
463 cod.Y = (pSnake->Snake_coord.rbegin())->Y ;
464 std::vector<COORD>::reverse_iterator rbeg = pSnake->Snake_coord.rbegin();
465 while( rbeg != pSnake->Snake_coord.rend()-1 ){
466 rbeg->X = (rbeg+1)->X ;
467 rbeg->Y = (rbeg+1)->Y ;
468 ++rbeg;
469 }
470 //顯示蛇
471 pSnake->Snake_coord.begin()->X = cd.X ;
472 pSnake->Snake_coord.begin()->Y = cd.Y ;
473 for( std::vector<COORD>::iterator beg = pSnake->Snake_coord.begin();
474 beg != pSnake->Snake_coord.end();++beg ){
475 SetConsoleCursorPosition( handle, *beg );
476 std::cout<<"*";
477 }
478 SetConsoleCursorPosition( handle,cod );
479 std::cout<<" ";
480 }
481
482 //顯示指針(完成)
483 inline void Snake_class::ShowPointer( COORD cd,std::string str ){
484 SetConsoleCursorPosition( handle, cd );
485 std::cout<<str[0];
486 pSnake->ID_interface != ID_6?cd.X += 14:cd.X = info.srWindow.Right/3*2+3;
487 SetConsoleCursorPosition( handle, cd );
488 std::cout<<str[1];
489 }
490
491 //顯示無數據(完成)
492 inline void Snake_class::Show_not(){
493 COORD cd = { info.srWindow.Right/2-4 ,info.srWindow.Bottom/2 };
494 SetConsoleCursorPosition( handle, cd );
495 std::cout<<"無 數 據 !";
496 cd.X -= 6;
497 cd.Y += 2;
498 SetConsoleCursorPosition( handle, cd );
499 std::cout<<"請按回車返回主菜單......";
500 }
main.cpp :
1 #include<iostream>
2 #include<direct.h>
3 #include"Snake_Class.h"
4
5 #define _max(ID) --snake.ID_option < ID_1?ID : snake.ID_option
6 #define _min(ID) ++snake.ID_option > ID?ID_1 : snake.ID_option
7
8 //鉤子過程
9 LRESULT CALLBACK _HookProc(int,WPARAM,LPARAM);
10
11 void Wall(); //畫牆函數
12 void Frame(); //畫框函數
13 void initialize_();//初始化蛇結構數據
14
15 Snake_data snake;
16 Snake_class csnake(&snake);
17 static HANDLE handle; //控制台句柄
18 //控制台信息結構
19 static CONSOLE_SCREEN_BUFFER_INFO info ;
20
21 int main(){
22 using namespace std;
23 //獲取輸出緩沖區句柄
24 handle = GetStdHandle(STD_OUTPUT_HANDLE);
25 //獲取相關信息(主要是緩沖區大小)
26 GetConsoleScreenBufferInfo( handle, &info );
27 initialize_();
28 _mkdir( "d://SnakeRecord" ); //創建目錄
29
30 CONSOLE_CURSOR_INFO cursor; //光標結構
31 cursor.dwSize = 10;
32 cursor.bVisible = 0; //0為隱藏光標
33 SetConsoleCursorInfo(handle, &cursor);//設置隱藏光標函數
34
35 //csnake.ShowMenu();
36 HHOOK hook;
37 MSG msg;
38 //相應的鉤子有相應的過程函數MSDN中可看,安裝鍵盤鉤子
39 hook = SetWindowsHookEx(WH_KEYBOARD_LL,_HookProc,GetModuleHandle(NULL),0);
40 while(1){
41 //判斷蛇是否還活著
42 Wall();
43 if( !snake.state && snake.ID_interface == ID_2 ){
44 //csnake.Die();
45 snake.ID_interface = ID_4;
46 Frame();
47 }
48 if( snake.ID_interface == ID_2 ){
49 csnake.StartGame();
50 Sleep( snake.rank );
51 }
52 if( PeekMessage(&msg,NULL,0,0,PM_REMOVE) ){//循環接收消息
53 TranslateMessage(&msg);
54 DispatchMessage(&msg);
55 }
56 }
57
58 UnhookWindowsHookEx( hook ); //卸載鉤子
59 return 0;
60 }
61
62 //定義鉤子過程(未完成)
63 LRESULT CALLBACK _HookProc(int message, WPARAM wParam, LPARAM lParam){
64 //判斷是否彈起按鍵消息
65 if( wParam == WM_KEYUP){
66 bool state = true;
67 switch(((LPKBDLLHOOKSTRUCT) lParam)->vkCode){//lParam:指向一個結構
68 //按下上鍵
69 case VK_UP:
70 switch( snake.ID_interface ){
71 case ID_1:
72 snake.Flag = true;
73 csnake.ShowMenu();
74 snake.Flag = false;
75 snake.ID_option = _max( ID_5 );
76 csnake.ShowMenu();
77 break;
78 case ID_2:
79 if( snake.key != VK_DOWN && snake.key != VK_UP ){
80 snake.key = VK_UP;
81 }
82 break;
83 case ID_5:
84 snake.Flag = true;
85 csnake.ShowRank();
86 snake.ID_option = _max( ID_3 );
87 snake.Flag = false;
88 csnake.ShowRank();
89 break;
90 case ID_6:
91 snake.Flag = true;
92 csnake.ShowRecord();
93 snake.ID_option = _max( ID_6 );
94 snake.Flag = false;
95 csnake.ShowRecord();
96 break;
97 }
98 break;
99 //按下下鍵
100 case VK_DOWN:
101 switch( snake.ID_interface ){
102 case ID_1:
103 snake.Flag = true;
104 csnake.ShowMenu();
105 snake.Flag = false;
106 snake.ID_option = _min( ID_5 );
107 csnake.ShowMenu();
108 break;
109 case ID_2:
110 if( snake.key != VK_UP && snake.key != VK_DOWN ){
111 snake.key = VK_DOWN;
112 }
113 break;
114 case ID_5:
115 snake.Flag = true;
116 csnake.ShowRank();
117 snake.ID_option = _min( ID_3 );
118 snake.Flag = false;
119 csnake.ShowRank();
120 break;
121 case ID_6:
122 snake.Flag = true;
123 csnake.ShowRecord();
124 snake.ID_option = _min( ID_6 );
125 snake.Flag = false;
126 csnake.ShowRecord();
127 break;
128 }
129 break;
130 //按下左鍵
131 case VK_LEFT:
132 switch( snake.ID_interface ){
133 case ID_2:
134 if( snake.key != VK_RIGHT && snake.key != VK_LEFT ){
135 snake.key = VK_LEFT;
136 }
137 break;
138 case ID_3:
139 snake.Flag = true;
140 csnake.ShowPause();
141 snake.ID_option = _max( ID_3 );
142 snake.Flag = false;
143 csnake.ShowPause();
144 break;
145 case ID_4:
146 snake.Flag = true;
147 csnake.Die();
148 snake.ID_option = _max( ID_2 );
149 snake.Flag = false;
150 csnake.Die();
151 break;
152 }
153 break;
154 //按下右鍵
155 case VK_RIGHT:
156 switch( snake.ID_interface ){
157 case ID_2:
158 if( snake.key != VK_LEFT && snake.key != VK_RIGHT ){
159 snake.key = VK_RIGHT;
160 }
161 break;
162 case ID_3:
163 snake.Flag = true;
164 csnake.ShowPause();
165 snake.ID_option = _min( ID_3 );
166 snake.Flag = false;
167 csnake.ShowPause();
168 break;
169 case ID_4:
170 snake.Flag = true;
171 csnake.Die();
172 snake.ID_option = _min( ID_2 );
173 snake.Flag = false;
174 csnake.Die();
175 break;
176 }
177 break;
178 //按下空格和回車鍵
179 case VK_SPACE:
180 case VK_RETURN:
181 system( "cls" );
182 switch( snake.ID_interface ){
183 case ID_1://主菜單界面
184 switch( snake.ID_option ){
185 case ID_1:
186 snake.ID_interface = ID_2;//開始游戲界面ID
187 csnake.StartGame();
188 break;
189 case ID_2:
190 snake.ID_interface = ID_5;//等級界面
191 snake.ID_option = ID_1;
192 Frame();
193 //csnake.ShowRank();
194 break;
195 case ID_3:
196 snake.ID_interface = ID_6;//讀取記錄界面
197 snake.ID_option = ID_1;
198 csnake.ShowRecord();
199 break;
200 case ID_4:
201 snake.ID_interface = ID_7;//英雄榜界面
202 csnake.ShowArmory();
203 break;
204 case ID_5:
205 state = false;
206 break;
207 }
208 break;
209
210 case ID_2://游戲界面
211 snake.ID_interface = ID_3;
212 snake.ID_option = ID_1;
213 Frame();
214 //csnake.ShowPause();
215 break;
216
217 case ID_3://暫停界面
218 switch( snake.ID_option ){
219 case ID_1:
220 snake.ID_interface = ID_2;
221 csnake.StartGame();
222 break;
223 case ID_2:
224 csnake.SaveRecord();
225 break;
226 case ID_3:
227 state = false;
228 break;
229 }
230 break;
231
232 case ID_4://死亡界面
233 switch( snake.ID_option ){
234 case ID_1:
235 snake.ID_interface = ID_1;
236 snake.ID_option = ID_1;
237 initialize_();
238 csnake.ShowMenu();
239 break;
240 case ID_2:
241 state = false;
242 break;
243 }
244 break;
245
246 case ID_5://等級界面
247 switch( snake.ID_option ){
248 case ID_1:
249 snake.rank = first;
250 break;
251 case ID_2:
252 snake.rank = middle;
253 break;
254 case ID_3:
255 snake.rank = high;
256 break;
257 }
258 snake.ID_interface = ID_1;
259 snake.ID_option = ID_1;
260 csnake.ShowMenu();
261 break;
262
263 case ID_6://讀取界面
264 size_t id;
265 switch( snake.ID_option ){
266 case ID_1:
267 id = 0; break;
268 case ID_2:
269 id = 1; break;
270 case ID_3:
271 id = 2; break;
272 case ID_4:
273 id = 3; break;
274 case ID_5:
275 id = 4; break;
276 }
277 //進行讀取文件
278 if( snake.ID_option != ID_6&&snake.ID_option != ID_7 ){
279 initialize_();
280 if( csnake.Read( id ) ){
281 snake.ID_interface = ID_2;
282 csnake.StartGame();
283 }
284 else snake.ID_interface = ID_6;
285 }
286 else {
287 snake.ID_interface = ID_1;
288 snake.ID_option = ID_1;
289 csnake.ShowMenu();
290 }
291 break;
292
293 case ID_7://英雄榜界面
294 snake.ID_interface = ID_1;
295 snake.ID_option = ID_1;
296 csnake.ShowMenu();
297 break;
298 }
299 if( !state ){
300 COORD cd = { info.srWindow.Right/4, info.srWindow.Bottom/5*4 };
301 SetConsoleCursorPosition( handle,cd );
302 exit(0);
303 }
304 snake.ID_option = ID_1;
305 break;
306 }
307 }
308 //消息傳給下個鉤子
309 return CallNextHookEx ( NULL, message, wParam, lParam );
310 }
311
312 //畫牆函數和調用相應界面(已測試完成)
313 void Wall(){
314 short i;
315 COORD coord = { 0,0 }; //坐標結構
316 //繪牆
317 SetConsoleCursorPosition( handle, coord );
318 for( i=0;i<=info.srWindow.Right;++i )
319 std::cout<<"#";
320
321 coord.X = info.srWindow.Right;
322 coord.Y = 1;
323 for( i=1;i<info.srWindow.Bottom;++i ){
324 SetConsoleCursorPosition( handle, coord );
325 std::cout<<"#";
326 ++coord.Y ;
327 }
328
329 coord.X = 0;
330 coord.Y = info.srWindow.Bottom;
331 for( i=1;i<=info.srWindow.Right;++i ){
332 SetConsoleCursorPosition( handle, coord );
333 std::cout<<"#";
334 ++coord.X ;
335 }
336
337 coord.X = 0;
338 coord.Y = 1;
339 for( i=1;i<info.srWindow.Bottom;++i ){
340 SetConsoleCursorPosition( handle, coord );
341 std::cout<<"#";
342 ++coord.Y ;
343 }
344 //判斷所在界面顯示相關界面的菜單選項及其它
345 int j = info.srWindow.Right/4;
346 switch( snake.ID_interface ){
347 case ID_1:
348 csnake.ShowMenu();
349 coord.X = j;
350 coord.Y = info.srWindow.Bottom-6;
351 SetConsoleCursorPosition( handle, coord );
352 std::cout<<"o(-\"-)o 貪 #^_^# 吃 →_→ 蛇 \\(^o^)/";
353 break;//顯示菜單選項
354
355 case ID_2:
356 case ID_3:
357 case ID_4:
358 //繪輸出信息框
359 coord.X = 1;
360 coord.Y = info.srWindow.Bottom - 5;
361 SetConsoleCursorPosition( handle, coord );
362 for( i=1;i<info.srWindow.Right; std::cout<<"#", ++i );
363 for( coord.X=j;coord.X<=info.srWindow.Right-j;coord.X+=j ){
364 coord.Y = info.srWindow.Bottom - 5;
365 for( i=coord.Y;i<info.srWindow.Bottom;++i ){
366 SetConsoleCursorPosition( handle, coord );
367 std::cout<<"#";
368 ++coord.Y ;
369 }
370 }
371 //輸出每個框的信息
372 coord.X = 2;
373 coord.Y-= 4;
374 SetConsoleCursorPosition( handle, coord );
375 std::cout<<"游戲難度:";
376 coord.Y +=2;
377 SetConsoleCursorPosition( handle, coord );
378 std::cout<<"\t ";
379 switch( snake.rank ){
380 case first:
381 std::cout<<"初 級"; break;
382 case middle:
383 std::cout<<"中 級"; break;
384 case high:
385 std::cout<<"高 級"; break;
386 }
387 //當前分數
388 coord.X += j;
389 coord.Y -= 2;
390 SetConsoleCursorPosition( handle, coord );
391 std::cout<<" 當 前 分 數";
392 coord.X +=j/2-3;
393 coord.Y +=2;
394 SetConsoleCursorPosition( handle, coord );
395 std::cout<<snake.mark ;
396 //操作說明
397 coord.X = j*2+1;
398 coord.Y = info.srWindow.Bottom -4;
399 SetConsoleCursorPosition( handle, coord );
400 std::cout<<" 操作說明: ";
401 coord.Y +=2;
402 SetConsoleCursorPosition( handle, coord );
403 std::cout<<" ↑ ↓ ← →";
404 ++coord.Y;
405 SetConsoleCursorPosition( handle, coord );
406 std::cout<<" 空格: 暫停游戲";
407 //制作人
408 coord.X += j;
409 SetConsoleCursorPosition( handle, coord );
410 std::cout<<"\t制作人: _ 翼";
411 break;
412
413 case ID_5:
414 csnake.ShowRank(); break;//顯示游戲等級
415
416 case ID_6:
417 csnake.ShowRecord(); break;//顯示存檔記錄
418
419 case ID_7:
420 csnake.ShowArmory(); break;//顯示英雄榜
421 }
422
423 }
424
425 //畫框函數(完成)
426 void Frame(){
427 COORD coord = { 0, info.srWindow.Bottom/3 };
428 SetConsoleCursorPosition( handle, coord );
429 for( short i=0;i<=info.srWindow.Right; std::cout<<"-", ++i );
430
431 coord.Y = info.srWindow.Bottom/3*2;
432 SetConsoleCursorPosition( handle, coord );
433 for( short i=0;i<=info.srWindow.Right; std::cout<<"-", ++i );
434
435 switch( snake.ID_interface ){
436 case ID_3:
437 csnake.ShowPause(); break;//顯示暫停菜單
438 case ID_4:
439 csnake.Die(); break;//顯示死亡界面菜單
440 case ID_5:
441 csnake.ShowRank(); break;//顯示等級選項
442 }
443 }
444
445 //初始化蛇數據(完成)
446 void initialize_(){
447 snake.state = true; //蛇狀態
448 snake.Snake_size = 5; //蛇初始化長度
449 //初始化蛇位置
450 COORD cd;
451 cd.Y = 3;
452 snake.Snake_coord.clear();
453 for( size_t i=10;i>5;--i ){
454 cd.X = i;
455 snake.Snake_coord.push_back( cd );
456 }
457 snake.food_coord.X = 0;
458 snake.food_coord.Y = 0;
459 snake.rank = first; //默認等級
460 snake.mark = 0; //分數
461 snake.key = VK_RIGHT;
462 snake.ID_interface = ID_1;//界面標記
463 snake.ID_option = ID_1; //選項標記
464 snake.Flag = false;
465 }