C++实现简易贪吃蛇游戏
C++实现建议贪吃蛇(不会闪屏幕)
使用vs2013完成。记录踏上游戏开发的道路。
效果图
代码
// 2021.7.24.1贪吃蛇.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <list>
#include <numeric>
#include <algorithm>
#include <Windows.h>
#include <WinUser.h>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;
#define KEY_DOWN(vk_code) (GetAsyncKeyState(vk_code) & 0x8000 ? 1 : 0)
#define MAX_SNAKE_LEN 20
#define MAP_MAXIMUM_HEIGHT 20
#define MAP_MAXIMUM_WIDTH 20
#define MAX_NUMBER_FRUIT 5
struct sSnakeBody
{
void setPostion(int x, int y)
{
nSnakeBodyX = x;
nSnakeBodyY = y;
}
void setPostion(sSnakeBody* temp)
{
nSnakeBodyX = temp->nSnakeBodyX;
nSnakeBodyY = temp->nSnakeBodyY;
}
int nSnakeBodyX;
int nSnakeBodyY;
};
typedef list<sSnakeBody> LISTSNAKEBODY;
struct sSnake
{
sSnake()
{
nSnakeHeadX = 1;
nSnakeHeadY = 1;
nSnakeDirection = 1;
speed = 5;
}
bool isExit(sSnakeBody temp)
{
if (nSnakeHeadX==temp.nSnakeBodyX&&nSnakeHeadY==temp.nSnakeBodyY)
{
return true;
}
return false;
}
bool isExit(int x, int y)
{
if (nSnakeHeadX == x&&nSnakeHeadY == y)
{
return true;
}
return false;
}
void reduction(sSnakeBody temp)
{
nSnakeHeadX = 2 * nSnakeHeadXBk - temp.nSnakeBodyX;
nSnakeHeadY = 2 * nSnakeHeadYBk - temp.nSnakeBodyY;
}
int nSnakeHeadX;
int nSnakeHeadY;
int nSnakeHeadXBk;
int nSnakeHeadYBk;
int nSnakeDirection;//0表示上,1表示右,2表示下,3表示左,顺时针
int speed;//指的是几个循环前进一次
LISTSNAKEBODY snakeBodyList[MAX_SNAKE_LEN];
};
struct sFruit
{
int FruitX;
int FruitY;
sFruit()
{
FruitX = -1;
FruitY = -1;
}
sFruit(int x, int y)
{
FruitX = x;
FruitY = y;
}
bool isExit(sSnake snake)
{
if (FruitX == snake.nSnakeHeadX && FruitY == snake.nSnakeHeadY)
return true;
else return false;
}
};
vector<sFruit> gFruitVector;
sSnake gSnake;
//显示地图
void showArrMap(int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH])
{
system("cls");
for (int i = 0; i < MAP_MAXIMUM_HEIGHT; i++)
{
for (int j = 0; j < MAP_MAXIMUM_WIDTH; j++)
{
if (1 == arrMap[i][j] || gSnake.isExit(i,j))
{
cout << "■";
}
else if (arrMap[i][j] == 2)
{
cout << "●";
}
else
{
cout << " ";
}
}
if (4 == i)
{
cout << "\t得分:" << gSnake.snakeBodyList->size();
}
cout << endl;
}
}
//将数据加载到地图上。返回值为加载后游戏是否失败
bool mapLoadData(int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH])
{
//加载水果的数据
for (unsigned int i = 0; i < gFruitVector.size(); i++)
{
arrMap[gFruitVector[i].FruitX][gFruitVector[i].FruitY] = 2;
}
//加载蛇的身体数据
for (LISTSNAKEBODY::iterator iter = gSnake.snakeBodyList->begin(); iter != gSnake.snakeBodyList->end(); iter++)
{
arrMap[iter->nSnakeBodyX][iter->nSnakeBodyY] = 1;
}
// 吃到第一个水果的时候,一定不是游戏失败
if (gSnake.snakeBodyList->size() == 1 && gSnake.isExit(gSnake.snakeBodyList->front()))
{
return false;
}
if (arrMap[gSnake.nSnakeHeadX][gSnake.nSnakeHeadY] == 1)
return true;
return false;
}
//更新蛇的数据
void updateSnake(int &nProgramCounter)
{
if (nProgramCounter > gSnake.speed)
{
gSnake.nSnakeHeadXBk = gSnake.nSnakeHeadX;
gSnake.nSnakeHeadYBk = gSnake.nSnakeHeadY;
if (gSnake.nSnakeDirection == 0)
{
gSnake.nSnakeHeadX--;
}
else if (gSnake.nSnakeDirection == 1)
{
gSnake.nSnakeHeadY++;
}
else if (gSnake.nSnakeDirection == 2)
{
gSnake.nSnakeHeadX++;
}
else if (gSnake.nSnakeDirection == 3)
{
gSnake.nSnakeHeadY--;
}
if (gSnake.snakeBodyList->size() != 0)
{
if (gSnake.isExit(gSnake.snakeBodyList->front()))
{
gSnake.reduction(gSnake.snakeBodyList->front());
}
}
//蛇的身体移动
if (gSnake.snakeBodyList->size() != 0)
{
sSnakeBody snakeBody;
snakeBody.setPostion(gSnake.nSnakeHeadXBk, gSnake.nSnakeHeadYBk);
gSnake.snakeBodyList->push_front(snakeBody);
gSnake.snakeBodyList->pop_back();
}
nProgramCounter = 0;
}
}
//绑定键盘事件
void bindKeyboardEvents()
{
if (KEY_DOWN(VK_UP))
{
gSnake.nSnakeDirection = 0;
}
else if (KEY_DOWN(VK_RIGHT))
{
gSnake.nSnakeDirection = 1;
}
else if (KEY_DOWN(VK_DOWN))
{
gSnake.nSnakeDirection = 2;
}
else if (KEY_DOWN(VK_LEFT))
{
gSnake.nSnakeDirection = 3;
}
if (KEY_DOWN(VK_SHIFT))
{
gSnake.speed = 2;
}
else
{
gSnake.speed = 5;
}
}
//随机生成 N 个水果,
void randomlyGeneratedFruit(int N, int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH])
{
int maxi = MAP_MAXIMUM_HEIGHT;
int maxj = MAP_MAXIMUM_WIDTH;
int AllCnt = 0;
vector<int> randMap;
for (int i = 0; i < maxi; i++)
{
for (int j = 0; j < maxj; j++)
{
if (0 == arrMap[i][j])
{
randMap.push_back(i*maxj + j);
AllCnt++;
}
}
}
if (AllCnt < N)
{
N = AllCnt;
}
for (int i = 0; i < N; i++)
{
int temp = (rand() % AllCnt--);
randMap.erase(randMap.begin() + temp);
sFruit fruitTemp = sFruit(temp / maxi + 1, temp % (maxi - 2) + 1);
gFruitVector.push_back(fruitTemp);
}
}
//初始化地图
void initArrMap(int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH])
{
for (int i = 0; i < MAP_MAXIMUM_HEIGHT; i++)
{
for (int j = 0; j < MAP_MAXIMUM_WIDTH; j++)
{
if (i == 0 || j == 0 || i == MAP_MAXIMUM_HEIGHT - 1 || j == MAP_MAXIMUM_WIDTH - 1)
arrMap[i][j] = 1;
else
arrMap[i][j] = 0;
}
}
}
//初始化水果数据
void initFruit(int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH])
{
randomlyGeneratedFruit(MAX_NUMBER_FRUIT, arrMap);
}
//蛇头吃到水果事件
void eatFruitEvent(int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH])
{
for (unsigned int i = 0; i < gFruitVector.size(); i++)
{
if (gFruitVector[i].isExit(gSnake))
{
sSnakeBody snakeBodyTemp;
if (gSnake.snakeBodyList->size() == 0)
{
snakeBodyTemp.setPostion(gSnake.nSnakeHeadX, gSnake.nSnakeHeadY);
}
else
{
snakeBodyTemp.setPostion(&gSnake.snakeBodyList->back());
}
gSnake.snakeBodyList->push_back(snakeBodyTemp);
gFruitVector.erase(gFruitVector.begin() + i);
randomlyGeneratedFruit(1, arrMap);
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hOutput;
COORD coord = { 0, 0 };
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//创建新的缓冲区
HANDLE hOutBuf = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
//设置新的缓冲区为活动显示缓冲
SetConsoleActiveScreenBuffer(hOutBuf);
//隐藏两个缓冲区的光标
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
SetConsoleCursorInfo(hOutBuf, &cci);
//双缓冲处理显示
DWORD bytes = 0;
char data[3200];
//地图,需要将数据映射到地图上,再去渲染地图。
int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH];
srand(time(NULL));
//计数器。
int nProgramCounter = 0;
//初始化各个数据
initArrMap(arrMap);
initFruit(arrMap);
while (true)
{
nProgramCounter++;
initArrMap(arrMap);
bindKeyboardEvents();
updateSnake(nProgramCounter);
eatFruitEvent(arrMap);
bool bIsWin = mapLoadData(arrMap);
showArrMap(arrMap);
if (bIsWin)
{
cout << endl << "游戏失败!!!";
ReadConsoleOutputCharacterA(hOutput, data, 3200, coord, &bytes);
WriteConsoleOutputCharacterA(hOutBuf, data, 3200, coord, &bytes);
break;
}
ReadConsoleOutputCharacterA(hOutput, data, 3200, coord, &bytes);
WriteConsoleOutputCharacterA(hOutBuf, data, 3200, coord, &bytes);
}
system("pause");
return 0;
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
以上是 C++实现简易贪吃蛇游戏 的全部内容, 来源链接: utcz.com/p/246645.html