本贪吃蛇主要运用C++和EasyX图形库进行开发。
详细的设计:
1.场景设计
运用了EasyX Graphics Library和Windows函数进行了对本游戏的图形化设计,我们的蛇采用若干个圆连接的形式组成,食物也采用圆的形式随机生成在地图上。
2.蛇和食物的储存结构
蛇和食物分别用一个类来储存,并且在该类中会储存相应的坐标、方向、速度、半径、等一些成员和成员函数。
3.蛇的移动
这里运用的kbhit()和getch()函数来接收用户的输入,并根据用户的输入来定蛇的方向。
4.蛇吃食物的判定
这里里的蛇吃食物的判定是根据蛇头和食物的距离来判定的,因游戏里的蛇头和食物都是一个圆构成的,所以我只需判定两个圆是否相交即可。
5.食物的生成,本游戏的食物是运用随机函数随机生成的。
6.蛇的死亡,这里的蛇是有2钟方式判定为死亡,一种是蛇头撞到墙和蛇头撞到身体,我们只需根据蛇头的坐标和蛇身的坐标来判定即可。
7.音乐的播放,运用Windows函数里的mciSendString()函数来播放音乐。
ps:这里的蛇的移动,是根据蛇头的方向移动而移动的,然后蛇身跟着前一节蛇身的位置而移动。
运行截图
#include源文件(snake.cpp)#include #define WIGHT 800 //窗口的宽度 #define HEIGHT 600 //窗口的高度 #define Snake_Num 500 //蛇最大的节数 using namespace std; class food; void Time_Out(); void Bgm(); void Begin(); double Distance(int x1, int y1, int x2, int y2); enum dir //枚举类型,UP,DOWN...相当于0,1... { UP, DOWN, LEFT, RIGHT }; class snake { public: snake(); bool Box(); bool Is_dead(); void GameDraw(food&); void SnakeMove(); void KeyControl(); void EatFood(food&); private: int len; //蛇的节数 int dir; //蛇的方向 int r; int grade; int speed; //蛇的速度 bool flag; //判断蛇是否死亡 POINT coor[Snake_Num]; //蛇的坐标, 里封装的结构体 }; class food { public: food(); void friend snake::GameDraw(food&); void friend snake::EatFood(food&); private: int x, y; int r; bool flag; };
#include "head.h"; #include主函数(main.cpp)#include #include #include #include #include #include //包含多媒体设备接口文件 #pragma comment(lib,"winmm.lib") //加载静态库 using namespace std; food::food() { r = 5; x = rand() % (WIGHT - 2 * r) + r; y = rand() % (HEIGHT - 2 * r) + r; flag = true; } snake::snake() { len = 3; dir = RIGHT; r = 5; speed = 10; grade = 0; flag = true; for (int i = 0; i <= len - 1; i++) { coor[i].x = 10 * (len - 1 - i) + 20; coor[i].y = 10; } } void snake::GameDraw(food &f) { BeginBatchDraw(); //防止闪屏 setbkcolor(RGB(56, 147, 186)); //设置填充颜色 cleardevice(); // 绘制蛇 for (int i = 0; i < len; i++) solidcircle(coor[i].x, coor[i].y, r); //绘制食物 if (f.flag) solidcircle(f.x, f.y, f.r); // 显示分数 wchar_t s[20] = L""; // L的作用,给s中的字符分配2个字节,wchar_t:宽字符 swprintf_s(s, L"分数:%d", grade); //把字符输入到s中 outtextxy(700, 20, s); // outtextxy(x, y, s),(x, y) 为坐标,是为要打印的内容 EndBatchDraw(); } void snake::KeyControl() { // kbhit()和getch()都得在 下才可以用 if (_kbhit()) //检查当前是否有键盘输入,若有返回一个非0的值,否则返回0 { switch (_getch()) //从控制台读取,不显示在屏幕上,即当用户按下某个字符时,无需按回车,函数自动读取 { case 'w': case 'W': case 72: if (dir == DOWN) break; // 防止蛇调头 dir = UP; break; case 's': case 'S': case 80: if (dir == UP) break; dir = DOWN; break; case 'a': case 'A': case 75: if (dir == RIGHT) break; dir = LEFT; break; case 'd': case 'D': case 77: if (dir == LEFT) break; dir = RIGHT; break; case ' ': Time_Out(); while (_getch() == ' ') break; break; default: break; } } } void snake::SnakeMove() { // 每节都跟着前一节移动 for (int i = len - 1; i > 0; i--) { coor[i].x = coor[i - 1].x; coor[i].y = coor[i - 1].y; } // 蛇头移动 switch (dir) { case UP: coor[0].y -= speed; break; case DOWN: coor[0].y += speed; break; case LEFT: coor[0].x -= speed; break; case RIGHT: coor[0].x += speed; break; default: break; } //判断是否撞墙 if (coor[0].x < r || coor[0].x > WIGHT - r) flag = false; if (coor[0].y < r || coor[0].y > HEIGHT - r) flag = false; // 判断是否撞到自己的身体 for (int i = 1; i < len; i++) { if (Distance(coor[0].x, coor[0].y, coor[i].x, coor[i].y) < 2 * r) { flag = false; break; } } } void snake::EatFood(food &f) { if (f.flag && Distance(coor[0].x, coor[0].y, f.x, f.y) <= r + f.r) { f.flag = false; len++; grade += 10; } if (!f.flag) { f.r = 5; f.x = rand() % (WIGHT - 2 * f.r) + f.r; f.y = rand() % (HEIGHT - 2 * f.r) + f.r; f.flag = true; } } double Distance(int x1, int y1, int x2, int y2) { double t1 = x1 - x2; double t2 = y1 - y2; return sqrt(t1 * t1 + t2 * t2); } bool snake::Box() { wchar_t s[20] = L""; swprintf_s(s, L"你的分数为:%dn是否再来一次", grade); HWND hWnd = GetHWnd(); // 获取窗口句柄 int id = MessageBox(hWnd, s, L"snake", MB_YESNO); //设置消息框 if (id == IDYES) return true; return false; } bool snake::Is_dead() { return flag; } void Begin() { IMAGE img; loadimage(&img, L"./snack.jpg", WIGHT, HEIGHT); putimage(0, 0, &img); } void Bgm() { mciSendString(L"open bgm.mp3", 0, 0, 0); mciSendString(L"play bgm.mp3", 0, 0, 0); } void Time_Out() { HWND hWnd = GetHWnd(); MessageBox(hWnd, L"游戏暂停,按空格键继续", L"提示", MB_OKCANCEL); }
#include "head.h"; #include#include #include #include #include #include using namespace std; int main() { Bgm(); srand(GetTickCount()); //设置种子为开机时间 initgraph(WIGHT, HEIGHT); while (1) { Begin(); if (_kbhit()) break; } snake s; food f; while (1) { s.KeyControl(); s.SnakeMove(); s.EatFood(f); s.GameDraw(f); if (!s.Is_dead()) { //重新开始 if (s.Box()) { snake ds; s = ds; food df; f = df; } else break; } Sleep(50); } return 0; }
总的来说这贪吃蛇做的并没有那么好,蛇和食物和背景都是非常的简陋,并且可玩性也不是非常的好,其实可以加速度选择,加关卡模式,还有界面的美化,甚至还可以和数据库进行链接,保存游戏的状态,但是作为一个课设,我觉得这样也够了,哈哈,懒是原罪。
好了,废话不多说了,如对大佬们有帮助,还请大佬们给个大拇指,哈哈
ps:这里在给大家一个打包教程:https://blog.csdn.net/qq_41506111/article/details/102777940
如果大家需要源码和课设报告,可以到这里下载:
https://download.csdn.net/download/weixin_52068218/85485458



