美文网首页C语言
一个适合初学者的C++推箱子小游戏

一个适合初学者的C++推箱子小游戏

作者: _年少无为 | 来源:发表于2018-12-27 19:09 被阅读0次

序言

最近在学习关于C++的一些基础,突发奇想做一个小游戏,编程其实并不难,重要的是,你的思路,以及优化,当然,这个小游戏,本人也是基于一个学习者编写的

游戏开始时的界面。

可以任意更改地图,当把所有箱子推到目的地,就完成游戏

【文章福利】:小编有自己的学习交流群728483370!进群可以免费领取C/C++基础到项目实战资料

当有一个问题出现的时候,我们首先应该先考虑这个问题有可能的解法:

这里想到的方法是

  1. 通过二维数组来存储地图信息

  2. 通过交换数组元素,来达到角色移动的目的

  3. 而推箱子,则让箱子和角色同步移动便可。

ps:_getch()方法需要头文件conio.h的支持,功能是不需要按回车键便可以得到输入的字符

那么这里我们有了大概的思路,但是再实际操作中,我们发现二维数组并不方便,因为它有两个下标,会加剧问题的复杂度,这里我们用 一维数组 便可。

移动:我们知道地图是一个方形:要么是m*n,要么就是m^2(正方形);

这里我们简单绘制一个长4,宽4的长方体来说明:

如果我在5的位置,那么我要 左移,应该是当前位置 -1,同样,向右便是 +1,向上 -4,向下 +4。

有了这些知识,我们便可以开始编程了,首先写出地图:

int map[100] =                   //玩家地图
 {
  1,1,1,1,1,1,1,1,1,1,
  1,0,0,0,0,0,0,0,0,1,
  1,0,0,0,3,0,4,0,0,1,
  1,2,0,0,0,0,0,0,0,1,
  1,0,0,0,0,0,0,0,0,1,
  1,0,0,3,0,4,0,0,0,1,
  1,0,0,0,0,0,0,0,0,1,
  1,0,0,0,3,0,0,0,0,1,
  1,0,0,0,0,0,0,4,0,1,
  1,1,1,1,1,1,1,1,1,1
 };

上面地图中: 0代表空地,1代表墙壁,2代表玩家,3代表箱子,4代表箱子目的地,5代表当人和箱子目的地重合的时候显示的图标,6代表箱子放在正确位置时候的图标

for (int i = 0; i < 100; i++)
  {
   switch (map[i])
   {
   case 1:std::cout << "□"; break;     //墙壁
   case 0:std::cout << "  "; break;     //空地
   case 2:std::cout << "Pe"; break;     //人
   case 3:std::cout << "■"; break;    //箱子
   case 4:std::cout << "**"; break;    //箱子目的地
   case 5:std::cout << "×"; break;    //和人重合
   case 6:std::cout << "√"; break;    //和箱子重合
   }
   if (i % w == 9)
    std::cout << '\n';
  }

我们打印一下:

我们发现和我们一维数组里的数字所代表的意义是一样的!

移动需要记录当前位置和移动的目标位置,比如你向上,那么

当前坐标=(当前坐标-地图宽度)

我们声明如下变量:

int input;                      //输入常数
    int nowpoint=31;                //玩家现在的地点
    int shift;                       //玩家目标点
    const int w=10;                  //地图宽度

移动方法如下:

shift = map[nowpoint-w];         //把目标点赋值给shift
                    map[nowpoint - w] = map[nowpoint];     
                    map[nowpoint] = shift;                   //移动目标点
                    nowpoint -= w;                              //移动当前所处的坐标位置

当然,我们要保证它不会“穿墙”:于是:

shift = map[nowpoint-w];
            if (shift == 0)              //目标点必须是空地才能移动!
            {
                    map[nowpoint - w] = map[nowpoint];
                    map[nowpoint] = shift;
                    nowpoint -= w;
            }

但是我们的推箱子人物都是可以穿过箱子的目标地点,于是有如下代码:

shift = map[nowpoint-w];         //下一个移动的目标点设置给shift
            if (shift ==0)                    //当下一个目标是空地的时候
            {
                if (map[nowpoint] == 5)       //当和箱子目标点重合的时候且需要移动到空地
                {
                    map[nowpoint] = 2;               //当前坐标设置为玩家
                    map[nowpoint - w] = map[nowpoint];    //下一个坐标为玩家
                    map[nowpoint] = 4;              //当前坐标为箱子目标点
                    nowpoint -= w;                  //移动当前坐标
                }
                else                        //如果没有和箱子目标点重合,则正常移动
                {
                    map[nowpoint - w] = map[nowpoint];     
                    map[nowpoint] = shift;
                    nowpoint -= w;
                }
            }
            if (shift == 4)                  //当下一个个目标点为箱子目标点时
            {
                map[nowpoint - w] = 5;            //目标点变为人和箱子重合的图案
                map[nowpoint] = 0;                //当前点变为空地
                nowpoint -= w;                    //移动人物的坐标
            }

那么有了这么一个开头,剩下的三个方向也就以此类推了。

接下来是推箱子部分:

这里我们需要注意的是,推箱子的时候,我们不仅仅要考虑玩家(2)的下一个坐标的情况,还要考虑箱子的移动坐标是否超出了我们的地图,那么通过本人总结,那么箱子前进的时候,玩家和箱子会遇到如下的情况:

  • 前方是墙壁
  • 前方是箱子
  • 前方是箱子目的地
  • 前方是放好的箱子
  • 前方是空地

玩家有两种情况:

1.玩家处于箱子目的地的时候推箱子
2.玩家处于箱子目的地,但是推动的方向是墙壁
于是,我们有如下代码:

if (shift == 3)                    //目标点为箱子
            {
                if (map[nowpoint- 2 * w]!=1&& map[nowpoint - 2 * w] != 3 && map[nowpoint - 2 * w] != 6)         //箱子的下一个目标点不能是墙壁,或者箱子
                {
                    if (map[nowpoint - 2 * w] == 4)                     //箱子的下一个目标点是箱子目的地
                    {
                        map[nowpoint - 2*w] = 6;                       //箱子的下一个目标点变为和箱子重合
                        map[nowpoint - w] = map[nowpoint];             //箱子的位置变为玩家位置
                        map[nowpoint] = 0;                             //玩家为之变为空地
                        nowpoint -= w;                                 //移动玩家坐标
                    }
                    else if (map[nowpoint] == 5)                       //目标点为箱子,并且玩家处在箱子目标点里面
                    {
                        map[nowpoint -w] = map[nowpoint - 2*w];         //箱子向上
                        map[nowpoint - 2*w] = shift;                  // 箱子目标点变为人物目标点
                        map[nowpoint - w ]= 2;                        //箱子位置变为玩家
                        map[nowpoint] = 4;                          //玩家上一个点变为箱子目的地
                        nowpoint -= w;
                    }
                    else                                          //其他情况自由移动
                    {
                        map[nowpoint - 2*w] = shift;             //箱子的目标点变为箱子
                        map[nowpoint - w] = map[nowpoint];       //玩家目标点变为玩家
                        map[nowpoint] = 0;                      //玩家下面的点变为空地
                        nowpoint -= w;                          //移动玩家点
                    }
                }
            }

我们不仅仅要把它推到目标点,还要能够推出来,所以:

if (shift == 6&& map[nowpoint - 2 * w] != 1)                  //如果下一个点为重合点,且前方不是墙壁
            {
                map[nowpoint - 2*w] = 3;                     //目标点的下一个点变为箱子
                map[nowpoint - w] = 5;                       //下一个点变为和人重合
                map[nowpoint] = 0;                           //人物当前点变为空地
                nowpoint -= w;                                //变换当前坐标
            }

我们解决了一个方向的移动问题,那么接下来的移动,和前面类似,只需要改变移动变量就可以了。

向下:当前坐标=(当前坐标+地图宽度)

向左:当前坐标=(当前坐标-1)

向右:当前坐标=(当前坐标+1)

当你需要修改地图的时候, 只需要修改数组里面的的1 就可以了,如果觉得图案自己不喜欢,那么 在switch里面就可以更换。

游戏结束判断:

我们做了移动和推箱子,但是并没有游戏成功的判定:我们加上如下判断成功的语句:

bool Isgameover(int *map,int Rbox)     //Rbox  为了方便拓展,此参数为目的地个数
{
    int n=0;
    for (int i = 0; i < 100; i++)
    {
        if (*(map+i)==6)
        {
            n++;
        }
    }
    if (Rbox == n)
    {
        std::cout << "恭喜通关!!!\n";
        return true;
    }
    else
    {
        return false;
    }
}

再于循环体里加入如下代码:

if (Isgameover(map, 3))
        {
            break;
        }

最后

这里由于小编的编程水平处于学习阶段,此代码并不够高效,如果对代码有任何建议,都可以添加小编的学习交流群728483370,欢迎大家来讨论。

福利

需要C/C++资料的朋友,因为平台不能发文件,可以添加小编的学习交流群728483370,资料就在群文件里。

相关文章

网友评论

    本文标题:一个适合初学者的C++推箱子小游戏

    本文链接:https://www.haomeiwen.com/subject/puydlqtx.html