首页后端开发其他后端知识用C++指针怎样制作简易的贪吃蛇小游戏?

用C++指针怎样制作简易的贪吃蛇小游戏?

时间2024-03-29 00:26:03发布访客分类其他后端知识浏览1478
导读:这篇文章给大家分享的是用C++制作简易的贪吃蛇小游戏的内容。这里使用的是C++指针实现的方法,对新手学习和理解指针的使用有一定的帮助,因此分享给大家做个参考,文中示例代码介绍的很详细,感兴趣的朋友接下来一起跟随小编看看吧。 贪吃蛇游戏...

这篇文章给大家分享的是用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);

	}

}

小蛇向右移动

假设小蛇初始元素值为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++有帮助,想要了解更多可以继续浏览网络其他相关的文章。

文本转载自脚本之家

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: 用C++指针怎样制作简易的贪吃蛇小游戏?
本文地址: https://pptw.com/jishu/655298.html
C语言中为何要用指针?一文带你了解指针的用处 C++中虚函数作用是什么,虚函数表你了解多少?

游客 回复需填写必要信息