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

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

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


开始界面:

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


过程:

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


游戏结束:

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


编码:

控制方向模块:

  1. <span style="font-size:18px;">//*************************************************************************************
  2. //通过键盘a s d w四个键控制上下左右移动方向;
  3. //int waittime; 等待时间,通过这个可以设置游戏的难易程度
  4. //bool &horizMove //允许水平移动标志
  5. //bool &verMove //允许垂直移动标志
  6. //int &moveDirection 具体移动方向,0:向左 1:向右 2:向上 3:向下
  7. //*************************************************************************************
  8. void MoveDirection(int waittime,bool &horizMove,bool &verMove,int &moveDirection)
  9. {
  10. char pointKey=waitKey(waittime);
  11. switch (pointKey)
  12. {
  13. case 'a':
  14. if(horizMove)
  15. {
  16. moveDirection=0;
  17. horizMove=false;
  18. verMove=true;
  19. }
  20. break;
  21. case 'd':
  22. if(horizMove)
  23. {
  24. moveDirection=1;
  25. horizMove=false;
  26. verMove=true;
  27. }
  28. break;
  29. case 's':
  30. if(verMove)
  31. {
  32. moveDirection=3;
  33. horizMove=true;
  34. verMove=false;
  35. }
  36. break;
  37. case 'w':
  38. if(verMove)
  39. {
  40. moveDirection=2;
  41. horizMove=true;
  42. verMove=false;
  43. }
  44. break;
  45. default:
  46. break;
  47. }
  48. }</span>

游戏结束判定模块:

  1. <span style="font-size:18px;">//************************************************************************************
  2. //越界判断游戏是否结束
  3. //传入参数: Box序列
  4. //************************************************************************************
  5. bool GameOver(const vector<Box> arraryBox)
  6. {
  7. if(arraryBox[0].boxPoint.x<0)
  8. {
  9. putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
  10. imshow(windowname,backGroundImage);
  11. return false;
  12. }
  13. if((arraryBox[0].boxPoint.x)>=Width)
  14. {
  15. putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
  16. imshow(windowname,backGroundImage);
  17. return false;
  18. }
  19. if(arraryBox[0].boxPoint.y<0)
  20. {
  21. putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
  22. imshow(windowname,backGroundImage);
  23. return false;
  24. }
  25. if((arraryBox[0].boxPoint.y)>=Hight)
  26. {
  27. putText(backGroundImage,"Game Over!",Point(50,200),1,3,Scalar(0,0,255),2,8,false);
  28. imshow(windowname,backGroundImage);
  29. return false;
  30. }
  31. return true;
  32. }</span>


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

  1. <span style="font-size:18px;">//************************************************************************
  2. //根据移动方向改变第一个box的增长方向
  3. //const int moveDirection: 移动方向,0:向左 1:向右 2:向上 3:向下
  4. //vector<Box> arraryBox :Box 序列
  5. //************************************************************************
  6. void MoveAccordingDirecton(const int moveDirection, vector<Box> &arraryBox,Box & boxTarget)
  7. {
  8. switch (moveDirection)
  9. {
  10. case 0:
  11. arraryBox[0].boxPoint.x-=width;
  12. if(arraryBox[0].boxPoint==boxTarget.boxPoint)
  13. {
  14. arraryBox.insert(arraryBox.begin(),boxTarget);
  15. meetTargetBox=true;
  16. }
  17. break;
  18. case 1:
  19. arraryBox[0].boxPoint.x+=width;
  20. if(arraryBox[0].boxPoint==boxTarget.boxPoint)
  21. {
  22. arraryBox.insert(arraryBox.begin(),boxTarget);
  23. meetTargetBox=true;
  24. }
  25. break;
  26. case 2:
  27. arraryBox[0].boxPoint.y-=hight;
  28. if(arraryBox[0].boxPoint==boxTarget.boxPoint)
  29. {
  30. arraryBox.insert(arraryBox.begin(),boxTarget);
  31. meetTargetBox=true;
  32. }
  33. break;
  34. case 3:
  35. arraryBox[0].boxPoint.y+=hight;
  36. if(arraryBox[0].boxPoint==boxTarget.boxPoint)
  37. {
  38. arraryBox.insert(arraryBox.begin(),boxTarget);
  39. meetTargetBox=true;
  40. }
  41. break;
  42. default:
  43. break;
  44. }
  45. }</span>

蛇身每一个Box移动模块:

  1. <span style="font-size:18px;">//******************************************************************************
  2. //定义蛇身box移动
  3. //每次移动,后一个box移动到前一个box位置
  4. //******************************************************************************
  5. void SnakeMove(vector<Box>&arraryBox1,vector<Box>&arraryBox,Mat &imageBackground)
  6. {
  7. Box bb;
  8. arraryBox1.push_back(bb);
  9. arraryBox1[0]=arraryBox[0];
  10. for(int i=0;i<arraryBox.size();i++)
  11. {
  12. if(i!=0)
  13. {
  14. arraryBox1[1]=arraryBox[i];
  15. arraryBox[i]=arraryBox1[0];
  16. arraryBox1[0]=arraryBox1[1];
  17. }
  18. for(int i=0;i<arraryBox.size();i++)
  19. {
  20. Mat ROICenterPoint=imageBackground(Rect(arraryBox[i].boxPoint.x,arraryBox[i].boxPoint.y,width,hight));
  21. addWeighted(ROICenterPoint,0,arraryBox[i].boxMat,1,0,ROICenterPoint);
  22. }
  23. }
  24. imshow(windowname,imageBackground);
  25. }</span>

主程序:

  1. <span style="font-size:18px;">//*************************************************
  2. //贪吃蛇游戏,C++、Opencv实现
  3. //设计思路:
  4. //1.显示初始画面,蛇头box初始位置为中心,食物box位置随机
  5. //2.按随机方向移动蛇头,按a、s、d、w键控制移动方向,分别为向左,向下,向右,向上
  6. //3.蛇头位置与食物box位置重合,则把食物box加入到蛇身向量arraryBox里,并设置食物box为第一个元素
  7. //4.蛇身各个box移动规律是,每次移动后一个box的位置变为前一个box的位置
  8. //5.蛇头移动超越边界,游戏结束
  9. //*************************************************
  10. #include <core/core.hpp>
  11. #include <highgui/highgui.hpp>
  12. #include <imgproc/imgproc.hpp>
  13. #include <iostream>
  14. #include <time.h>
  15. using namespace std;
  16. using namespace cv;
  17. //定义每个box大小和窗口大小
  18. int width=14;
  19. int hight=14;
  20. int Width=41*width;
  21. int Hight=41*hight;
  22. //定义box类,包含大小和位置信息
  23. class Box
  24. {
  25. public:
  26. Mat boxMat;
  27. Point boxPoint;
  28. Box();
  29. };
  30. Box:: Box()
  31. {
  32. Mat image01(width,hight,CV_8UC3,Scalar(255,255,255));
  33. boxMat=image01;
  34. boxPoint=Point(((Width/width)/2+1)*width,((Hight/hight)/2+1)*hight);
  35. }
  36. vector<Box> arraryBox;
  37. vector<Box> arraryBox1;
  38. Mat image;
  39. int moveDirection; //移动方向,
  40. bool horizMove=true; //水平移动
  41. bool verMove=true; //垂直移动
  42. bool meetTargetBox=false; //是否击中目标box
  43. Box boxTarget;
  44. Mat backGroundImage;
  45. string windowname="Gluttonous Snake ----by 牧野";
  46. //*************************************************************************************
  47. //通过键盘a s d w四个键控制上下左右移动方向;
  48. //int waittime; 等待时间,通过这个可以设置游戏的难易程度
  49. //bool &horizMove //允许水平移动标志
  50. //bool &verMove //允许垂直移动标志
  51. //int &moveDirection 具体移动方向,0:向左 1:向右 2:向上 3:向下
  52. //*************************************************************************************
  53. void MoveDirection(int waittime,bool &horizMove,bool &verMove,int &moveDirection);
  54. //************************************************************************************
  55. //越界判断游戏是否结束
  56. //传入参数: Box序列
  57. //************************************************************************************
  58. bool GameOver(const vector<Box> arraryBox);
  59. //******************************************************************************
  60. //定义蛇身box移动
  61. //每次移动,后一个box移动到前一个box位置
  62. //******************************************************************************
  63. void SnakeMove(vector<Box>&arraryBox1,vector<Box>&arraryBox,Mat &imageBackground);
  64. //************************************************************************
  65. //根据移动方向改变box
  66. //const int moveDirection: 移动方向,0:向左 1:向右 2:向上 3:向下
  67. //vector<Box> arraryBox :Box 序列
  68. //************************************************************************
  69. void MoveAccordingDirecton(const int moveDirection, vector<Box> &arraryBox,Box & boxTarget);
  70. int main(int argc,char* argv[])
  71. {
  72. Box box01;
  73. arraryBox.push_back(box01);
  74. srand(time(0));
  75. boxTarget.boxPoint.x=(rand()%(Width/width))*width;
  76. boxTarget.boxPoint.y=(rand()%(Hight/hight))*hight;
  77. moveDirection=rand()%4; //初始化移动方向 0:向左 1:向右 2 向上 3 乡下
  78. while(true)
  79. {
  80. //判断是否越界,越界则游戏结束
  81. if(!GameOver(arraryBox))
  82. {
  83. break;
  84. }
  85. //初始化显示界面
  86. Mat imageBackground(Width,Hight,CV_8UC3,Scalar(0,0,0));
  87. Mat ROIBackground=imageBackground(Rect(boxTarget.boxPoint.x,boxTarget.boxPoint.y,width,hight));
  88. addWeighted(ROIBackground,0,boxTarget.boxMat,1,0,ROIBackground);
  89. Mat ROICenterPoint=imageBackground(Rect(arraryBox[0].boxPoint.x,arraryBox[0].boxPoint.y,width,hight));
  90. addWeighted(ROICenterPoint,0,arraryBox[0].boxMat,1,0,ROICenterPoint);
  91. if(arraryBox.size()>1)
  92. {
  93. Mat imageBackground01(Width,Hight,CV_8UC3,Scalar(0,0,0));
  94. imageBackground=imageBackground01;
  95. Mat ROIBackground=imageBackground(Rect(boxTarget.boxPoint.x,boxTarget.boxPoint.y,width,hight));
  96. addWeighted(ROIBackground,0,boxTarget.boxMat,1,0,ROIBackground);
  97. }
  98. if(meetTargetBox)
  99. {
  100. boxTarget.boxPoint.x=(rand()%(Width/width))*width;
  101. boxTarget.boxPoint.y=(rand()%(Hight/hight))*hight;
  102. Mat ROIBackground=imageBackground(Rect(boxTarget.boxPoint.x,boxTarget.boxPoint.y,width,hight));
  103. addWeighted(ROIBackground,0,boxTarget.boxMat,1,0,ROIBackground);
  104. meetTargetBox=false;
  105. }
  106. //通过键盘a s d w四个键控制上下左右移动方向;
  107. MoveDirection(10000,horizMove,verMove,moveDirection);
  108. //定义蛇身box移动
  109. SnakeMove(arraryBox1,arraryBox,imageBackground);
  110. //根据移动方向改变第一个box的增长方向
  111. MoveAccordingDirecton(moveDirection, arraryBox,boxTarget);
  112. backGroundImage=imageBackground;
  113. imshow(windowname,imageBackground);
  114. }
  115. waitKey();
  116. }</span>

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