贪吃蛇小游戏—C++、Opencv编写实现

贪吃蛇游戏,C++、Opencv实现

设计思路:
1.显示初始画面,蛇头box初始位置为中心,食物box位置随机
2.按随机方向移动蛇头,按a、s、d、w键控制移动方向,分别为向左,向下,向右,向上
3.蛇头位置与食物box位置重合,则把食物box加入到蛇身向量arraryBox里,并设置食物box为第一个元素
4.蛇身各个box移动规律是,每次移动后一个box的位置变为前一个box的位置
5.蛇头移动超越边界,游戏结束


开始界面:



过程:



游戏结束:



编码:

控制方向模块:

<span style="font-size:18px;">//*************************************************************************************
//通过键盘a s d w四个键控制上下左右移动方向;
//int waittime; 等待时间,通过这个可以设置游戏的难易程度
//bool &horizMove //允许水平移动标志
//bool &verMove //允许垂直移动标志
//int &moveDirection  具体移动方向,0:向左  1:向右  2:向上  3:向下
//*************************************************************************************
void MoveDirection(int waittime,bool &horizMove,bool &verMove,int &moveDirection)
{
	char pointKey=waitKey(waittime);
	switch (pointKey)
	{
	case 'a':
		if(horizMove)
		{
			moveDirection=0;
			horizMove=false;
			verMove=true;
		}
		break;
	case 'd':
		if(horizMove)
		{
			moveDirection=1;
			horizMove=false;
			verMove=true;
		}
		break;
	case 's':
		if(verMove)
		{
			moveDirection=3;
			horizMove=true;
			verMove=false;
		}
		break;

	case 'w':
		if(verMove)
		{
			moveDirection=2;
			horizMove=true;
			verMove=false;
		}
		break;
	default:
		break;
	}	
}</span>

游戏结束判定模块:

<span style="font-size:18px;">//************************************************************************************
//越界判断游戏是否结束
//传入参数: Box序列
//************************************************************************************
bool GameOver(const vector<Box> arraryBox)
{
	if(arraryBox[0].boxPoint.x<0)
	{

		putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
		imshow(windowname,backGroundImage);
		return false;
	}
	if((arraryBox[0].boxPoint.x)>=Width)
	{
		putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
		imshow(windowname,backGroundImage);
		return false;
	}
	if(arraryBox[0].boxPoint.y<0)
	{
		putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
		imshow(windowname,backGroundImage);	
		return false;
	}
	if((arraryBox[0].boxPoint.y)>=Hight)
	{
		putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
		imshow(windowname,backGroundImage);
		return false;
	}
	return true;
}</span>


蛇身序列第一个(蛇头)Box根据移动方向移动模块:

<span style="font-size:18px;">//************************************************************************
//根据移动方向改变第一个box的增长方向
//const int moveDirection: 移动方向,0:向左  1:向右  2:向上  3:向下
//vector<Box> arraryBox :Box 序列
//************************************************************************
void MoveAccordingDirecton(const int moveDirection, vector<Box> &arraryBox,Box & boxTarget)
{	
	switch (moveDirection)
	{
	case 0:
		arraryBox[0].boxPoint.x-=width;

		if(arraryBox[0].boxPoint==boxTarget.boxPoint)
		{
			arraryBox.insert(arraryBox.begin(),boxTarget);
			meetTargetBox=true;
		}
		break;
	case 1:
		arraryBox[0].boxPoint.x+=width;
		if(arraryBox[0].boxPoint==boxTarget.boxPoint)
		{
			arraryBox.insert(arraryBox.begin(),boxTarget);
			meetTargetBox=true;
		}
		break;
	case 2:
		arraryBox[0].boxPoint.y-=hight;
		if(arraryBox[0].boxPoint==boxTarget.boxPoint)
		{
			arraryBox.insert(arraryBox.begin(),boxTarget);
			meetTargetBox=true;
		}
		break;
	case 3:
		arraryBox[0].boxPoint.y+=hight;	
		if(arraryBox[0].boxPoint==boxTarget.boxPoint)
		{
			arraryBox.insert(arraryBox.begin(),boxTarget);
			meetTargetBox=true;
		}
		break;
	default:
		break;
	}
}</span>

蛇身每一个Box移动模块:

<span style="font-size:18px;">//******************************************************************************
//定义蛇身box移动
//每次移动,后一个box移动到前一个box位置
//******************************************************************************
void SnakeMove(vector<Box>&arraryBox1,vector<Box>&arraryBox,Mat &imageBackground)
{
	Box bb;
	arraryBox1.push_back(bb);
	arraryBox1[0]=arraryBox[0];
	for(int i=0;i<arraryBox.size();i++)
	{
		if(i!=0)
		{
			arraryBox1[1]=arraryBox[i];
			arraryBox[i]=arraryBox1[0];
			arraryBox1[0]=arraryBox1[1];
		}
		for(int i=0;i<arraryBox.size();i++)
		{
			Mat ROICenterPoint=imageBackground(Rect(arraryBox[i].boxPoint.x,arraryBox[i].boxPoint.y,width,hight));
			addWeighted(ROICenterPoint,0,arraryBox[i].boxMat,1,0,ROICenterPoint);
		}
	}
	imshow(windowname,imageBackground);
}</span>

主程序:

<span style="font-size:18px;">//*************************************************
//贪吃蛇游戏,C++、Opencv实现
//设计思路:
//1.显示初始画面,蛇头box初始位置为中心,食物box位置随机
//2.按随机方向移动蛇头,按a、s、d、w键控制移动方向,分别为向左,向下,向右,向上
//3.蛇头位置与食物box位置重合,则把食物box加入到蛇身向量arraryBox里,并设置食物box为第一个元素
//4.蛇身各个box移动规律是,每次移动后一个box的位置变为前一个box的位置
//5.蛇头移动超越边界,游戏结束
//*************************************************


#include <core/core.hpp>
#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>
#include <iostream>
#include <time.h>

using namespace std;
using namespace cv;

//定义每个box大小和窗口大小
int width=14;
int hight=14;
int Width=41*width;
int Hight=41*hight;

//定义box类,包含大小和位置信息
class  Box
{
public:
	Mat boxMat;
	Point boxPoint;
	Box();	
};

Box:: Box()
{
	Mat image01(width,hight,CV_8UC3,Scalar(255,255,255));
	boxMat=image01;
	boxPoint=Point(((Width/width)/2+1)*width,((Hight/hight)/2+1)*hight);

}

vector<Box> arraryBox;
vector<Box> arraryBox1;
Mat image;
int moveDirection;   //移动方向,

bool horizMove=true;   //水平移动
bool verMove=true;  //垂直移动
bool meetTargetBox=false;  //是否击中目标box
Box boxTarget;
Mat backGroundImage;
string windowname="Gluttonous Snake ----by 牧野";

//*************************************************************************************
//通过键盘a s d w四个键控制上下左右移动方向;
//int waittime; 等待时间,通过这个可以设置游戏的难易程度
//bool &horizMove //允许水平移动标志
//bool &verMove //允许垂直移动标志
//int &moveDirection  具体移动方向,0:向左  1:向右  2:向上  3:向下
//*************************************************************************************
void MoveDirection(int waittime,bool &horizMove,bool &verMove,int &moveDirection);


//************************************************************************************
//越界判断游戏是否结束
//传入参数: Box序列
//************************************************************************************
bool GameOver(const vector<Box> arraryBox);



//******************************************************************************
//定义蛇身box移动
//每次移动,后一个box移动到前一个box位置
//******************************************************************************
void SnakeMove(vector<Box>&arraryBox1,vector<Box>&arraryBox,Mat &imageBackground);



//************************************************************************
//根据移动方向改变box
//const int moveDirection: 移动方向,0:向左  1:向右  2:向上  3:向下
//vector<Box> arraryBox :Box 序列
//************************************************************************
void MoveAccordingDirecton(const int moveDirection, vector<Box> &arraryBox,Box & boxTarget);

int main(int argc,char* argv[])
{	
	Box box01;
	arraryBox.push_back(box01);
	srand(time(0));
	boxTarget.boxPoint.x=(rand()%(Width/width))*width;
	boxTarget.boxPoint.y=(rand()%(Hight/hight))*hight;
	moveDirection=rand()%4;  //初始化移动方向  0:向左   1:向右   2 向上  3 乡下   
	while(true)
	{
		//判断是否越界,越界则游戏结束
		if(!GameOver(arraryBox))
		{
			break;
		}
		//初始化显示界面
		Mat imageBackground(Width,Hight,CV_8UC3,Scalar(0,0,0));
		Mat ROIBackground=imageBackground(Rect(boxTarget.boxPoint.x,boxTarget.boxPoint.y,width,hight));
		addWeighted(ROIBackground,0,boxTarget.boxMat,1,0,ROIBackground);

		Mat ROICenterPoint=imageBackground(Rect(arraryBox[0].boxPoint.x,arraryBox[0].boxPoint.y,width,hight));
		addWeighted(ROICenterPoint,0,arraryBox[0].boxMat,1,0,ROICenterPoint);

		if(arraryBox.size()>1)
		{
			Mat imageBackground01(Width,Hight,CV_8UC3,Scalar(0,0,0));
			imageBackground=imageBackground01;
			Mat ROIBackground=imageBackground(Rect(boxTarget.boxPoint.x,boxTarget.boxPoint.y,width,hight));
			addWeighted(ROIBackground,0,boxTarget.boxMat,1,0,ROIBackground);
		}

		if(meetTargetBox)
		{
			boxTarget.boxPoint.x=(rand()%(Width/width))*width;
			boxTarget.boxPoint.y=(rand()%(Hight/hight))*hight;
			Mat ROIBackground=imageBackground(Rect(boxTarget.boxPoint.x,boxTarget.boxPoint.y,width,hight));
			addWeighted(ROIBackground,0,boxTarget.boxMat,1,0,ROIBackground);
			meetTargetBox=false;
		}

		//通过键盘a s d w四个键控制上下左右移动方向;
		MoveDirection(10000,horizMove,verMove,moveDirection);

		//定义蛇身box移动
		SnakeMove(arraryBox1,arraryBox,imageBackground);

		//根据移动方向改变第一个box的增长方向
		MoveAccordingDirecton(moveDirection, arraryBox,boxTarget);

		backGroundImage=imageBackground;
		imshow(windowname,imageBackground);
	}
	waitKey();
}</span>

原理很简单,部分代码有注释,就不多说了,欢迎探讨。


原文地址:https://www.cnblogs.com/mtcnn/p/9411998.html