C++ vector容器實現貪吃蛇小遊戲
阿新 • • 發佈:2020-02-25
本文例項為大家分享了C++ vector容器 實現貪吃蛇,供大家參考,具體內容如下
使用vector容器實現貪吃蛇簡化了很多繁瑣操作,且相比之前我的程式碼已經做到了儘量的簡潔
技術環節:
編譯環境:windows VS2019
需求:
控制貪吃蛇吃食物,吃到一個食物蛇身變長一節,得分增加,撞牆或撞自己則遊戲結束。
思路:
建立一個vector容器,容器記憶體儲蛇的每節身體的結構變數,結構變數中儲存蛇身體的xy座標,通過使用vector成員方法不斷新增和刪除容器中的資料,實現蛇座標的規律移動,吃到食物等時執行對應操作。
在程式碼註釋中標註了每一步是怎麼實現的。
注意:
由於編譯器原因程式中_kbhit()和_getch()函式可能在其他編譯器上編譯會出現錯誤,解決辦法是去掉函式前面的“_”。
執行效果:
#include <iostream> #include <vector> #include <windows.h> #include <conio.h> #include <ctime> using namespace std; void gotoxy(int x,int y); //游標定位 //食物類 class Food { private: int m_x; int m_y; public: void randfood() //隨機產生一個食物 { srand((int)time(NULL)); L1: m_x = rand() % (85) + 2; m_y = rand() % (25) + 2; if (m_x % 2) //如果食物的x座標不是偶數則重新確定食物的座標 goto L1; gotoxy(m_x,m_y); //在確認好的位置輸出食物 cout << "★"; } int getFoodm_x() //返回食物的x座標 { return m_x; } int getFoodm_y() //返回食物的y座標 { return m_y; } }; //蛇類 class Snake { private: //蛇座標結構 struct Snakecoor { int x; int y; }; //蛇容器 vector<Snakecoor> snakecoor; //判斷和改變方向函式 void degdir(Snakecoor& nexthead) //引數:新蛇頭結構變數、蛇座標容器 { static char key = 'd'; //靜態變數防止改變移動方向後重新改回來 if (_kbhit()) //改變蛇前進的方向 { char temp = _getch(); switch (temp) //如果臨時變數的值為wasd中的一個,則賦值給key { default: break; case 'w': case 'a': case 's': case 'd': //如果temp的方向和key的方向不相反則賦值 if ((key == 'w' && temp != 's') || (key == 's' && temp != 'w') || \ (key == 'a' && temp != 'd') || (key == 'd' && temp != 'a')) key = temp; } } switch (key) //根據key的值確定蛇的移動方向 { case 'd': nexthead.x = snakecoor.front().x + 2; //新的蛇頭的頭部等於容器內第一個資料(舊蛇頭)x座標+2 nexthead.y = snakecoor.front().y; break; case 'a': nexthead.x = snakecoor.front().x - 2; nexthead.y = snakecoor.front().y; break; case 'w': nexthead.x = snakecoor.front().x; nexthead.y = snakecoor.front().y - 1; break; case 's': nexthead.x = snakecoor.front().x; nexthead.y = snakecoor.front().y + 1; } } //遊戲結束時需要做的事情 void finmatt(const int score) { system("cls"); gotoxy(40,14); cout << "遊戲結束"; gotoxy(40,16); cout << "得分:" << score; gotoxy(0,26); exit(0); } //遊戲結束的情況 void finishgame(const int score) { //撞牆情況 if (snakecoor[0].x >= 88 || snakecoor[0].x < 0 || snakecoor[0].y >= 28 || snakecoor[0].y < 0) finmatt(score); //撞到自己情況 for (int i = 1; i < snakecoor.size(); i++) if (snakecoor[0].x == snakecoor[i].x && snakecoor[0].y == snakecoor[i].y) finmatt(score); } public: //構造初始化蛇的位置 Snake() { Snakecoor temp; //臨時結構變數用於建立蛇 for (int i = 5; i >= 0; i--) //反向建立初始蛇身,初始蛇頭朝東 { temp.x = 16 + (i << 1); //偶數 temp.y = 8; snakecoor.push_back(temp); } } //蛇運動主要函式 void move(Food& food,int& score) { Snakecoor nexthead; //新蛇頭變數 degdir(nexthead); //判斷和改變蛇前進的方向 snakecoor.insert(snakecoor.begin(),nexthead); //將新的蛇頭插入容器頭部 gotoxy(0,0); cout << "得分:" << score; //每次移動都在左上角重新整理得分 finishgame(score); //判斷遊戲結束函式 if (snakecoor[0].x == food.getFoodm_x() && snakecoor[0].y == food.getFoodm_y()) //蛇頭與食物重合 { gotoxy(snakecoor[0].x,snakecoor[0].y); //吃到食物時因為直接返回此次移動沒有輸出蛇身,會少輸出一次蛇 cout << "●"; //所以在這裡補上蛇移動時需要輸出的字元 gotoxy(snakecoor[1].x,snakecoor[1].y); cout << "■"; score++; //吃到食物得分+1 food.randfood(); //如果蛇頭座標和食物座標重合則重新產生一個食物 return; //直接結束本次移動 } for (int i = 0; i < snakecoor.size(); i++) //遍歷容器,判斷食物與蛇身是否重合並輸出整條蛇 { gotoxy(snakecoor[i].x,snakecoor[i].y); if (!i) //頭部輸出圓形否則輸出方塊 cout << "●"; else cout << "■"; //如果食物重新整理到了蛇身上,則重新產生一個食物 if (snakecoor[i].x == food.getFoodm_x() && snakecoor[i].y == food.getFoodm_y()) food.randfood(); } gotoxy(snakecoor.back().x,snakecoor.back().y); //在容器尾部的地方輸出空格 cout << " "; snakecoor.pop_back(); //刪除容器中最後一個數據 } }; void HideCursor() //隱藏游標 { CONSOLE_CURSOR_INFO cursor_info = { 1,0 }; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info); } void gotoxy(int x,int y) //游標定位 { COORD pos = { x,y }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); } //主函式 int main() { system("mode con cols=88 lines=28"); //設定控制檯視窗大小 system("title C++ 貪吃蛇"); //設定標題 HideCursor(); //游標隱藏 int score = 0; //得分變數 Food food; //食物物件 food.randfood(); //開局隨機產生一個食物 Snake snake; //蛇物件 while (true) { snake.move(food,score);//蛇移動 Sleep(150); //遊戲速度 } return 0; }
不足之處:
因為初學C++,所以程式中肯定還有一些不規範或不合理的地方。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。