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

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

本篇文章会教大家用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
};
1
2
3
4
5
6
7
8
9
10
11
12
13
上面地图中: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’;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
我们打印一下:
我们发现和我们一维数组里的数字所代表的意义是一样的!

移动:
移动需要记录当前位置和移动的目标位置,比如你向上,那么
当前坐标=(当前坐标-地图宽度)

我们声明如下变量:

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

1
2
3
4
移动方法如下:

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

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

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

1
2
3
4
5
6
7
但是我们的推箱子人物都是可以穿过箱子的目标地点,也就是:

于是有如下代码:

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; //移动人物的坐标
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
那么有了这么一个开头,剩下的三个方向也就以此类推了。

接下来是推箱子部分:
这里我们需要注意的是,推箱子的时候,我们不仅仅要考虑玩家(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;							//移动玩家点
				}
			}
		}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
我们不仅仅要把它推到目标点,还要能够推出来,所以:

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

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

向下:当前坐标=(当前坐标+地图宽度)
向左:当前坐标=(当前坐标-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;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
再于循环体里加入如下代码:

if (Isgameover(map, 3))
{
break;
}
1
2
3
4
完整源码,基于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;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
这里由于博主的编程水平处于学习阶段,此代码并不够高效,如果对代码有任何建议,都可以给博主发邮件,我很欢迎大家来讨论。

作者:汪汪_scb
来源:CSDN
原文:https://blog.csdn.net/Lightinf/article/details/83960744
版权声明:本文为博主原创文章,转载请附上博文链接!

你可能感兴趣的:(推箱子)