一、题目
贪吃蛇游戏机制是通过控制蛇上下左右移动并吃到食物得分。
蛇头碰到墙壁或者碰到蛇身就游戏结束。
食物随机生成,蛇吃到食物之后蛇身变长,蛇速加快。
二、算法
1. 初始化游戏地图并打印,地图的边缘是墙,地图的每个坐标都有属性(EMPTY、WALL、FOOD、HEAD、BODY),通过库里面的函数控制光标跳转和颜色。
2. 初始化蛇,蛇是一个单独的类,类里面的属性有蛇头、蛇身、长度、速度,蛇头一个SnakeNode节点,蛇身是一个SnakeNode指针,每个SnakeNode都是一个x、y坐标,用于表示蛇在地图上的位置。
3. 随机生成食物,蛇移动的下一步如果是食物则得分,若下一步是墙壁或蛇身则游戏失败。
4. 通过键盘输入控制方向,若键盘没有输入则保持方向不变。
三、代码
#define _CRT_SECURE_NO_WARNINGS 1#pragma warning (disable:4996)#include #include #include #include #include using namespace std;#define ROW 22#define COL 42#define EMPTY 0#define WALL1#define FOOD2#define HEAD3#define BODY4#define COL_WALL6#define COL_FOOD12#define COL_SNAKE 10#define UP 72#define DOWN 80#define LEFT 75#define RIGHT 77#define SPACE 32#define ESC 27#define ENTER 13int g_map[ROW][COL] = { 0 };int g_grade = 0;void CursorJump(int x, int y){COORD pos;//定义光标位置的结构体变量pos.X = x;pos.Y = y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);//设置光标位置}void Color(int x){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);//设置颜色// 6——土黄色7——白色10——绿色12——红色}void SysInit(){srand((unsigned int)time(NULL));system("title 贪吃蛇");system("mode con cols=84 lines=23");//设置终端窗口大小CONSOLE_CURSOR_INFO curInfo;//光标信息结构体变量curInfo.dwSize = 1;curInfo.bVisible = FALSE;//光标光标隐藏不可见SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &curInfo);//设置光标信息}void MapInit(){for (int i = 0; i < ROW; ++i){for (int j = 0; j < COL; ++j){CursorJump(2 * j, i);if (i == 0 || i == ROW - 1 || j == 0 || j == COL - 1){Color(COL_WALL);g_map[i][j] = WALL;cout << "■";}else{g_map[i][j] = EMPTY;cout << "";}}}Color(7);CursorJump(0, ROW);cout << "当前得分是:" << g_grade;}void RandFood(){int row, col;do{row = rand() % ROW;col = rand() % COL;} while (g_map[row][col] != EMPTY);g_map[row][col] = FOOD;Color(COL_FOOD);CursorJump(2 * col, row);cout << "●";}class Snack{public:Snack(){len = 2;rate = 3000;head.x = COL / 2;head.y = ROW / 2;g_map[head.y][head.x] = HEAD;body.resize(ROW * COL, Pos(0, 0));for (int i = 0; i < len; ++i){body[i].x = head.x - i - 1;body[i].y = head.y;g_map[body[i].y][body[i].x] == BODY;}}void PrintSnake(int flag){if (flag){// 打印蛇Color(COL_SNAKE);CursorJump(2 * head.x, head.y);cout << "◆";for (int i = 0; i < len; ++i){CursorJump(2 * body[i].x, body[i].y);cout << "◇";}}else{// 覆盖蛇if (body[len - 1].x != 0){CursorJump(2 * body[len - 1].x, body[len - 1].y);cout < 1000)rate -= 50;Color(7);CursorJump(0, ROW);cout << "当前得分是:" << g_grade;RandFood();}else if (g_map[head.y + y][head.x + x] == WALL|| g_map[head.y + y][head.x + x] == BODY){// 失败Sleep(2000);Color(7);system("cls");cout << " GAME OVER!" << endl;cout << "游戏失败!" < 0){body[tail].x = body[tail - 1].x;body[tail].y = body[tail - 1].y;--tail;}body[0].x = head.x;body[0].y = head.y;g_map[body[0].y][body[0].x] = BODY;head.x += x;head.y += y;g_map[head.y][head.x] = HEAD;PrintSnake(1);}void Run(int x, int y){int t = 0;while (1){if (t == 0)t = rate;while (--t){if (kbhit() != 0)break;}if (t == 0)Move(x, y);elsebreak;}}void Play(){int dir = RIGHT;int old = dir;while (1){switch (dir){case 'w':case 'W':case UP:Run(0, -1);old = dir;break;case 's':case 'S':case DOWN:Run(0, 1);old = dir;break;case 'a':case 'A':case LEFT:Run(-1, 0);old = dir;break;case 'd':case 'D':case RIGHT:Run(1, 0);old = dir;break;case SPACE:system("pause>nul");break;case ESC:system("cls");cout << " ESC 退出游戏" << endl;exit(0);}dir = getch();switch (dir){case 'w':case 'W':case UP:case 's':case 'S':case DOWN:if (old == UP || old == DOWN)dir = old;break;case 'a':case 'A':case LEFT:case 'd':case 'D':case RIGHT:if (old == LEFT || old == RIGHT)dir = old;break;case SPACE:case ESC:break;default:dir = old;}}}private:struct Pos{int x, y;Pos() {}Pos(int x1, int y1): x(x1), y(y1){}};Pos head;vector body;int len;int rate;};int main(){SysInit();MapInit();RandFood();Snack s;s.Play();return 0;}