c/c++语言开发共享C++入门指南之贪吃蛇游戏的实现

目录参考 《c和c++游戏趣味编程》 贪吃蛇游戏键盘控制小蛇上、下、左、右移动,迟到食物后长度加1;蛇头碰到自身或窗口边缘,游戏失败程序框架#include <graphics.h&

目录

    参考

    • 《c和c++游戏趣味编程》

    贪吃蛇游戏

    键盘控制小蛇上、下、左、右移动,迟到食物后长度加1;蛇头碰到自身或窗口边缘,游戏失败

    程序框架

      #include <graphics.h>  #include <conio.h>  #include <stdio.h>    // 全局变量定义    void startup()                       // 初始化函数  {    }    void show()                          // 绘制函数  {  	  }    void updatewithoutinput()            // 与输入无关的更新  {      }    void updatewithinput()               // 和输入有关的更新  {    }    int main()  {  	startup();                       // 初始化函数,仅执行一次  	while (1)  	{  		show();                      // 进行绘制  		updatewithoutinput();        // 和输入无关的更新  		updatewithinput();           // 和输入有关的更新  	}  	return 0;  }  

    绘制游戏地图和蛇

    绘制网格状的游戏地图,使用二维数组blocks存储每个网格的信息。二维数组blocks中也可以记录蛇的信息。设定元素值为0表示空,画出灰色的方格;元素值为1表示蛇头,蛇头后的蛇身依次为2、3、4、5等正整数,画出彩色的方格

      int i, j;  for (i = 0; i < height; i++)  {  	for (j = 0; j < width; j++)  	{  		if (blocks[i][j] > 0)  		{  			setfillcolor(hsvtorgb(blocks[i][j] * 10, 0.9, 1));  		}  		else  		{  			setfillcolor(rgb(150, 150, 150));  		}  		fillrectangle(j * block_size, i * block_size, (j + 1) * block_size, (i + 1) * block_size);  	}  }  

    C++入门指南之贪吃蛇游戏的实现

    小蛇向右移动

    假设小蛇初始元素值为54321,其中1位蛇头,5432位蛇身。首先将二维数组中所有大于0的元素加1,得到65432;然后将最大值6变成0,即去除了原来的蛇尾;最后将2右边的元素由0变成1,即实现了小蛇向右移动

      void movesnake()  {  	int i, j;  	for (i = 0; i < height; i++)  	{  		for (j = 0; j < width; j++)  		{  			if (blocks[i][j] > 0)  			{  				blocks[i][j]++;  			}  		}  	}  	int oldtail_i, oldtail_j, oldhead_i, oldhead_j;  	int max = 0;  	for (i = 0; i < height; i++)  	{  		for (j = 0; j < width; j++)  		{  			if (max < blocks[i][j])  			{  				max = blocks[i][j];  				oldtail_i = i;  				oldtail_j = j;  			}  			if (blocks[i][j] == 2)  			{  				oldhead_i = i;  				oldhead_j = j;  			}  		}  	}  	int newhead_i = oldhead_i;  	int newhead_j = oldhead_j;  	newhead_j = oldhead_j + 1;  	blocks[newhead_i][newhead_j] = 1;  	blocks[oldtail_i][oldtail_j] = 0;  }  void updatewithoutinput()            // 与输入无关的更新  {  	movesnake();  	sleep(100);  }  

    控制小蛇4个方向移动

    变量oldhead_i、oldhead_j存储移动前的蛇头位置,newhead_i、newhead_j存储移动后的蛇头位置。小蛇向上移动,只需把新蛇头的坐标设为旧蛇头的上方即可

      newhead_i = oldhead_i - 1;  

    让玩家用a、s、d、w键控制游戏角色移动,定义字符变量movedirection表示小蛇运动方向,在movesnake函数中对其值进行判断,取a向左运动、d向右运动、w向上运动、s向下运动:

      if (movedirection == 'a')  {  	newhead_j = oldhead_j - 1;  }  else if (movedirection == 'd')  {  	newhead_j = oldhead_j + 1;  }  else if (movedirection == 'w')  {  	newhead_i = oldhead_i - 1;  }  else if (movedirection == 's')  {  	newhead_i = oldhead_i + 1;  }  

    在updatewithinput()函数中获得用户按键输入,如果是a、s、d、w键之一,就更新movedirection变量,执行movesnake()函数让小蛇向对应方向移动:

      void updatewithinput()               // 和输入有关的更新  {  	if (_kbhit())  	{  		char input = _getch();  		if (input == 'a' || input == 's' || input == 'd' || input == 'w')  		{  			movedirection = input;  			movesnake();  		}  	}  }  

    时间控制的改进

    在sleep()函数运行时,整个程序都会暂停,包括用户输入模块。用户会感觉到卡顿

    利用静态变量,将updatewithoutinput()修改如下:

      void updatewithoutinput()            // 与输入无关的更新  {  	static int waitindex = 1;  	waitindex++;                     // 每一帧加1  	if (waitindex == 10)  	{  		movesnake();  		waitindex = 1;  	}  }  

    其中,updatewithoutinput()每次运行时,waitindex加1,每隔10帧,才执行一次移动函数movesnake()。这样可在不影响用户按键输入的情况下,降低小蛇的移动速度

    失败判断与显示

    定义全局变量isfailure表示游戏是否失败,初始化为0:

      int isfailure = 0;  

    当小蛇碰到画面边界时,则认为游戏失败;当蛇头与蛇身发生碰撞时,游戏也失败。由于每次只有蛇头是新生成的位置,所以在movesnake()函数中只需判断蛇头是否越过边界和碰撞:

      	if (newhead_i >= height || newhead_i < 0 || newhead_j >= width || newhead_j < 0 || blocks[newhead_i][newhead_j] > 0)   	{  		isfailure = 1;  		return;  	}    在show()函数中添加游戏失败后的显示信息:  	if (isfailure)                   // 游戏失败  	{  		setbkmode(transparent);      // 文字字体透明  		settextcolor(rgb(255, 0, 0));  		settextstyle(80, 0, _t("宋体"));  		outtextxy(240, 220, _t("游戏失败"));  	}  

    在updatewithoutinput()中添加代码,当isfailure为1时,直接返回:

      void updatewithoutinput()            // 与输入无关的更新  {   if (isfailure)   {    return;   }   //...  }  

    在updatewithinput()中,只有当按下键盘且isfailure为0时,才进行相应的处理:

      void updatewithinput()               // 和输入有关的更新  {   if (_kbhit() && isfailure == 0)   {    // ...   }  }  

    添加食物

    添加全局变量记录食物的位置:

      int food_i, food_j;    在startup()函数中初始化食物的位置:    void startup()                       // 初始化函数  {   food_i = rand() % (height - 5) + 2;   food_j = rand() % (width - 5) + 2;  }  

    在show()函数中在食物位置处绘制一个绿色小方块:

      setfillcolor(rgb(0, 255, 0));  fillrectangle(food_j * block_size, food_i * block_size, (food_j + 1) * block_size, (food_i + 1) * block_size);  

    当新蛇头碰到食物时,只需保留原蛇尾,即可让蛇的长度加1。当吃到食物时,食物位置重新随机出现,蛇长度加1;当没有迟到食物时,旧蛇尾变成空白,蛇长度保持不变:

      blocks[newhead_i][newhead_j] = 1;// 新蛇头位置数值为1  if (newhead_i == food_i && newhead_j == food_j) // 如果新蛇头碰到食物  {   food_i = rand() % (height - 5) + 2; // 食物重新随机位置   food_j = rand() % (width - 5) + 2;  }  else  {   blocks[oldtail_i][oldtail_j] = 0;   // 旧蛇尾变成空白  }  

    完整代码

      #include <graphics.h>  #include <conio.h>  #include <stdio.h>  #define block_size 20                // 每个小格子的长宽  #define height 30                    // 高度上一共30个小格子  #define width 40                     // 宽度上一共40个小格子    // 全局变量定义  int blocks[height][width] = { 0 };  char movedirection;  int isfailure = 0;  int food_i, food_j;                  // 食物的位置    void startup()                       // 初始化函数  {   int i;   blocks[height / 2][width / 2] = 1;  // 画面中间画蛇头   for (i = 1; i <= 4; i++)            // 向左依次4个蛇身   {    blocks[height / 2][width / 2 - i] = i + 1;   }   movedirection = 'd';   food_i = rand() % (height - 5) + 2;   food_j = rand() % (width - 5) + 2;   initgraph(width * block_size, height * block_size);   setlinecolor(rgb(200, 200, 200));   beginbatchdraw();                   // 开始批量绘制  }    void show()                          // 绘制函数  {   cleardevice();   int i, j;   for (i = 0; i < height; i++)   {    for (j = 0; j < width; j++)    {     if (blocks[i][j] > 0)     {      setfillcolor(hsvtorgb(blocks[i][j] * 10, 0.9, 1));     }     else     {      setfillcolor(rgb(150, 150, 150));     }     fillrectangle(j * block_size, i * block_size, (j + 1) * block_size, (i + 1) * block_size);    }   }   setfillcolor(rgb(0, 255, 0));    // 食物颜色为绿色   fillrectangle(food_j * block_size, food_i * block_size, (food_j + 1) * block_size, (food_i + 1) * block_size);     if (isfailure)                   // 游戏失败   {    setbkmode(transparent);      // 文字字体透明    settextcolor(rgb(255, 0, 0));    settextstyle(80, 0, _t("宋体"));    outtextxy(240, 220, _t("游戏失败"));   }   flushbatchdraw();                // 批量绘制  }    void movesnake()  {   int i, j;   for (i = 0; i < height; i++)   {    for (j = 0; j < width; j++)    {     if (blocks[i][j] > 0)     // 大于0的为小蛇元素     {      blocks[i][j]++;     }    }   }   int oldtail_i, oldtail_j, oldhead_i, oldhead_j; // 存储旧蛇   int max = 0;   for (i = 0; i < height; i++)   {    for (j = 0; j < width; j++)    {     if (max < blocks[i][j])     {      max = blocks[i][j];      oldtail_i = i;      oldtail_j = j;     }     if (blocks[i][j] == 2)      // 旧蛇头     {      oldhead_i = i;      oldhead_j = j;     }    }   }   int newhead_i = oldhead_i;          // 设定变量存储新蛇头   int newhead_j = oldhead_j;     if (movedirection == 'a')           // 根据用户按键,设定新蛇头的位置   {    newhead_j = oldhead_j - 1;   }   else if (movedirection == 'd')   {    newhead_j = oldhead_j + 1;   }   else if (movedirection == 'w')   {    newhead_i = oldhead_i - 1;   }   else if (movedirection == 's')   {    newhead_i = oldhead_i + 1;   }      if (newhead_i >= height || newhead_i < 0 || newhead_j >= width || newhead_j < 0 || blocks[newhead_i][newhead_j] > 0) // 失败条件   {    isfailure = 1;    return;   }     blocks[newhead_i][newhead_j] = 1;               // 新蛇头位置数值为1   if (newhead_i == food_i && newhead_j == food_j) // 如果新蛇头碰到食物   {    food_i = rand() % (height - 5) + 2;         // 食物重新随机位置    food_j = rand() % (width - 5) + 2;   }   else   {    blocks[oldtail_i][oldtail_j] = 0;           // 旧蛇尾变成空白   }  }  void updatewithoutinput()                           // 与输入无关的更新  {   if (isfailure)   {    return;   }   static int waitindex = 1;   waitindex++;                                     // 每一帧加1   if (waitindex == 10)   {    movesnake();    waitindex = 1;   }  }    void updatewithinput()                                // 和输入有关的更新  {   if (_kbhit() && isfailure == 0)   {    char input = _getch();    if (input == 'a' || input == 's' || input == 'd' || input == 'w')    {     movedirection = input;     movesnake();    }   }  }    int main()  {   startup();                       // 初始化函数,仅执行一次   while (1)   {    show();                      // 进行绘制    updatewithoutinput();        // 和输入无关的更新    updatewithinput();           // 和输入有关的更新   }   return 0;  }    

    总结

    到此这篇关于c++入门指南之贪吃蛇游戏实现的文章就介绍到这了,更多相关c++实现贪吃蛇游戏内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!

    需要了解更多c/c++开发分享C++入门指南之贪吃蛇游戏的实现,都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!

    www.ctvol.com true Article c/c++语言开发共享C++入门指南之贪吃蛇游戏的实现

    本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

    ctvol管理联系方式QQ:251552304

    本文章地址:https://www.ctvol.com/c-cdevelopment/859671.html

    (0)
    上一篇 2021年10月18日 上午4:56
    下一篇 2021年10月18日 上午4:58

    精彩推荐