1、建立游戏地图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#define ROWS 11
#define COLS 12
char
map
[
ROWS
]
[
COLS
]
=
{
"###########"
,
"# #"
,
"#O #"
,
"# X# # @#"
,
"# # # #"
,
"# # # #"
,
"# # # #"
,
"# #"
,
"# #"
,
"###########"
}
;
|
由于推箱子游戏地图是由多个格子组成的,因此咱们可使用二维字符数组或字符串数组建立地图。咱们能够改变数组中的元素来对游戏功能进行实现。例如:小人移动方向无障碍物,就是小人原来位置的数组元素设置为路,移动后的元素设置为小人。这样就实现了小人移动功能,箱子也是同理。数组
2、初始化位置和游戏开关
1
2
3
4
5
6
7
8
9
10
|
//游戏开关
int
flag
=
1
;
//人的坐标
int
renRows
=
2
;
int
renCols
=
1
;
//箱子的坐标
int
xiangRows
=
3
;
int
xiangCols
=
2
;
|
由于整个游戏操做都是放在循环里的,因此咱们先定义一个全局开关,而后用while(开关)来控制游戏的结束。而且在判断用户输入方向前,咱们须要先肯定小人和箱子的初始位置,再根据用户输入进行判断。ide
3、接收用户输入方向
1
2
3
4
5
|
printf
(
"W.前 S.后 A.左 D.右 Q.退出\n"
)
;
char
enterInput
=
'a'
;
rewind
(
stdin
)
;
//接收键盘方向
scanf
(
"%c"
,
&
enterInput
)
;
|
接收用户从键盘输入的字符,因为方向4个,加上退出功能就5个分支。因此咱们使用switch case结构来实现判断用户输入字符,并执行一些操做。函数
4、判断用户输入方向
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
|
//初始化人和箱子的下一个坐标
int
nextRows
=
0
,
nextCols
=
0
,
nextXiangRows
=
0
,
nextXiangCols
=
0
;
//判断方向并操做
switch
(
enterInput
)
{
case
'w'
:
case
'W'
:
{
nextRows
=
renRows
-
1
;
nextCols
=
renCols
;
nextXiangRows
=
xiangRows
-
1
;
nextXiangCols
=
xiangCols
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
's'
:
case
'S'
:
{
nextRows
=
renRows
+
1
;
nextCols
=
renCols
;
nextXiangRows
=
xiangRows
+
1
;
nextXiangCols
=
xiangCols
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
'a'
:
case
'A'
:
{
nextRows
=
renRows
;
nextCols
=
renCols
-
1
;
nextXiangRows
=
xiangRows
;
nextXiangCols
=
xiangCols
-
1
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
'd'
:
case
'D'
:
{
nextRows
=
renRows
;
nextCols
=
renCols
+
1
;
nextXiangRows
=
xiangRows
;
nextXiangCols
=
xiangCols
+
1
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
'q'
:
case
'Q'
:
//若是输入Q则关闭游戏
flag
=
0
;
break
;
default
:
printf
(
"输入错误\n"
)
;
break
;
}
|
人下一个位置的行下标 nextRowsspa
人下一个位置的列下标 nextColscode
箱子下一个位置的行下标 nextXiangRowsblog
箱子下一个位置的列下标 nextXiangCols游戏
这里说的下一个位置就比如,我输入w后向上移动了一个位置,这个新的位置我称他为下一个位置。ci
若是向上移动,人和箱子的行下标-1,列下标不变。rem
若是向下移动,人和箱子的行下标+1,列下标不变。字符串
若是向左移动,人和箱子的行下标不变,列下标-1。
若是向右移动,人和箱子的行下标不变,列下标+1。
我这里是先根据方向判断出人和箱子位置会发生的移动变化,并使用局部变量临时存储,因此不用担忧人没有顶着箱子的时候,箱子也会跟着移动的问题。由于最终移动后的新位置坐标仍是由全局变量来存储的,我只是根据用户输入方向计算出人和箱子下一个位置的新坐标,而后再根据实际状况(实际状况就是人前进方向是不是障碍物,仍是箱子来肯定的。若是是障碍物,就只有人移动,并只有人刷新位置。若是是箱子,则判断箱子下一个位置是不是障碍物,来刷新人和箱子的新位置)赋值给全局变量。
5、移动控制实现
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
|
void
moveRen
(
int
nextRows
,
int
nextCols
,
int
nextXiangRows
,
int
nextXiangCols
)
{
if
(
map
[
nextRows
]
[
nextCols
]
==
' '
)
{
//若是人下一个位置是路
map
[
nextRows
]
[
nextCols
]
=
'O'
;
//下一个位置设置为人
map
[
renRows
]
[
renCols
]
=
' '
;
//人原来的位置设置为路
//刷新人的位置
renRows
=
nextRows
;
renCols
=
nextCols
;
}
else
if
(
map
[
nextRows
]
[
nextCols
]
==
'X'
&&
map
[
nextXiangRows
]
[
nextXiangCols
]
!=
'#'
&&
map
[
nextXiangRows
]
[
nextXiangCols
]
!=
'@'
)
{
//若是人下一个位置是箱子,而且箱子下一个位置不是墙也不是关卡
map
[
nextRows
]
[
nextCols
]
=
'O'
;
//下一个位置设置为人
map
[
renRows
]
[
renCols
]
=
' '
;
//人原来的位置设置为路
map
[
nextXiangRows
]
[
nextXiangCols
]
=
'X'
;
//箱子下一个位置设置为箱子
//刷新人和箱子的位置
renRows
=
nextRows
;
renCols
=
nextCols
;
xiangRows
=
nextXiangRows
;
xiangCols
=
nextXiangCols
;
}
else
if
(
map
[
nextXiangRows
]
[
nextXiangCols
]
==
'@'
)
{
//若是箱子下一个位置是关卡,就过关
printf
(
"您已通过关!\n"
)
;
flag
=
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
|
#include <stdio.h>
#include <stdlib.h>
#define ROWS 11
#define COLS 12
char
map
[
ROWS
]
[
COLS
]
=
{
"###########"
,
"# #"
,
"#O #"
,
"# X# # @#"
,
"# # # #"
,
"# # # #"
,
"# # # #"
,
"# #"
,
"# #"
,
"###########"
}
;
//游戏开关
int
flag
=
1
;
//人的坐标
int
renRows
=
2
;
int
renCols
=
1
;
//箱子的坐标
int
xiangRows
=
3
;
int
xiangCols
=
2
;
//移动小人
void
moveRen
(
int
nextRows
,
int
nextCols
,
int
nextXiangRows
,
int
nextXiangCols
)
;
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
while
(
flag
)
{
system
(
"clear"
)
;
//刷新地图
for
(
int
i
=
0
;
i
<
ROWS
;
i
++
)
{
printf
(
"%s\n"
,
map
[
i
]
)
;
}
printf
(
"W.前 S.后 A.左 D.右 Q.退出\n"
)
;
char
enterInput
=
'a'
;
rewind
(
stdin
)
;
//接收键盘方向
scanf
(
"%c"
,
&
enterInput
)
;
//初始化人和箱子的下一个坐标
int
nextRows
=
0
,
nextCols
=
0
,
nextXiangRows
=
0
,
nextXiangCols
=
0
;
//判断方向并操做
switch
(
enterInput
)
{
case
'w'
:
case
'W'
:
{
nextRows
=
renRows
-
1
;
nextCols
=
renCols
;
nextXiangRows
=
xiangRows
-
1
;
nextXiangCols
=
xiangCols
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
's'
:
case
'S'
:
{
nextRows
=
renRows
+
1
;
nextCols
=
renCols
;
nextXiangRows
=
xiangRows
+
1
;
nextXiangCols
=
xiangCols
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
'a'
:
case
'A'
:
{
nextRows
=
renRows
;
nextCols
=
renCols
-
1
;
nextXiangRows
=
xiangRows
;
nextXiangCols
=
xiangCols
-
1
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
'd'
:
case
'D'
:
{
nextRows
=
renRows
;
nextCols
=
renCols
+
1
;
nextXiangRows
=
xiangRows
;
nextXiangCols
=
xiangCols
+
1
;
//调用移动函数
moveRen
(
nextRows
,
nextCols
,
nextXiangRows
,
nextXiangCols
)
;
}
break
;
case
'q'
:
case
'Q'
:
//若是输入Q则关闭游戏
flag
=
0
;
break
;
default
:
printf
(
"输入错误\n"
)
;
break
;
}
}
return
0
;
}
//移动小人
void
moveRen
(
int
nextRows
,
int
nextCols
,
int
nextXiangRows
,
int
nextXiangCols
)
{
if
(
map
[
nextRows
]
[
nextCols
]
==
' '
)
{
//若是人下一个位置是路
map
[
nextRows
]
[
nextCols
]
=
'O'
;
//下一个位置设置为人
map
[
renRows
]
[
renCols
]
=
' '
;
//人原来的位置设置为路
//刷新人的位置
renRows
=
nextRows
;
renCols
=
nextCols
;
}
else
if
(
map
[
nextRows
]
[
nextCols
]
==
'X'
&&
map
[
nextXiangRows
]
[
nextXiangCols
]
!=
'#'
&&
map
[
nextXiangRows
]
[
nextXiangCols
]
!=
'@'
)
{
//若是人下一个位置是箱子,而且箱子下一个位置不是墙也不是关卡
map
[
nextRows
]
[
nextCols
]
=
'O'
;
//下一个位置设置为人
map
[
renRows
]
[
renCols
]
=
' '
;
//人原来的位置设置为路
map
[
nextXiangRows
]
[
nextXiangCols
]
=
'X'
;
//箱子下一个位置设置为箱子
//刷新人和箱子的位置
renRows
=
nextRows
;
renCols
=
nextCols
;
xiangRows
=
nextXiangRows
;
xiangCols
=
nextXiangCols
;
}
else
if
(
map
[
nextXiangRows
]
[
nextXiangCols
]
==
'@'
)
{
//若是箱子下一个位置是关卡,就过关
printf
(
"您已通过关!\n"
)
;
flag
=
0
;
}
}
|