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;
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 }
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 }