0006 10分钟带你用C++代码实现贪吃蛇游戏
贪吃蛇游戏是一款休闲益智类游戏,既简单又耐玩。该游戏通过控制蛇头方向吃蛋,从而使得蛇变得越来越长,下面我们用代码实现贪吃蛇游戏吧!
语言: C++
环境:VS2012及以上版本
文章目录
前言
相信很多人写贪吃蛇的时候,脑袋里冒出了无数的想法。
蛇长什么样?食物长什么样?怎么去计算是否碰到了墙壁?怎么去计算是否碰到了蛇身?怎么增加蛇的身体长度?怎么让蛇自动移动?怎么控制蛇的方向?
一下子N个问题冒出来需要处理,是很难理清楚逻辑和规律的,然后很多同学就会崩溃,无法继续编码。
所以,与其同时思考N个问题,不如先集中注意力,解决第一个小问题。这就是分治法的精髓所在,分而治之,把大问题拆成小问题,然后着力先解决一个个小问题,解决不了的问题放后面,先把能解决的解决掉。
后面还有问题怎么办呢?到了那步再说呗。
游戏规则
用WASD控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,不能咬到自己的身体,更不能咬自己的尾巴
一、蛇部分
1.一条蛇最关键的就是蛇头的位置和蛇身的长度,将蛇看为一个vector数组,存放蛇头到蛇尾的坐标;
2.每次移动,蛇头向前进方向移动一位,后面的蛇身分别继承上一级的位置,这样就实现了蛇的移动;
3.当蛇吃到食物时,新创造一个点继承蛇尾的位置。
4.当蛇碰撞到墙体或者自己的身体,则游戏结束,显示总分
1、Snake.h
Snake.h代码如下:
#pragma once
#include<vector>
#include<windows.h>
#include "Food.h"
using namespace std;
//上下左右
#define DIR_UP 1
#define DIR_RIGHT 2
#define DIR_DOWN 3
#define DIR_LEFT 4
class Snake
{
public:
Snake(void);
~Snake(void);
vector<COORD> n_bodyPos;
int n_bodyLen;
HANDLE n_hOut;
void show();
void disappear();
void init(int len,COORD startPos);
void move(int dir,Food thFood);
void move(int dir);
void grow();
void keyBdCtr(Food thFood);
};
2、Snake.cpp
Snake.cpp代码如下:
#include "stdafx.h"
#include "Snake.h"
#include "Food.h"
#include<windows.h>
#include<conio.h>
Snake::Snake(void)
{
n_bodyPos.clear();
n_bodyLen=0;
}
Snake::~Snake(void)
{
}
void Snake::init(int len,COORD startPos)
{
for(int i=0;i<len;i++)
{
COORD tmp=startPos;
tmp.X=startPos.X-i;
n_bodyPos.push_back(tmp);
n_bodyLen++;
}
}
void Snake::show()
{
n_hOut=GetStdHandle(STD_OUTPUT_HANDLE);
for(int i=0;i<n_bodyLen;i++)
{
SetConsoleCursorPosition(n_hOut,n_bodyPos[i]);
if(i==0)
printf("@");
else
printf("*");
}
}
void Snake::move(int dir,Food thFood)
{
Sleep(500); //间隔一段时间
//system("cls");
//蛇身体消失
disappear();
for(int i=n_bodyPos.size()-1;i>=1;i--)
{
n_bodyPos[i]=n_bodyPos[i-1];
SetConsoleCursorPosition(n_hOut,n_bodyPos[i]);
printf("*");
}
switch (dir)
{
case DIR_UP:
{
n_bodyPos[0].Y-=1;
break;
}
case DIR_RIGHT:
{
n_bodyPos[0].X+=1;
break;
}
case DIR_DOWN:
{
n_bodyPos[0].Y+=1;
break;
}
case DIR_LEFT:
{
n_bodyPos[0].X-=1;
break;
}
default:
break;
}
SetConsoleCursorPosition(n_hOut,n_bodyPos[0]);
printf("*");
//判断碰撞
if(thFood.n_pos.X==n_bodyPos[0].X&&
thFood.n_pos.Y==n_bodyPos[0].Y)
{
grow();
thFood.disappear();
}
}
void Snake::move(int dir)
{
Sleep(500); //间隔一段时间
//system("cls");
//蛇身体消失
disappear();
for(int i=n_bodyPos.size()-1;i>=1;i--)
{
n_bodyPos[i]=n_bodyPos[i-1];
SetConsoleCursorPosition(n_hOut,n_bodyPos[i]);
printf("*");
}
switch (dir)
{
case DIR_UP:
{
n_bodyPos[0].Y-=1;
break;
}
case DIR_RIGHT:
{
n_bodyPos[0].X+=1;
break;
}
case DIR_DOWN:
{
n_bodyPos[0].Y+=1;
break;
}
case DIR_LEFT:
{
n_bodyPos[0].X-=1;
break;
}
default:
break;
}
SetConsoleCursorPosition(n_hOut,n_bodyPos[0]);
printf("@");
}
void Snake::grow()
{
COORD tmp=n_bodyPos[n_bodyLen-1];
n_bodyPos.push_back(tmp);
n_bodyLen++;
}
void Snake::disappear()
{
for(int i=0;i<n_bodyLen;i++)
{
SetConsoleCursorPosition(n_hOut,n_bodyPos[i]);
printf(" ");
}
}
void Snake::keyBdCtr(Food thFood)
{
while(1)
{
char ch=' ';
if(_kbhit())
{
ch=_getch();
switch (ch)
{
case 'w':
{
move(DIR_UP,thFood);
break;
}
case 'a':
{
move(DIR_LEFT,thFood);
break;
}
case 's':
{
move(DIR_DOWN,thFood);
break;
}
case 'd':
{
move(DIR_RIGHT,thFood);
break;
}
default:
break;
}
}
}
}
二、食物部分
食物是一个用坐标表示的特殊点,当蛇头碰撞到食物点,食物消失,系统加分并蛇身加长。
再食物被吃掉之后,调用随机函数重新生成食物。
1.Food.h
Food.h代码如下:
#pragma once
#include<windows.h>
class Food
{
public:
Food(void);
~Food(void);
COORD n_pos;
HANDLE n_hOut;
int n_stat;
int score;
static int n_firstRun;
int create();
int create(COORD pos);
void disappear();
};
2.Food.cpp
Food.cpp代码如下:
#include "stdafx.h"
#include "Food.h"
#include<windows.h>
#include <time.h>
int Food::n_firstRun=0;
Food::Food(void)
{
if(Food::n_firstRun==0)
{
srand((unsigned)time(NULL));
Food::n_firstRun=1;
}
n_hOut=GetStdHandle(STD_OUTPUT_HANDLE);
}
Food::~Food(void)
{
}
int Food::create()
{
score=rand()%10+1;
n_pos.X=rand()%20+1;
n_pos.Y=rand()%20+1;
SetConsoleCursorPosition(n_hOut,n_pos);
printf("&");
return 0;
}
int Food::create(COORD pos)
{
score=1;
n_pos=pos;
SetConsoleCursorPosition(n_hOut,n_pos);
printf("&");
return 0;
}
void Food::disappear()
{
n_stat=0;
}
三、墙体部分
墙体相对而言简单点,只需要初始化并显示,然后蛇运动时判断是否碰撞墙体
1.Wall.h
Wall.h代码如下:
#pragma once
#include<vector>
#include<windows.h>
using namespace std;
class Wall
{
public:
Wall(void);
~Wall(void);
vector<COORD> n_bodyPos;
void init();
void show();
};
2.Wall.cpp
#include "stdafx.h"
#include "Wall.h"
Wall::Wall(void)
{
n_bodyPos.clear();
}
Wall::~Wall(void)
{
}
void Wall::init()
{
for(int i=0;i<22;i++)
{
COORD tmp1={0,0};
COORD tmp=tmp1;
tmp.X=tmp1.X+i;
n_bodyPos.push_back(tmp);
}
for(int i=0;i<22;i++)
{
COORD tmp1={0,0};
COORD tmp=tmp1;
tmp.Y=tmp1.Y+i;
n_bodyPos.push_back(tmp);
}
for(int i=0;i<22;i++)
{
COORD tmp1={21,21};
COORD tmp=tmp1;
tmp.X=tmp1.X-i;
n_bodyPos.push_back(tmp);
}
for(int i=0;i<22;i++)
{
COORD tmp1={21,21};
COORD tmp=tmp1;
tmp.Y=tmp1.Y-i;
n_bodyPos.push_back(tmp);
}
}
void Wall::show()
{
HANDLE n_hOut=GetStdHandle(STD_OUTPUT_HANDLE);
for(int i=0;i<n_bodyPos.size();i++)
{
SetConsoleCursorPosition(n_hOut,n_bodyPos[i]);
printf("#");
}
}
四、游戏主体部分
1.Game.h
Game.h代码如下:
#pragma once
#include "Snake.h"
#include "Food.h"
#include "Wall.h"
class Game
{
public:
Game(void);
~Game(void);
Snake n_snake;
Food n_food;
Wall n_wall;
int score;
HANDLE n_hOut;
int init();
int start();
int end();
void keyBdCtr();
};
2.Game.cpp
#include "stdafx.h"
#include "Game.h"
#include "Snake.h"
#include "Food.h"
#include<conio.h>
#include<windows.h>
Game::Game(void)
{
n_hOut=GetStdHandle(STD_OUTPUT_HANDLE);
}
Game::~Game(void)
{
}
int Game::init()
{
score=0;
n_wall.init();
n_wall.show();
COORD pos={10,10};
n_snake.init(5,pos);
n_snake.show();
COORD pos2={15,10};
n_food.create(pos2);
COORD pos3={0,22};
SetConsoleCursorPosition(n_hOut,pos3);
printf("当前总得分:%d",score);
COORD pos4={0,23};
SetConsoleCursorPosition(n_hOut,pos4);
printf("当前食物分数:%d",n_food.score);
return 0;
}
int Game::start()
{
keyBdCtr();
return 0;
}
int Game::end()
{
COORD pos={0,24};
SetConsoleCursorPosition(n_hOut,pos);
printf("游戏结束!\n");
printf("总得分:%d\n",score);
system("pause");
return 0;
}
void Game::keyBdCtr()
{
char ch=' ';
while(1)
{
if(_kbhit())
{
ch=_getch();
}
switch (ch)
{
case 'w':
{
n_snake.move(DIR_UP);
break;
}
case 'a':
{
n_snake.move(DIR_LEFT);
break;
}
case 's':
{
n_snake.move(DIR_DOWN);
break;
}
case 'd':
{
n_snake.move(DIR_RIGHT);
break;
}
default:
break;
}
Sleep(500);
//判断是否撞墙,结束
for(int i=0;i<n_wall.n_bodyPos.size();i++)
{
if(n_wall.n_bodyPos[i].X==n_snake.n_bodyPos[0].X&&
n_wall.n_bodyPos[i].Y==n_snake.n_bodyPos[0].Y)
{
end();
}
}
//判断蛇咬身体,结束
for(int i=1;i<n_snake.n_bodyLen;i++)
{
if(n_snake.n_bodyPos[i].X==n_snake.n_bodyPos[0].X&&
n_snake.n_bodyPos[i].Y==n_snake.n_bodyPos[0].Y)
{
end();
}
}
//判断与食物碰撞
if(n_food.n_pos.X==n_snake.n_bodyPos[0].X&&
n_food.n_pos.Y==n_snake.n_bodyPos[0].Y)
{
score+=n_food.score;
COORD pos={0,22};
SetConsoleCursorPosition(n_hOut,pos);
printf("当前总得分:%d",score);
n_snake.grow();
n_food.disappear();
Sleep(500);
n_food.create();
COORD pos1={0,23};
SetConsoleCursorPosition(n_hOut,pos1);
printf("当前食物分数:%d",n_food.score);
}
}
}
五、主函数测试
#include "stdafx.h"
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include "Snake.h"
#include "Food.h"
#include "Game.h"
#include <time.h>
#define MAXLEN 30
int _tmain(int argc, _TCHAR* argv[])
{
Game thgame;
thgame.init();
thgame.start();
return 0;
}
六、运行结果展示
资源学习与下载
联系作者
如需要本资源下载也可以直接添加作者QQ,并可以获取资源预览、软件安装、工程导入、协助运行、算法解释、报告协助撰写等售后服务
随时在线,欢迎交流
QQ:2215991436(心源易码 派大星)
备用QQ:402501817(心源易码 佩奇)