深圳幻海软件技术有限公司 欢迎您!

C语言实现推箱子小游戏

2023-06-29

一、设计目的用简单的C语言知识制作的推箱子游戏,通过上下左右键将所有箱子移动到目标位置。2.让我们更好地了解和巩固C语言知识,并实际运用,同时运用一些不太常见的知识点。二、功能描述1.模块功能本程序可分为初始界面、进行游戏、判定通关三个模块。初始界面模块:欢迎来到推箱子游戏,按方向键上下左右,可以实

一、设计目的

  1. 用简单的C语言知识制作的推箱子游戏,通过上下左右键将所有箱子移动到目标位置。

2.让我们更好地了解和巩固C语言知识,并实际运用,同时运用一些不太常见的知识点。

二、功能描述

1.模块功能

本程序可分为初始界面、进行游戏、判定通关三个模块。

  1. 初始界面模块:欢迎来到推箱子游戏,按方向键上下左右,可以实现方向,按->键进行游戏。

  1. 进行游戏:通过上下左右键控制人的上下左右来移动箱子,箱子只能向前推,不能向后面拉,游戏分为两关,完成第一关,按->建可进入下一关。

  1. 判定输赢模块:当所有箱子都推到目的地时,则游戏过关。当两关都通过时,会提示”恭喜你过关了”。

  1. 流程图

三.总体设计

(一)使用到的头文件

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<conio.h>
  4. #include<stdlib.h>

以上为本程序中所用到的头文件,#include<stdio.h>是c语言进行输入输出的头文件,#include<string.h>调用memcpy(map,temp,sizeof(temp))将临时数组赋值给map,

#include<conio.h>,调用_getch()获取按键操作,#include<stdlib.h>头文件调用system(“cls”)进行清屏操作。

(二)宏定义

  1. //宏定义数据
  2. #define SPACE 0 //空地
  3. #define WALL 1 //墙
  4. #define DEST 2 //目的地
  5. #define BOX 3 //箱子
  6. #define PLAYER 4 //玩家
  7. #define ROW 10 //行数
  8. #define COL 10 //列数

#define 是宏定义,在程序预处理阶段将define定义的内容进行了替换,可以增加代码可读性

(三)初始界面

  1. void menu()
  2. {
  3. printf("*********欢迎来到推箱子小游戏**********\n");
  4. printf("***按方向键上下左右,可以实现移动方向***\n");
  5. system("pause");
  6. }

Menu()函数里写好初始界面,并用system(“pause”)暂停程序,点任意键继续,进入游戏。

功能模块设计

创建并绘制地图:用 代表空地,■代表墙,☆代表目的地,★代表箱子,人字代表人,进代表到达目的地的箱子。在此基础上用数组储存数据,三维数组来创建两个不同的地图,并通过图标代替数字实现地图绘制。

(四)初始化地图

  1. //数组储存数据
  2. //定义地图
  3. int map[2][ROW][COL];
  4. int level = 0;//当前所在关
  5. //初始化地图
  6. void initMap()
  7. {
  8. //临时数组
  9. int temp[2][ROW][COL] =
  10. {
  11. {
  12. {0,0,0,0,0,0,0,0,0,0},
  13. {0,0,0,1,1,1,0,0,0,0},
  14. {0,0,0,1,2,1,0,0,0,0},
  15. {0,0,0,1,0,1,1,1,1,0},
  16. {0,1,1,1,3,3,0,2,1,0},
  17. {0,1,2,3,4,0,1,1,1,0},
  18. {0,1,1,1,1,3,1,0,0,0},
  19. {0,0,0,0,1,2,1,0,0,0},
  20. {0,0,0,0,1,1,1,0,0,0},
  21. {0,0,0,0,0,0,0,0,0,0}
  22. },
  23. {
  24. {0,0,0,0,0,0,0,0,0,0},
  25. {0,0,1,1,0,0,1,1,0,0},
  26. {0,1,0,0,1,1,0,0,1,0},
  27. {1,0,2,0,0,0,0,2,0,1},
  28. {1,0,0,3,4,0,3,0,0,1},
  29. {0,1,0,3,0,0,3,0,1,0},
  30. {0,0,1,0,2,2,0,1,0,0},
  31. {0,0,0,1,0,0,1,0,0,0},
  32. {0,0,0,0,1,1,0,0,0,0},
  33. {0,0,0,0,0,0,0,0,0,0}
  34. }
  35. };
  36. //把临时的数组赋值给map
  37. memcpy(map, temp, sizeof(temp));
  38. }

1.map[2][ROW][COL](ROW==10,COL==10)三维数组可有效实现多关卡设置,游戏设置了两个关卡。

2.void initMap()

此函数用来初始化地图,并定义了一个临时数组来绘制地图结构,并调用memcpy()函数赋值给map数组。

3.memcpy函数实现赋值操作(在程序中要引用#include<string.h>头文件)

(五)输出地图

  1. void show()
  2. {
  3. system("cls");//清屏
  4. for (int i = 0; i < ROW; i++)
  5. {
  6. for (int j = 0; j < COL; j++)
  7. {
  8. //把数据转为图形输出
  9. switch (map[level][i][j])
  10. {
  11. case SPACE:
  12. printf(" ");
  13. break;
  14. case WALL:
  15. printf("■");
  16. break;
  17. case DEST:
  18. printf("☆");
  19. break;
  20. case BOX:
  21. printf("★");
  22. break;
  23. case PLAYER:
  24. printf("人");
  25. break;
  26. case BOX + DEST://箱子在目的地上
  27. printf("进");
  28. break;
  29. }
  30. }
  31. printf("\n");
  32. }
  33. }

void show()此函数内运用for循环和switch分支结构来绘制地图,将数据用指定图标代替,使地图更具有可观性。

(六)移动操作:通过人或人和箱子的移动来进行,系统接受用户输入的一个字符(按键)来控制人的走向 ,在允许的条件下推动箱子。

  1. void move()
  2. {
  3. int r = -1, c = -1;
  4. //查找玩家的位置并复制给r c
  5. for (int i = 0; i < ROW; i++)
  6. {
  7. for (int j = 0; j < COL; j++)
  8. {
  9. if (map[level][i][j] == PLAYER || map[level][i][j] == PLAYER + DEST)
  10. {
  11. r = i;
  12. c = j;
  13. goto end;
  14. }
  15. }
  16. }
  17. end:;
  18. //获取按键操作
  19. int key = _getch();
  20. switch (key)
  21. {
  22. case 'W':
  23. case 'w':
  24. case 72://上
  25. //只有人前面是空地或者目的地的时候才可以移动
  26. // r c 是玩家当前所在的下标
  27. if (map[level][r - 1][c] == SPACE || map[level][r - 1][c] == DEST)
  28. {
  29. map[level][r - 1][c] += PLAYER;
  30. map[level][r][c] -= PLAYER;
  31. }
  32. else if (map[level][r - 1][c] == BOX)
  33. {//箱子前面是空地或者是目的地
  34. if (map[level][r - 2][c] == SPACE || map[level][r - 2][c] == DEST)
  35. {
  36. //先把箱子移动到指定位置
  37. map[level][r - 2][c] += BOX;
  38. //把箱子从原来的位置删除
  39. map[level][r - 1][c] -= BOX;
  40. //把玩家移动到箱子的位置
  41. map[level][r - 1][c] += PLAYER;
  42. //把玩家从原来的位置删除
  43. map[level][r - 1][c] -= PLAYER;
  44. }
  45. }
  46. break;
  47. case 80://下
  48. if (map[level][r + 1][c] == SPACE || map[level][r + 1][c] == DEST)
  49. {
  50. map[level][r + 1][c] += PLAYER;
  51. map[level][r][c] -= PLAYER;
  52. }
  53. else if (map[level][r + 1][c] == BOX || map[level][r + 1][c] == DEST)
  54. {//箱子前面是空地或者是目的地
  55. if (map[level][r + 2][c] == SPACE || map[level][r + 2][c] == DEST)
  56. {
  57. //先把箱子移动到指定位置
  58. map[level][r + 2][c] += BOX;
  59. //把箱子从原来的位置删除
  60. map[level][r + 1][c] -= BOX;
  61. //把玩家移动到箱子的位置
  62. map[level][r + 1][c] += PLAYER;
  63. //把玩家从原来的位置删除
  64. map[level][r][c] -= PLAYER;
  65. }
  66. }
  67. break;
  68. case 75://左
  69. if (map[level][r][c - 1] == SPACE || map[level][r][c - 1] == DEST)
  70. {
  71. map[level][r][c - 1] += PLAYER;
  72. map[level][r][c] -= PLAYER;
  73. }
  74. else if (map[level][r][c - 1] == BOX)
  75. {//箱子前面是空地或者是目的地
  76. if (map[level][r][c - 2] == SPACE || map[level][r][c - 2] == DEST)
  77. {
  78. //先把箱子移动到指定位置
  79. map[level][r][c - 2] += BOX;
  80. //把箱子从原来的位置删除
  81. map[level][r][c - 1] -= BOX;
  82. //把玩家移动到箱子的位置
  83. map[level][r][c - 1] += PLAYER;
  84. //把玩家从原来的位置删除
  85. map[level][r][c] -= PLAYER;
  86. }
  87. }
  88. break;
  89. case 77:
  90. if (map[level][r][c + 1] == SPACE || map[level][r][c + 1] == DEST)
  91. {
  92. map[level][r][c + 1] += PLAYER;
  93. map[level][r][c] -= PLAYER;
  94. }
  95. else if (map[level][r][c + 1] == BOX)
  96. {//箱子前面是空地或者是目的地
  97. if (map[level][r][c + 2] == SPACE || map[level][r][c + 2] == DEST)
  98. {
  99. //先把箱子移动到指定位置
  100. map[level][r][c + 2] += BOX;
  101. //把箱子从原来的位置删除
  102. map[level][r][c + 1] -= BOX;
  103. //把玩家移动到箱子的位置
  104. map[level][r][c + 1] += PLAYER;
  105. //把玩家从原来的位置删除
  106. map[level][r][c] -= PLAYER;
  107. }
  108. }
  109. break;
  110. }
  111. }

void move():先运用for循环遍历数组来定位人物的位置,定位好之后,我们可以将玩家的值赋值给r,c,找到玩家的位置。在人物移动时我们运用到了switch循环和if循环。先用switch循环判定得到key的值,此值可以确定按键操作方向,我们可以在此基础上对人物进行移动再运用if结构对人物移动或人物移动带动箱子的移动进行判定,将人(箱子)移动到指定位置,再进行删除人(箱子)原来的位置,运用goto语句到指定语句,以此,我们能实现箱子的连贯性移动。

(七)判定通关:当箱子全部达到目的地,最后提示恭喜你过关了,判定通关。

  1. //判断什么情况下过关
  2. int judge()
  3. {
  4. for (int i = 0; i < ROW; i++)
  5. {
  6. for (int j = 0; j < COL; j++)
  7. {
  8. if (map[level][i][j] == BOX)
  9. {
  10. return 0;
  11. }
  12. }
  13. }
  14. return 1;
  15. }

1.int judge():函数内通过for循环和if结构判断途中是否还有箱子,并通过return返回0或1,1表示过关。

2.system("cls"):清屏操作。

四、游戏测试

  1. //(完整代码)
  2. #define _CRT_SECURE_NO_WARNINGS 1
  3. #include<stdio.h>
  4. #include<string.h>
  5. #include<conio.h>
  6. #include<stdbool.h>
  7. #include<stdlib.h>
  8. //宏定义数据
  9. #define SPACE 0 //空地
  10. #define WALL 1 //墙
  11. #define DEST 2 //目的地
  12. #define BOX 3 //箱子
  13. #define PLAYER 4 //玩家
  14. #define ROW 10 //行数
  15. #define COL 10 //列数
  16. void menu()
  17. {
  18. printf("*********欢迎来到推箱子小游戏**********\n");
  19. printf("***按方向键上下左右,可以实现移动方向***\n");
  20. system("pause");
  21. }
  22. //数组储存数据
  23. //定义地图
  24. int map[2][ROW][COL];
  25. //初始化地图
  26. int level = 0;//当前所在关
  27. void initMap()
  28. {
  29. //临时数组
  30. int temp[2][ROW][COL] =
  31. {
  32. {
  33. {0,0,0,0,0,0,0,0,0,0},
  34. {0,0,0,1,1,1,0,0,0,0},
  35. {0,0,0,1,2,1,0,0,0,0},
  36. {0,0,0,1,0,1,1,1,1,0},
  37. {0,1,1,1,3,3,0,2,1,0},
  38. {0,1,2,3,4,0,1,1,1,0},
  39. {0,1,1,1,1,3,1,0,0,0},
  40. {0,0,0,0,1,2,1,0,0,0},
  41. {0,0,0,0,1,1,1,0,0,0},
  42. {0,0,0,0,0,0,0,0,0,0}
  43. },
  44. {
  45. {0,0,0,0,0,0,0,0,0,0},
  46. {0,0,1,1,0,0,1,1,0,0},
  47. {0,1,0,0,1,1,0,0,1,0},
  48. {1,0,2,0,0,0,0,2,0,1},
  49. {1,0,0,3,4,0,3,0,0,1},
  50. {0,1,0,3,0,0,3,0,1,0},
  51. {0,0,1,0,2,2,0,1,0,0},
  52. {0,0,0,1,0,0,1,0,0,0},
  53. {0,0,0,0,1,1,0,0,0,0},
  54. {0,0,0,0,0,0,0,0,0,0}
  55. }
  56. };
  57. //把临时的数组赋值给map
  58. memcpy(map, temp, sizeof(temp));
  59. }
  60. //输出地图
  61. void show()
  62. {
  63. system("cls");//清屏
  64. for (int i = 0; i < ROW; i++)
  65. {
  66. for (int j = 0; j < COL; j++)
  67. {
  68. //printf("%d", map[level][i][j]);
  69. //把数据转为图形输出 墙,人
  70. switch (map[level][i][j])
  71. {
  72. case SPACE:
  73. printf(" ");
  74. break;
  75. case WALL:
  76. printf("■");
  77. break;
  78. case DEST:
  79. printf("☆");
  80. break;
  81. case BOX:
  82. printf("★");
  83. break;
  84. case PLAYER:
  85. printf("人");
  86. break;
  87. case PLAYER+DEST:
  88. printf("出");
  89. break;
  90. case BOX + DEST://箱子在目的地上//玩家站在空地上
  91. printf("进");
  92. break;
  93. }
  94. }
  95. printf("\n");
  96. }
  97. }
  98. void move()
  99. {
  100. int r = -1, c = -1;
  101. //查找玩家的位置并复制给r c
  102. for (int i = 0; i < ROW; i++)
  103. {
  104. for (int j = 0; j < COL; j++)
  105. {
  106. if (map[level][i][j] == PLAYER|| map[level][i][j] == PLAYER+DEST)
  107. {
  108. r = i;
  109. c = j;
  110. goto end;
  111. }
  112. }
  113. }
  114. end:;
  115. //获取按键操作
  116. int key = _getch();
  117. switch (key)
  118. {
  119. case 72://上
  120. //只有人前面是空地或者目的地的时候我才可以移动
  121. // r c 是玩家当前所在的下标
  122. if (map[level][r - 1][c] == SPACE || map[level][r - 1][c] == DEST)
  123. {
  124. map[level][r - 1][c] += PLAYER;
  125. map[level][r][c] -= PLAYER;
  126. }
  127. else if (map[level][r - 1][c] == BOX)
  128. {//箱子前面是空地或者是目的地
  129. if (map[level][r - 2][c] == SPACE || map[level][r - 2][c] == DEST)
  130. {
  131. //先把箱子移动到指定位置
  132. map[level][r - 2][c] += BOX;
  133. //把箱子从原来的位置删除
  134. map[level][r - 1][c] -= BOX;
  135. //把玩家移动到箱子的位置
  136. map[level][r - 1][c] += PLAYER;
  137. //把玩家从原来的位置删除
  138. map[level][r - 1][c] -= PLAYER;
  139. }
  140. }
  141. break;
  142. case 80://下
  143. if (map[level][r + 1][c] == SPACE || map[level][r + 1][c] == DEST)
  144. {
  145. map[level][r + 1][c] += PLAYER;
  146. map[level][r][c] -= PLAYER;
  147. }
  148. else if (map[level][r + 1][c] == BOX || map[level][r + 1][c] == DEST)
  149. {//箱子前面是空地或者是目的地
  150. if (map[level][r + 2][c] == SPACE || map[level][r + 2][c] == DEST)
  151. {
  152. //先把箱子移动到指定位置
  153. map[level][r + 2][c] += BOX;
  154. //把箱子从原来的位置删除
  155. map[level][r + 1][c] -= BOX;
  156. //把玩家移动到箱子的位置
  157. map[level][r + 1][c] += PLAYER;
  158. //把玩家从原来的位置删除
  159. map[level][r][c] -= PLAYER;
  160. }
  161. }
  162. break;
  163. case 75://左
  164. if (map[level][r][c - 1] == SPACE || map[level][r][c - 1] == DEST)
  165. {
  166. map[level][r][c - 1] += PLAYER;
  167. map[level][r][c] -= PLAYER;
  168. }
  169. else if (map[level][r][c - 1] == BOX)
  170. {//箱子前面是空地或者是目的地
  171. if (map[level][r][c - 2] == SPACE || map[level][r][c - 2] == DEST)
  172. {
  173. //先把箱子移动到指定位置
  174. map[level][r][c - 2] += BOX;
  175. //把箱子从原来的位置删除
  176. map[level][r][c - 1] -= BOX;
  177. //把玩家移动到箱子的位置
  178. map[level][r][c - 1] += PLAYER;
  179. //把玩家从原来的位置删除
  180. map[level][r][c] -= PLAYER;
  181. }
  182. }
  183. break;
  184. case 77:
  185. if (map[level][r][c + 1] == SPACE || map[level][r][c + 1] == DEST)
  186. {
  187. map[level][r][c + 1] += PLAYER;
  188. map[level][r][c] -= PLAYER;
  189. }
  190. else if (map[level][r][c + 1] == BOX)
  191. {//箱子前面是空地或者是目的地
  192. if (map[level][r][c + 2] == SPACE || map[level][r][c + 2] == DEST)
  193. {
  194. //先把箱子移动到指定位置
  195. map[level][r][c + 2] += BOX;
  196. //把箱子从原来的位置删除
  197. map[level][r][c + 1] -= BOX;
  198. //把玩家移动到箱子的位置
  199. map[level][r][c + 1] += PLAYER;
  200. //把玩家从原来的位置删除
  201. map[level][r][c] -= PLAYER;
  202. }
  203. }
  204. break;
  205. }
  206. }
  207. //什么情况下过关
  208. int judge()
  209. {
  210. for (int i = 0; i < ROW; i++)
  211. {
  212. for (int j = 0; j < COL; j++)
  213. {
  214. if (map[level][i][j] == BOX)
  215. {
  216. return 0;
  217. }
  218. }
  219. }
  220. return 1;
  221. }
  222. int main()
  223. {
  224. menu();
  225. initMap();
  226. show();
  227. move();
  228. while (1)
  229. {
  230. show();
  231. if (judge())
  232. {
  233. level++;//每过一关加一
  234. if (level == 2)
  235. {
  236. printf("恭喜你过关了!");
  237. break;
  238. }
  239. }
  240. move();
  241. }
  242. return 0;
  243. }

五、程序实现

第一关初始地图界面

按↑↓←→时,人物会向上下左右移动

第一关:

第一关通关:

第二关:

第二关完成:

总结:

上面是简易推箱子小游戏,由于我自身能力还有待提升,写出这些代码对我来说有一定难度,在此过程中我通过上网课,不断查找资料写了这篇文章,代码可能还存在许多需要改进的地方,各位小伙伴们如果有时间的话可以对其进行优化,如果上述有错误的地方麻烦大家能够指正,同时也可以给我一些建议,这样我可以向各位优秀的伙伴学习,文章较长,感谢大家愿意发时间观看。

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览48554 人正在系统学习中