C++實(shí)現(xiàn)簡(jiǎn)易貪吃蛇游戲
更新時(shí)間:2021年07月29日 11:11:19 作者:AAH。
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)易貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
C++實(shí)現(xiàn)建議貪吃蛇(不會(huì)閃屏幕)
使用vs2013完成。記錄踏上游戲開發(fā)的道路。
效果圖

代碼
// 2021.7.24.1貪吃蛇.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
//
#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表示左,順時(shí)針
int speed;//指的是幾個(gè)循環(huán)前進(jìn)一次
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;
}
}
//將數(shù)據(jù)加載到地圖上。返回值為加載后游戲是否失敗
bool mapLoadData(int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH])
{
//加載水果的數(shù)據(jù)
for (unsigned int i = 0; i < gFruitVector.size(); i++)
{
arrMap[gFruitVector[i].FruitX][gFruitVector[i].FruitY] = 2;
}
//加載蛇的身體數(shù)據(jù)
for (LISTSNAKEBODY::iterator iter = gSnake.snakeBodyList->begin(); iter != gSnake.snakeBodyList->end(); iter++)
{
arrMap[iter->nSnakeBodyX][iter->nSnakeBodyY] = 1;
}
// 吃到第一個(gè)水果的時(shí)候,一定不是游戲失敗
if (gSnake.snakeBodyList->size() == 1 && gSnake.isExit(gSnake.snakeBodyList->front()))
{
return false;
}
if (arrMap[gSnake.nSnakeHeadX][gSnake.nSnakeHeadY] == 1)
return true;
return false;
}
//更新蛇的數(shù)據(jù)
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());
}
}
//蛇的身體移動(dòng)
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;
}
}
//隨機(jī)生成 N 個(gè)水果,
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;
}
}
}
//初始化水果數(shù)據(jù)
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);
//創(chuàng)建新的緩沖區(qū)
HANDLE hOutBuf = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
//設(shè)置新的緩沖區(qū)為活動(dòng)顯示緩沖
SetConsoleActiveScreenBuffer(hOutBuf);
//隱藏兩個(gè)緩沖區(qū)的光標(biāo)
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
SetConsoleCursorInfo(hOutBuf, &cci);
//雙緩沖處理顯示
DWORD bytes = 0;
char data[3200];
//地圖,需要將數(shù)據(jù)映射到地圖上,再去渲染地圖。
int arrMap[MAP_MAXIMUM_HEIGHT][MAP_MAXIMUM_WIDTH];
srand(time(NULL));
//計(jì)數(shù)器。
int nProgramCounter = 0;
//初始化各個(gè)數(shù)據(jù)
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;
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:
- C++ 情懷游戲貪吃蛇的實(shí)現(xiàn)流程詳解
- 利用C/C++實(shí)現(xiàn)貪吃蛇游戲
- C++入門指南之貪吃蛇游戲的實(shí)現(xiàn)
- C++實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲
- C++實(shí)現(xiàn)貪吃蛇游戲
- C++代碼實(shí)現(xiàn)貪吃蛇小游戲
- 基于easyx的C++實(shí)現(xiàn)貪吃蛇
- C++控制臺(tái)循環(huán)鏈表實(shí)現(xiàn)貪吃蛇
- C++控制臺(tái)實(shí)現(xiàn)貪吃蛇游戲
- C++通過類實(shí)現(xiàn)控制臺(tái)貪吃蛇
- C++結(jié)構(gòu)體數(shù)組實(shí)現(xiàn)貪吃蛇
- c++實(shí)現(xiàn)超簡(jiǎn)單的貪吃蛇游戲?qū)嵗榻B
相關(guān)文章
C++控制臺(tái)實(shí)現(xiàn)簡(jiǎn)單人機(jī)對(duì)弈井字棋
這篇文章主要為大家詳細(xì)介紹了C++控制臺(tái)實(shí)現(xiàn)簡(jiǎn)單人機(jī)對(duì)弈井字棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
最新VScode C/C++ 環(huán)境配置的詳細(xì)教程
這篇文章主要介紹了最新VScode C/C++ 環(huán)境配置的詳細(xì)教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié)
這篇文章主要介紹了c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
C語言程序設(shè)計(jì)之指針的應(yīng)用詳解
為了讓大家能夠更準(zhǔn)確的了解C語言中指針的使用,本文為大家準(zhǔn)備了四個(gè)指針相關(guān)的例題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下2022-11-11

