C++實現貪吃蛇小游戲


今天突發奇想想用C++實現一個貪吃蛇小游戲,無奈C++沒有自帶的GUI框架,蒟蒻博主也不會用C++做GUI,於是只能在黑乎乎的命令行中完成這個游戲了(qwq)。

貪吃蛇游戲還是比較簡單的,就用C++的基礎知識和一點個Windows的api就可以開發完成了,這里就稍微講一下思路吧。

 

總共是GameInit.cpp,Snake.cpp,Food.cpp,Display.cpp,GameStart.cpp 這5個文件。

 

GameInit是游戲的初始設置類,負責設置游戲窗口大小,設置光標,初始化隨機種子等等初始化工作。

 1 #include"pch.h"
 2 #include "GmaeInit.h"
 3 #include<Windows.h>
 4 #include<random>
 5 #include<ctime>
 6 #include <conio.h>
 7 
 8 using namespace std;
 9 
10 GameInit::GameInit(int s) : speed(s) {
11     //設置游戲窗口大小
12     char buffer[32];
13     sprintf_s(buffer, "mode con cols=%d lines=%d", windowWidth, windowHeight);
14     system(buffer);
15 
16     //隱藏光標
17     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
18     CONSOLE_CURSOR_INFO CursorInfo;
19     GetConsoleCursorInfo(handle, &CursorInfo);//獲取控制台光標信息
20     CursorInfo.bVisible = false; //隱藏控制台光標
21     SetConsoleCursorInfo(handle, &CursorInfo);//設置控制台光標狀態
22     //初始化隨機數種子
23     srand((unsigned int)time(0));
24 }
View Code

 

Snake是控制蛇的類,包括監聽鼠標對蛇的方向做出改變,以及在地圖上移動蛇兩個功能。當然在移動中非常重要的是,判斷蛇是否撞到邊界,是否撞到自己等等。

這里講一下移動應該怎么做,首先蛇的身體是用list來存儲,移動其實很簡單分兩種情況:①沒吃到食物,那么就是蛇頭朝目標方向移動一個作為新的蛇頭加入身體list,然后把蛇的尾部刪除。②那么如果吃到了食物該怎么辦呢?想一想,欸沒錯就是不把蛇尾刪除就是了(相當於增上了一格)。

 1 #include"pch.h"
 2 #include"Snake.h"
 3 #include"GmaeInit.h"
 4 #include<iostream>
 5 #include<unordered_set>
 6 #include<Windows.h>
 7 #include <conio.h>
 8 
 9 using namespace std;
10 
11 Snake::Snake() {
12     oldDirection = 1;
13     newDirection = -1;
14     body.push_back(point{ 40, 15 });
15     body.push_back(point{ 39,15 });
16     body.push_back(point{ 38,15 });
17     body.push_back(point{ 37, 15 });
18     body.push_back(point{ 36, 15 });
19 }
20 
21 //監聽鍵盤
22 void Snake::listen_key_borad() {
23     char ch;
24     if (_kbhit())                    //kbhit 非阻塞函數 
25     {
26         ch = _getch();    //使用 getch 函數獲取鍵盤輸入 
27         switch (ch)
28         {
29         case 'w':
30         case 'W':
31             if (oldDirection == 2) break;
32             newDirection = 0;
33             break;
34         case 's':
35         case 'S':
36             if (oldDirection == 0) break;
37             newDirection = 2;
38             break;
39         case 'a':
40         case 'A':
41             if (oldDirection == 1) break;
42             newDirection = 3;
43             break;
44         case 'd':
45         case 'D':
46             if (oldDirection == 3) break;
47             newDirection = 1;
48             break;
49         }
50     }
51 }
52 
53 bool Snake::movePoint(point& pt,int dir) {
54     point newpt = pt;
55     newpt.x += dx[dir];
56     newpt.y += dy[dir];
57     if (newpt.x<=1 || newpt.x>=GameInit::windowWidth || newpt.y<=1 || newpt.y>=GameInit::windowHeight) return 0;
58     unordered_set<int> snakebody;
59     for (auto pt : body)  snakebody.insert(pt.x*1000+pt.y);
60     if (snakebody.count(newpt.x*1000+newpt.y)) return 0;
61     pt = newpt;
62     return 1;
63 }
64 
65 bool Snake::moveHead() {
66     if (newDirection == -1) newDirection = oldDirection;
67 
68     point newpt = body.front();
69     if (movePoint(newpt,newDirection) == 0) return 0;
70     body.push_front(newpt);
71 
72     oldDirection = newDirection; newDirection = -1;
73     return 1;
74 }
75 
76 bool Snake::moveHeadAndTail() {
77     if (newDirection == -1) newDirection = oldDirection;
78 
79     body.pop_back();
80     point newpt = body.front();
81     if (movePoint(newpt,newDirection) == 0) return 0;
82     body.push_front(newpt);
83     
84     oldDirection = newDirection; newDirection = -1;
85     return 1;
86 }
View Code

 

Food是食物類,只有生成食物只一個主要功能(當然生成還要避免生成在蛇身上)。

 1 #include"pch.h"
 2 #include<iostream>
 3 #include<random>
 4 #include<cstdlib>
 5 #include"Food.h"
 6 #include"GmaeInit.h"
 7 #include"Snake.h"
 8 
 9 using namespace std;
10 
11 bool Food::EatFood(const list<point>& body) {
12     if (x == body.front().x && y == body.front().y) return 1;
13     else return 0;
14 }
15 
16 bool Food::FoodOnBody(int tmpx,int tmpy,const list<point>& body) {
17     for (auto pt : body)
18         if (pt.x == tmpx && pt.y == tmpy) return 1;
19     return 0;
20 }
21 
22 void Food::CreateFood(const list<point>& body) {
23     int tmpx,tmpy;
24     do {
25         tmpx = rand() % GameInit::windowWidth + 1;
26         tmpy = rand() % GameInit::windowHeight + 1;
27     } while (FoodOnBody(tmpx, tmpy, body));
28     this->x = tmpx;
29     this->y = tmpy;
30 }
View Code

 

Display是一個比較關鍵的類,它負責地圖上各個資源的展示,包括蛇身體,食物,地圖邊界,當然也包括各個資源的銷毀。

這個函數要用到一個比較有趣的Window API:SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);  這個函數能夠移動命令行光標位置,然后我們就能在那個位置輸出符號!!!

 1 #include"pch.h"
 2 #include"Display.h"
 3 #include"GmaeInit.h"
 4 #include"Snake.h"
 5 #include<iostream>
 6 #include<Windows.h>
 7 #include <conio.h>
 8 
 9 using namespace std;
10 
11 void Display::printBorder() {
12     system("cls");
13     int n = GameInit::windowHeight;
14     int m = GameInit::windowWidth;
15     for (int i = 1; i <= n; i++) {
16         for (int j = 1; j <= m; j++) {
17             if (i == 1 || i==n  || j == 1 || j == m) cout << "#"; else cout << " ";
18         }
19         cout << endl;
20     }
21 }
22 
23 //將光標移動到x,y位置
24 void Display::gotoxy(int x, int y) {
25     COORD c;
26     c.X = x; c.Y = y;
27     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
28 }
29 
30 void Display::printSnake(const list<point> &body) {
31     for (auto pt : body) {
32         gotoxy(pt.x, pt.y);
33         cout << "*";
34     }
35 }
36 
37 void Display::destroySnake(const list<point> &body) {
38     for (auto pt : body) {
39         gotoxy(pt.x, pt.y);
40         cout << " ";
41     }
42 }
43 
44 void Display::printFood(int x, int y) {
45     gotoxy(x, y);
46     cout << "@";
47 }
48 
49 void Display::destroyFood(int x, int y) {
50     gotoxy(x, y);
51     cout << " ";
52 }
53 
54 void Display::clean() {
55     for (int i = 32; i <= 50; i++) {
56         gotoxy(i, 16);
57         cout << " ";
58     }
59 }
60 
61 void Display::gameover() {
62     string over = "游戲結束";
63     for (int i = 32; i <= 40; i++) {
64         gotoxy(i, 16);
65         cout << over[i-32];
66     }
67 }
View Code

 

 

這只是個心血來潮做的小demo,讀者很容易能看懂,也很容易為它擴展各種功能:例如計分板,根據玩家選難度加快蛇移動速度,加入經典的無邊界地圖玩法等等。

游戲項目Github地址:https://github.com/Clno1/Blockade    。改一改玩一玩很是很歡樂的,哈哈哈。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM