• 贪吃蛇小游戏—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>

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


  • 相关阅读:
    认识正向代理与反向代理
    python中and和or的用法
    怎样查看端口的占用情况?
    配置FCKeditor
    Ant工具(二)
    myeclipse 提示错误Undefined exploded archive location&deploy project 时不能正常显示 问题的解决
    FCKediter
    Ant工具(一)
    MyEclipse 总是弹出“multiple Errors have Occurred”
    linux下svn的常用代码
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9411998.html
Copyright © 2020-2023  润新知