博主最近在学习关于C++的一些基础,这是本人突发奇想做的一个小游戏,编程其实并不难,重要的是,你的思路,以及优化,当然,这个小游戏,本人也是基于一个学习者编写的
这是游戏开始时的界面。
当然,如果你喜欢,你可以任意更改地图:
当把所有箱子推到目的地,就完成游戏
当有一个问题出现的时候,我们首先应该先考虑这个问题有可能的解法:
这里博主想到的方法是
1. 通过二维数组来存储地图信息
2. 通过交换数组元素,来达到角色移动的目的
3. 而推箱子,则让箱子和角色同步移动便可。
4. 移动控制:_getch()
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)的下一个坐标的情况,还要考虑箱子的移动坐标是否超出了我们的地图,那么通过本人总结,那么箱子前进的时候,玩家和箱子会遇到如下的情况:
玩家有两种情况:
于是,我们有如下代码:
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;
}
完整源码,基于Vs2017:
#include
#include
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;
}
}
int main()
{
int input; //输入常数
int nowpoint=31; //玩家现在的地点
int shift; //玩家目标点
const int w=10; //地图宽度
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
};
while (true)
{
system("cls");
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';
}
if (Isgameover(map, 3))
{
break;
}
input=_getch();
//往上
if (input=='w'||input=='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;
}
}
else if (shift == 4) //当下一个个目标点为箱子目标点时
{
map[nowpoint - w] = 5; //目标点变为人和箱子重合的图案
map[nowpoint] = 0; //当前点变为空地
nowpoint -= w; //移动人物的坐标
}
else if (shift == 6&& map[nowpoint - 2 * w] != 1) //如果下一个点为箱子和箱子的目标点重合
{
map[nowpoint - 2*w] = 3; //目标点的下一个点变为箱子
map[nowpoint - w] = 5; //下一个点变为和人重合
map[nowpoint] = 0; //人物当前点变为空地
nowpoint -= w;
}
else 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; //移动玩家点
}
}
}
}
//往下
else if (input == 's' || input == 'S')
{
shift = map[nowpoint+w];
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;
}
}
else if (shift==4)
{
map[nowpoint + w] = 5;
map[nowpoint] = 0;
nowpoint += w;
}
else if (shift == 6 && map[nowpoint + 2 * w] != 1)
{
map[nowpoint + 2*w] = 3;
map[nowpoint + w] = 5;
map[nowpoint] = 0;
nowpoint += w;
}
else 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;
}
}
}
}
//往左
else if (input == 'a' || input == 'A')
{
shift = map[nowpoint-1];
if (shift == 0)
{
if (map[nowpoint] == 5)
{
map[nowpoint] = 2;
map[nowpoint - 1] = map[nowpoint];
map[nowpoint] = 4;
nowpoint -= 1;
}
else
{
map[nowpoint - 1] = map[nowpoint];
map[nowpoint] = shift;
nowpoint -= 1;
}
}
else if (shift == 4)
{
map[nowpoint -1] = 5;
map[nowpoint] = 0;
nowpoint -= 1;
}
else if (shift == 6 && map[nowpoint - 2] != 1)
{
map[nowpoint - 2] = 3;
map[nowpoint - 1] = 5;
map[nowpoint] = 0;
nowpoint -= 1;
}
else if (shift == 3)
{
if (map[nowpoint - 2]!=1 && map[nowpoint - 2] != 3 && map[nowpoint - 2] != 6)
{
if (map[nowpoint - 2]==4)
{
map[nowpoint - 1] = map[nowpoint - 2];
map[nowpoint - 2] = 6;
map[nowpoint - 1] = map[nowpoint];
map[nowpoint] = 0;
nowpoint -= 1;
}
else if (map[nowpoint] == 5)
{
map[nowpoint - 1] = map[nowpoint - 2];
map[nowpoint - 2] = shift;
map[nowpoint - 1] = 2;
map[nowpoint] = 4;
nowpoint -= 1;
}
else
{
map[nowpoint - 2] = shift;
map[nowpoint - 1] = map[nowpoint];
map[nowpoint] = 0;
nowpoint -= 1;
}
}
}
}
//往右
else if (input == 'd' || input == 'D')
{
shift = map[nowpoint+1];
if (shift == 0)
{
if (map[nowpoint] == 5)
{
map[nowpoint] = 2;
map[nowpoint + 1] = map[nowpoint];
map[nowpoint] = 4;
nowpoint += 1;
}
else
{
map[nowpoint + 1] = map[nowpoint];
map[nowpoint] = shift;
nowpoint += 1;
}
}
else if (shift == 4)
{
map[nowpoint + 1] = 5;
map[nowpoint] = 0;
nowpoint += 1;
}
else if (shift == 6 && map[nowpoint +2] != 1)
{
map[nowpoint + 2] = 3;
map[nowpoint + 1] = 5;
map[nowpoint] = 0;
nowpoint += 1;
}
else if (shift == 3)
{
if (map[nowpoint + 2]!=1 && map[nowpoint + 2] != 3 && map[nowpoint + 2 ] != 6)
{
if (map[nowpoint + 2] == 4)
{
map[nowpoint + 1] = map[nowpoint + 2];
map[nowpoint + 2] = 6;
map[nowpoint + 1] = map[nowpoint];
map[nowpoint] = 0;
nowpoint += 1;
std::cout << "!!!";
}
else if (map[nowpoint] == 5)
{
map[nowpoint + 1] = map[nowpoint + 2];
map[nowpoint + 2] = shift;
map[nowpoint + 1] = 2;
map[nowpoint] = 4;
nowpoint += 1;
std::cout << "!!";
}
else
{
map[nowpoint + 2] = shift;
map[nowpoint + 1] = map[nowpoint];
map[nowpoint] = 0;
nowpoint += 1;
std::cout << "!";
}
}
}
}
}
system("pause");
return 0;
}
这里由于博主的编程水平处于学习阶段,此代码并不够高效,如果对代码有任何建议,都可以给博主发邮件,我很欢迎大家来讨论。