C++控制檯貪吃蛇程式碼
阿新 • • 發佈:2018-12-11
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" }; 1617 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 }else203 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.c