C++实现贪吃蛇小游戏
标签:line 贪吃蛇 今天 href bool 生成 alt std idt
今天突发奇想想用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 4 #include 5 #include 6 #include 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 5 #include 6 #include 7 #include 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.x1 || newpt.x>=GameInit::windowWidth || newpt.y1 || newpt.y>=GameInit::windowHeight) return 0;
58 unordered_setint> 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 3 #include 4 #include 5 #include"Food.h"
6 #include"GmaeInit.h"
7 #include"Snake.h"
8
9 using namespace std;
10
11 bool Food::EatFood(const list& 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& 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& 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 6 #include 7 #include 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 ) {
16 for (int j = 1; 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 &body) {
31 for (auto pt : body) {
32 gotoxy(pt.x, pt.y);
33 cout "*";
34 }
35 }
36
37 void Display::destroySnake(const list &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 32];
66 }
67 }
View Code
这只是个心血来潮做的小demo,读者很容易能看懂,也很容易为它扩展各种功能:例如计分板,根据玩家选难度加快蛇移动速度,加入经典的无边界地图玩法等等。
游戏项目Github地址:https://github.com/Clno1/Blockade 。改一改玩一玩很是很欢乐的,哈哈哈。
C++实现贪吃蛇小游戏
标签:line 贪吃蛇 今天 href bool 生成 alt std idt
原文地址:https://www.cnblogs.com/clno1/p/12838952.html
评论