经过四次的修改和优化,终于将推箱子这个游戏完整的写出来了,今天就像大家分享一下这个游戏的编写。
这个游戏界面的编写总的来说不困难,主要是推动箱子的算法。
(1)利用数组和windows api 即可写出界面
1 #define N 15
2 #define M 15
3 int map[N][M] = {
4 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
5 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
6 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
7 { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 },//0->空白
8 { 0, 0, 0, 0, 1, 0, 2, 1, 1, 1, 0, 0, 0, 0, 0 },//1->墙
9 { 0, 0, 0, 0, 1, 0, 3, 0, 0, 1, 0, 0, 0, 0, 0 },//2->人
10 { 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0 },//3->箱子
11 { 0, 0, 0, 1, 4, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0 },//4->位置
12 { 0, 0, 0, 1, 4, 3, 0, 0, 1, 0, 1, 0, 0, 0, 0 },
13 { 0, 0, 0, 1, 4, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0 },
14 { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
15 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
16 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
17 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
18 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
19
20 void PushBox::Color(int m)//封装到PushBox类里
21 {
22 HANDLE consolehwnd;//创建句柄,详细句柄知识,请百度一下或查MSDN
23 consolehwnd = GetStdHandle(STD_OUTPUT_HANDLE);//实例化句柄
24 SetConsoleTextAttribute(consolehwnd, m);
25 }
26
27
28
29 void PushBox::Drop(int map[N][M])
30 {
31 int i, j;
32 for (i = 0; i < N; i++)
33 {
34 for (j = 0; j < M; j++)
35 switch (map[i][j])
36 {
37 case 0: Color(7); std::cout << " "; break;
38 case 1: Color(4); std::cout << "■"; break;
39 case 2: Color(10); std::cout << "△"; break;
40 case 3: Color(5); std::cout << "□"; break;
41 case 4: Color(1); std::cout << "☆"; break;
42 case 5: Color(7); std::cout << "◆"; break;//箱子到达目标位置
43 case 6: Color(10); std::cout << "△"; break;//表示人与位置重叠
44
45 }
46 std::cout << "\n";
47 }
48 }
(2)推箱子算法:本人比较笨,没有找到捷径,所以就穷举了推箱子步骤,分析如下:
以人为中心,出现两种可能:①人在空位 ②人在目标位置上
①有六种可能:(注:x1,y1, x2, y2为坐标的偏移量,i ,为人所在的坐标 )

②人在目标位置上 同样也有六种可能:

用if语句进行对这12中可能进行判断,除了处理这几种能够移动的外,其他没有可能移动,分析清楚,则很容写出移动算法:
1 int PushBox::push(int map[N][M],int x1,int x2,int y1,int y2)
2 {
3 int i, j;
4 Postion(map, &i, &j);
5 /*******************人在空格处*/
6 if (map[i][j] == 2)
7 {
8 //人前是箱子,箱子在空格处
9 if (map[i + x1][j + y1] == 3)
10 { //箱子前面为空格S
11 if (map[i + x2][j + y2] == 0)
12 {
13 map[i][j] = 0;
14 map[i + x1][j + y1] = 2;
15 map[i + x2][j + y2] = 3;
16 return 1;
17 }
18 //箱子前面为位置
19 if (map[i + x2][j + y2] == 4)
20 {
21 map[i][j] = 0;
22 map[i + x1][j + y1] = 2;
23 map[i + x2][j + y2] = 5;
24 return 1;
25 }
26 }
27 //人前为箱子,箱子在位置上
28 if (map[i + x1][j + y1] == 5)
29 {
30 //箱子前面为空
31 if (map[i + x2][j + y2] == 0)
32 {
33 map[i + x2][j + y2] = 3;
34 map[i + x1][j + y1] = 6;
35 map[i][j] = 0;
36 return 1;
37
38 }
39 //箱子前面为位置
40 if (map[i + x2][j + y2] == 4)
41 {
42 map[i][j] = 0;
43 map[i + x1][j + y1] = 6;
44 map[i + x2][j + y2] = 5;
45 return 1;
46 }
47
48 }
49 /*--------------------*/
50 //人前为空格
51 if (map[i + x1][j + y1] == 0)
52 {
53 map[i + x1][j + y1] = 2;
54 map[i][j] = 0;
55 return 1;
56 }
57 //人前为位置
58 if (map[i + x1][j + y1] == 4)
59 {
60 map[i + x1][j + y1] = 6;
61 map[i][j] = 0;
62 return 1;
63 }
64 return 0;
65 }
66 /*******************人在位置上*/
67 if (map[i][j] == 6)
68 {
69 //位置前面是箱子,箱子在空格
70 if (map[i + x1][j + y1] == 3)
71 {
72 //箱子前面为空格
73 if (map[i + x2][j + y2] == 0)
74 {
75 map[i][j] = 4;
76 map[i + x1][j + y1] = 2;
77 map[i + x2][j + y2] = 3;
78 return 1;
79 }
80 //箱子前面为位置
81 if (map[i + x2][j + y2] == 4)
82 {
83 map[i][j] = 4;
84 map[i + x1][j + y1] = 2;
85 map[i + x2][j + y2] = 5;
86 return 1;
87 }
88 }
89 //位置前面是箱子,箱子在位置
90 if (map[i + x1][j + y1] == 5)
91 {
92 //箱子前面是空格
93 if (map[i + x2][j + y2] == 0)
94 {
95 map[i][j] = 4;
96 map[i + x1][j + y1] = 6;
97 map[i + x2][j + y2] = 3;
98 return 1;
99 }
100 //箱子前面是位置
101 if (map[i + x2][j + y2] == 4)
102 {
103 map[i][j] = 4;
104 map[i + x1][j + y1] = 6;
105 map[i + x2][j + y2] = 5;
106 return 1;
107 }
108 }
109
110 /*-----------------*/
111 //人前为位置
112 if (map[i + x1][j + y1] == 4)
113 {
114 map[i + x1][j + y1] = 6;
115 map[i][j] = 4;
116 return 1;
117 }
118 //人前为空格
119 if (map[i + x1][j + y1] == 0)
120 {
121 map[i + x1][j + y1] = 2;
122 map[i][j] = 4;
123 return 1;
124 }
125 return 0;
126 }return 0;
127 }
这里写返回1值既可以减少系统的判断,还可以判断是否执行了移动操作,方便统计移动的步数
(3)编写获取人的位置函数、判断是否获胜
获取人的位置,只需要判断得到地图中6或者2其中一个坐标,由于需要横坐标和纵坐标,所以利用指针得到位置
void PushBox::Postion(int map[N][M], int *cl, int *cow)
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
if (map[i][j] == 2 || map[i][j] == 6)goto ML;
}
}ML:
*cl = i;
*cow = j;
}
判断是否获胜:即地图中没有目标位置,就获胜,若胜利返回1值,否则返回0;
int PushBox::juide(int map[N][M])
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
if (map[i][j] == 6)return 0;
if (map[i][j] == 4)return 0;
}
if (i == N - 1 && j == M - 1)return 1;
}
}
(4)编写移动方向算法,并统计执行步数
int PushBox::move(int map[N][M], char ch)
{
static int step = 0;
int x1, x2, y1, y2;
switch (ch)
{
case 's':
case 'S': x1 = 1; x2 = 2; y1 = 0; y2 = 0;
if (push(map, x1, x2, y1, y2)) step++; return step;
case 'w':
case 'W': x1 = -1; x2 = -2; y1 = 0; y2 = 0;
if (push(map,x1,x2,y1,y2)) step++; return step;
case 'A':
case 'a': x1 = 0; x2 = 0; y1 = -1; y2 = -2;
if (push(map,x1,x2,y1,y2)) step++; return step;
case 'D':
case 'd': x1 = 0; x2 = 0; y1 = 1; y2 = 2;
if (push(map,x1,x2,y1,y2)) step++; return step;
}
}
(5)Push类的封装,将以上的几个方法封装到类里,建立头文件
1 #include <iostream>
2 using namespace std;
3 #include <windows.h>
4 #include <string.h>
5 #include <conio.h>
6 #include <fstream>
7 #pragma warning(disable:4996)
8 #define N 15
9 #define M 15
10
11 //建立一个推箱子相关操作的类
12 /*--------------------------PushBox类编写--------------------------------------*/
13 /****************************************************************************/
14 class PushBox{
15 public:
16 int move(int map[N][M], char ch);//移动箱子
17 void Drop(int map[N][M]);//箱子界面编写
18 int juide(int map[N][M]);//判断是否全部移入位置,成功返回1,失败返回0
19 private:
20 int push(int map[N][M],int x1,int x2,int y1,int y2);
21 void Color(int m);
22 void Postion(int map[N][M], int *i, int *j);
23 };
(6)主函数的编写:这里我将地图放入外部txt文件中,方便以后添加地图
#include <iostream>
using namespace std;
#include <windows.h>
#include <string.h>
#include <conio.h>
#include "Push.h"
#pragma warning(disable:4996)
#define N 15
#define M 15
int read_map(int *p);
void change_map(int *p, char *temp);
//主函数
int main()
{
int map[N][M] = { 0 };
PushBox box;
int *p = &map[0][0];
int select = read_map(p);
int step = 0;
while (1)
{
cout << "你选择的关卡是:" << select << endl;
cout << "你走了:" << step << "步";
box.Drop(map);
cout << "W-----向上 S------向下" << endl;
cout << "A-----向左 S------向右" << endl;
char ch;
ch = _getch();
step = box.move(map, ch);
system("cls");
if (box.juide(map))break;
}
std::cout << "你赢了!";
std::cout << "共走:" << step << "步";
getchar();
getchar();
}
/*选择关卡*/
int read_map(int *p)
{
int ch;
cout << "请输入关卡:";
cin >> ch;
char temp[15];
switch (ch)
{
case 1:strcpy(temp, "map/map_1.txt"); change_map(p, temp); system("cls"); return 1;
case 2:strcpy(temp, "map/map_2.txt"); change_map(p, temp); system("cls"); return 1;
}
}
/*打开关卡*/
void change_map(int *p, char *temp)
{
ifstream infile;
infile.open(temp);
while (!infile.eof())
{
infile >> *p;
p++;
}
infile.close();
}
程序分析图:

经过调试运行,暂时还没有发现BUG,一下是源代码,希望大家发现了以后给我留言,写得不好的地方希望大家能够指出
源文件
1 /**************************************************
2 * Name : 推箱子
3 * FileName : PushBox.cpp
4 * Author : 和导
5 * Version : V4.0
6 * Date :
7 *Description : 制作一个简单的推箱子
8
9 *Function List : (1)void read_map(int *p);
10 (2)void change_map(int *p, char *temp);
11 --------------
12 History:
13 <author> <time> <reviseInf>
14 和导 2016/4/1 把类封装到头文件中,重写推函数,添加地图
15 ****************************************************/
16
17
18 #include <iostream>
19 using namespace std;
20 #include <windows.h>
21 #include <string.h>
22 #include <conio.h>
23 #include "Push.h"
24 #pragma warning(disable:4996)
25 #define N 15
26 #define M 15
27
28 int read_map(int *p);
29 void change_map(int *p, char *temp);
30 //主函数
31
32 int main()
33 {
34 int map[N][M] = { 0 };
35 PushBox box;
36 int *p = &map[0][0];
37 int select = read_map(p);
38 int step = 0;
39 while (1)
40 {
41 cout << "你选择的关卡是:" << select << endl;
42 cout << "你走了:" << step << "步";
43 box.Drop(map);
44 cout << "W-----向上 S------向下" << endl;
45 cout << "A-----向左 S------向右" << endl;
46 char ch;
47 ch = _getch();
48 step = box.move(map, ch);
49 system("cls");
50 if (box.juide(map))break;
51 }
52 std::cout << "你赢了!";
53 std::cout << "共走:" << step << "步";
54 getchar();
55 getchar();
56 }
57
58
59
60 /*选择关卡*/
61 int read_map(int *p)
62 {
63 int ch;
64 cout << "请输入关卡:";
65 cin >> ch;
66 char temp[15];
67 switch (ch)
68 {
69 case 1:strcpy(temp, "map/map_1.txt"); change_map(p, temp); system("cls"); return 1;
70 case 2:strcpy(temp, "map/map_2.txt"); change_map(p, temp); system("cls"); return 1;
71 }
72
73 }
74 /*打开关卡*/
75 void change_map(int *p, char *temp)
76 {
77 ifstream infile;
78 infile.open(temp);
79 while (!infile.eof())
80 {
81 infile >> *p;
82 p++;
83 }
84 infile.close();
85 }
头文件

1 #include <iostream>
2 using namespace std;
3 #include <windows.h>
4 #include <string.h>
5 #include <conio.h>
6 #include <fstream>
7 #pragma warning(disable:4996)
8 #define N 15
9 #define M 15
10
11 //建立一个推箱子相关操作的类
12 /*--------------------------PushBox类编写--------------------------------------*/
13 /****************************************************************************/
14 class PushBox{
15 public:
16 int move(int map[N][M], char ch);//移动箱子
17 void Drop(int map[N][M]);//箱子界面编写
18 int juide(int map[N][M]);//判断是否全部移入位置,成功返回1,失败返回0
19 private:
20 int push(int map[N][M],int x1,int x2,int y1,int y2);
21 void Color(int m);
22 void Postion(int map[N][M], int *i, int *j);
23 };
24
25 int PushBox::move(int map[N][M], char ch)
26 {
27
28 static int step = 0;
29 int x1, x2, y1, y2;
30 switch (ch)
31 {
32 case 's':
33 case 'S': x1 = 1; x2 = 2; y1 = 0; y2 = 0;
34 if (push(map, x1, x2, y1, y2)) step++; return step;
35
36 case 'w':
37 case 'W': x1 = -1; x2 = -2; y1 = 0; y2 = 0;
38 if (push(map,x1,x2,y1,y2)) step++; return step;
39
40 case 'A':
41 case 'a': x1 = 0; x2 = 0; y1 = -1; y2 = -2;
42 if (push(map,x1,x2,y1,y2)) step++; return step;
43 case 'D':
44 case 'd': x1 = 0; x2 = 0; y1 = 1; y2 = 2;
45 if (push(map,x1,x2,y1,y2)) step++; return step;
46 }
47 }
48
49 void PushBox::Drop(int map[N][M])
50 {
51 int i, j;
52 for (i = 0; i < N; i++)
53 {
54 for (j = 0; j < M; j++)
55 switch (map[i][j])
56 {
57 case 0: Color(7); std::cout << " "; break;
58 case 1: Color(4); std::cout << "■"; break;
59 case 2: Color(10); std::cout << "△"; break;
60 case 3: Color(5); std::cout << "□"; break;
61 case 4: Color(1); std::cout << "☆"; break;
62 case 5: Color(7); std::cout << "◆"; break;
63 case 6: Color(10); std::cout << "△"; break;
64
65 }
66 std::cout << "\n";
67 }
68 }
69
70 int PushBox::juide(int map[N][M])
71 {
72 int i, j;
73 for (i = 0; i < N; i++)
74 {
75 for (j = 0; j < M; j++)
76 {
77 if (map[i][j] == 6)return 0;
78 if (map[i][j] == 4)return 0;
79 }
80
81 if (i == N - 1 && j == M - 1)return 1;
82 }
83 }
84
85 int PushBox::push(int map[N][M],int x1,int x2,int y1,int y2)
86 {
87 int i, j;
88 Postion(map, &i, &j);
89 /*******************人在空格处*/
90 if (map[i][j] == 2)
91 {
92 //人前是箱子,箱子在空格处
93 if (map[i + x1][j + y1] == 3)
94 { //箱子前面为空格S
95 if (map[i + x2][j + y2] == 0)
96 {
97 map[i][j] = 0;
98 map[i + x1][j + y1] = 2;
99 map[i + x2][j + y2] = 3;
100 return 1;
101 }
102 //箱子前面为位置
103 if (map[i + x2][j + y2] == 4)
104 {
105 map[i][j] = 0;
106 map[i + x1][j + y1] = 2;
107 map[i + x2][j + y2] = 5;
108 return 1;
109 }
110 }
111 //人前为箱子,箱子在位置上
112 if (map[i + x1][j + y1] == 5)
113 {
114 //箱子前面为空
115 if (map[i + x2][j + y2] == 0)
116 {
117 map[i + x2][j + y2] = 3;
118 map[i + x1][j + y1] = 6;
119 map[i][j] = 0;
120 return 1;
121
122 }
123 //箱子前面为位置
124 if (map[i + x2][j + y2] == 4)
125 {
126 map[i][j] = 0;
127 map[i + x1][j + y1] = 6;
128 map[i + x2][j + y2] = 5;
129 return 1;
130 }
131
132 }
133 /*--------------------*/
134 //人前为空格
135 if (map[i + x1][j + y1] == 0)
136 {
137 map[i + x1][j + y1] = 2;
138 map[i][j] = 0;
139 return 1;
140 }
141 //人前为位置
142 if (map[i + x1][j + y1] == 4)
143 {
144 map[i + x1][j + y1] = 6;
145 map[i][j] = 0;
146 return 1;
147 }
148 return 0;
149 }
150 /*******************人在位置上*/
151 if (map[i][j] == 6)
152 {
153 //位置前面是箱子,箱子在空格
154 if (map[i + x1][j + y1] == 3)
155 {
156 //箱子前面为空格
157 if (map[i + x2][j + y2] == 0)
158 {
159 map[i][j] = 4;
160 map[i + x1][j + y1] = 2;
161 map[i + x2][j + y2] = 3;
162 return 1;
163 }
164 //箱子前面为位置
165 if (map[i + x2][j + y2] == 4)
166 {
167 map[i][j] = 4;
168 map[i + x1][j + y1] = 2;
169 map[i + x2][j + y2] = 5;
170 return 1;
171 }
172 }
173 //位置前面是箱子,箱子在位置
174 if (map[i + x1][j + y1] == 5)
175 {
176 //箱子前面是空格
177 if (map[i + x2][j + y2] == 0)
178 {
179 map[i][j] = 4;
180 map[i + x1][j + y1] = 6;
181 map[i + x2][j + y2] = 3;
182 return 1;
183 }
184 //箱子前面是位置
185 if (map[i + x2][j + y2] == 4)
186 {
187 map[i][j] = 4;
188 map[i + x1][j + y1] = 6;
189 map[i + x2][j + y2] = 5;
190 return 1;
191 }
192 }
193
194 /*-----------------*/
195 //人前为位置
196 if (map[i + x1][j + y1] == 4)
197 {
198 map[i + x1][j + y1] = 6;
199 map[i][j] = 4;
200 return 1;
201 }
202 //人前为空格
203 if (map[i + x1][j + y1] == 0)
204 {
205 map[i + x1][j + y1] = 2;
206 map[i][j] = 4;
207 return 1;
208 }
209 return 0;
210 }return 0;
211 }
212
213 void PushBox::Postion(int map[N][M], int *cl, int *cow)
214 {
215 int i, j;
216 for (i = 0; i < N; i++)
217 {
218 for (j = 0; j < M; j++)
219 {
220 if (map[i][j] == 2 || map[i][j] == 6)goto ML;
221 }
222 }ML:
223 *cl = i;
224 *cow = j;
225 ;
226 }
227
228 void PushBox::Color(int m)
229 {
230 HANDLE consolehwnd;//创建句柄,详细句柄知识,请百度一下或查MSDN
231 consolehwnd = GetStdHandle(STD_OUTPUT_HANDLE);//实例化句柄
232 SetConsoleTextAttribute(consolehwnd, m);
233 }
两个地图张

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 4 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 3 1 1 1 1 0 0 0 0 0 0 1 4 0 0 3 2 3 4 1 0 0 0 0 0 0 1 1 1 1 1 3 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 4 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 2 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 3 3 1 0 1 1 1 0 0 0 0 0 0 1 0 3 0 1 0 1 4 1 0 0 0 0 0 0 1 1 1 0 1 1 1 4 1 0 0 0 0 0 0 0 1 1 0 0 0 0 4 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0
文件放置如图:


来源:https://www.cnblogs.com/deom/p/5345361.html
