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

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

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


开始界面:



过程:



游戏结束:



编码:

控制方向模块:

  
  
  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>

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