贪吃蛇案例

mac2022-06-30  111

wall.h
#pragma once #ifndef _WALL_HEAD #define _WALL_HEAD #include <iostream> using namespace std; class Wall { public: enum { ROW = 26 , COL = 26 }; // 初始化墙壁 void initWall(); // 画出强墙壁 void drawWall(); // 根据索引设置二维数组里的内容 void setWall(int x, int y, char c); // 根据索引获取当前位置的符号 char getWall(int x, int y); private: char gameArray[ROW][COL]; }; #endif // !WALL
wall.cpp
#include "wall.h" void Wall::initWall() { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { // 放墙壁 if (i == 0 || j == 0 || i == ROW - 1 || j == COL - 1) { gameArray[i][j] = '*'; } else { gameArray[i][j] = ' '; } } } } void Wall::drawWall() { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { cout << gameArray[i][j] << " "; } if (i == 5) { cout << "create by xiaomeng"; } if (i == 6) { cout << "a:left"; } if (i == 6) { cout << "a:left"; } if (i == 7) { cout << "d:right"; } if (i == 8) { cout << "w:ip"; } if (i == 9) { cout << "s:down"; } cout << endl; // cout << endl; } } void Wall::setWall(int x, int y, char c) { gameArray[x][y] = c; } char Wall::getWall(int x, int y) { return gameArray[x][y]; }
snake.h
#pragma once #include <iostream> #include "wall.h" #include "food.h" #include <Windows.h> using namespace std; class Snake { public: Snake(Wall & tmpWall, Food &food); enum { UP = 'w', DOWN = 's', LEFT = 'a', RIGHT = 'd' }; // 节点 struct Point { // 数据域 int x; int y; // 指针域 Point * next; }; void initSnake(); // 销毁节点 void destoryPonit(); // 添加节点 void addPonit(int x, int y); // 删除节点 --删除最后一个节点 void delPoint(); // 移动蛇的操作 -- 返回值代表移动是否成功 bool move(char key); // 设定难度 // 获取刷屏时间 int getSleepTime(); // 获取蛇的身段 int countList(); // 获取分数 int getScore(); Point * pHead; // 头节点 Wall &wall; Food &food; bool isRool; // 是否碰到尾巴 -- 循环的标识 };
snake.cpp
#include "snake.h" void gotoxy1(HANDLE hOut1, int x, int y) { COORD pos; pos.X = x; // 横坐标 pos.Y = y; // 纵坐标 SetConsoleCursorPosition(hOut1, pos); } HANDLE hOut1 = GetStdHandle(STD_OUTPUT_HANDLE); // 定义显示器句柄变量 Snake::Snake(Wall & tmpWall, Food &tmpFood):wall(tmpWall),food(tmpFood) // 初始化 Snake 类里面的wall { pHead = NULL; isRool = false; } // 初始化蛇 void Snake::initSnake() { destoryPonit(); addPonit(5, 3); addPonit(5, 4); addPonit(5, 5); } // 销毁所有节点 void Snake::destoryPonit() { Point * pCur = pHead; while (pHead != NULL) { pCur = pHead->next; delete pHead; pHead = pCur; } } void Snake::addPonit(int x, int y) { // 创建新节点 Point * newPoint = new Point; newPoint->x = x; newPoint->y = y; newPoint->next = NULL; // 如果原来头不为空 改为身子 if (pHead != NULL) { wall.setWall(pHead->x, pHead->y, '='); gotoxy1(hOut1, pHead->y * 2, pHead->x); cout << "="; } newPoint->next = pHead; pHead = newPoint; // 更新头部 wall.setWall(pHead->x, pHead->y, '@'); gotoxy1(hOut1, pHead->y * 2, pHead->x); cout << "@"; } // 删除节点 - 删除最后一个节点 void Snake::delPoint() { // 两个节点以上 才去做删除节点操作 if (pHead == NULL || pHead->next == NULL) { return; } Point * pPre = pHead; Point * pCur = pHead->next; while (pCur->next != NULL) { pPre = pPre->next; pCur = pCur->next; } // 删除尾节点 wall.setWall(pCur->x, pCur->y, ' '); gotoxy1(hOut1, pCur->y * 2, pCur->x); cout << ' '; delete pCur; pCur = NULL; pPre->next = NULL; } bool Snake::move(char key) { int x = pHead->x; int y = pHead->y; switch (key) { case UP: x--; break; case DOWN: x++; break; case LEFT: y--; break; case RIGHT: y++; break; default: break; } // 判断 如果下一步碰到的是尾巴 不应该死亡 Point * pCur = pHead->next; Point * pPre = pHead; while (pCur->next != NULL) { pPre = pPre->next; pCur = pCur->next; } if (pCur->x == x && pCur->y == y) { // 碰到尾巴的循环 isRool = true; } else { // 判断用户到达位置是否成功 if (wall.getWall(x, y) == '*' || wall.getWall(x, y) == '=') { addPonit(x, y); system("cls"); wall.drawWall(); cout << "得分 : " << getScore() << "分" << endl; cout << "GAME OVER !!!" << endl; return false; } } // 移动成功分两种 // 吃到食物 未吃到食物 if (wall.getWall(x, y) == '#') { addPonit(x, y); // 重新设置食物 food.setFood(); } else { addPonit(x, y); delPoint(); if (isRool == true) { // 重新绘制头节点 wall.setWall(x, y, '@'); gotoxy1(hOut1, y * 2, x); cout << "@"; } } return true; } int Snake::getSleepTime() { int sleepTime = 0; int size = countList(); if (size < 5) { sleepTime = 300; } else if (size >= 5 <= 9) { sleepTime = 200; } else { sleepTime = 100; } return sleepTime; } int Snake::countList() { int size = 0; Point * curPoint = pHead; while (curPoint != NULL) { size++; curPoint = curPoint->next; } return size; } int Snake::getScore() { int size = countList(); int score = (size - 3) * 100; return score; }
food.h
#pragma once #include <iostream> #include "wall.h" #include <Windows.h> using namespace std; class Food { public: Food(Wall &tmpWall); // 设置食物 void setFood(); int foodX; int foodY; Wall & wall; };
food.cpp
#include "food.h" void gotoxy2(HANDLE hOut2, int x, int y) { COORD pos; pos.X = x; // 横坐标 pos.Y = y; // 纵坐标 SetConsoleCursorPosition(hOut2, pos); } HANDLE hOut2 = GetStdHandle(STD_OUTPUT_HANDLE); // 定义显示器句柄变量 Food::Food(Wall &tmpWall) :wall(tmpWall) { } void Food::setFood() { while (true) { // 随机生成食物的 foodX = rand() % (Wall::ROW - 2) + 1; foodY = rand() % (Wall::COL - 2) + 1; // 如果随机的位置是蛇头或者是蛇身 就重新生成随机数 if (wall.getWall(foodX, foodY) == ' ') { wall.setWall(foodX, foodY, '#'); gotoxy2(hOut2, foodY * 2, foodX); cout << "#"; break; } } }
game.cpp
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; #include "wall.h" #include "snake.h" #include "food.h" #include "ctime" #include "conio.h" #include <Windows.h> void gotoxy(HANDLE hOut, int x, int y) { COORD pos; pos.X = x; // 横坐标 pos.Y = y; // 纵坐标 SetConsoleCursorPosition(hOut, pos); } HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 定义显示器句柄变量 int main() { // 添加随机种子 srand((unsigned int)time(NULL)); // 是否死亡的标识 bool isDead = false; char preKey = NULL; Wall wall; wall.initWall(); wall.drawWall(); // initWall() 之后就需要 drawWall() // 测试 /*wall.setWall(5, 4, '='); wall.setWall(5, 5, '='); wall.setWall(5, 6, '@');*/ Food food(wall); food.setFood(); Snake snake(wall, food); snake.initSnake(); gotoxy(hOut, 0, Wall::ROW); cout << "得分 : " << snake.getScore() << "分" << endl; gotoxy(hOut, 10, 5); // 接收用户输入 while (!isDead) { char key = _getch(); // 判断如果是第一次 按了左键 才不能激活游戏 // 判断上一次的移动方向 if (preKey == NULL && key == snake.LEFT) { continue; } do { if (key == snake.UP || key == snake.DOWN || key == snake.LEFT || key == snake.RIGHT) { // 判断本次的按键是否与上次冲突 if ( (key == snake.LEFT && preKey == snake.RIGHT) || (key == snake.RIGHT && preKey == snake.LEFT) || (key == snake.UP && preKey == snake.DOWN) || (key == snake.DOWN && preKey == snake.UP) ) { key = preKey; } else { preKey = key; // 不是冲突按键 就直接更新按键 } if (snake.move(key) == true) { // 移动成功 // system("cls"); // wall.drawWall(); gotoxy(hOut, 0, Wall::ROW); cout << "得分 : " << snake.getScore() << "分" << endl; Sleep(snake.getSleepTime()); } else { isDead = true; break; } } else { key = preKey; // 强制将锁雾按键变为上一次移动的方向 } } while (!_kbhit()); // _kbhit() 在没有键盘输入的时候 返回为 0 } system("pause"); return EXIT_SUCCESS; }
最新回复(0)