C语言知识巩固–会打字就能学会的推箱子
临近期末了,不知道大家复习的怎么样(头大)。
学C语言也将近一个学期了,最近发现了一个推箱子的小游戏可以巩固一下C语言知识,涉及到基本的输入输出、循环、函数、数组,跟大家一起分享复习。
代码在200行左右,简单易学,不仅能积累代码量,对数组复习也是挺有帮助的
-
找到相关的特殊符号
为了方便起见,相关的符号我已经帮大家找好了,当然大家也可以找自己喜欢的符号
找到对应的符号之后,我们还要确定符号对应的数字,因为操作数组还是要回归到数字的嘛(数字也是任意的)
人 ♀ 5 箱子 ★ 4 障碍 ■ 1 目的地 ☆ 3 箱子推到目的地:● 7 空地 0
-
设计窗口
控制太黑黑的窗口真的不太好看,所以我专门写了个函数设计了一下窗口(设计了还是不好看[捂脸])
void designWin() { system("title 推箱子(控制台版本)"); system("color E0"); system("mode con cols=24 lines=12"); }
-
设计地图
现在开始就要开始复习我们的数组知识啦
首先我们先定义一个数组
int map[3][8][8];//3:游戏的总关卡数 //8:游戏地图的长宽
地图设计:
int map[3][8][8] ={ 1,1,1,1,1,1,1,1, 1,3,4,0,0,4,3,1, 1,1,1,1,0,1,1,1, 1,1,1,1,5,1,1,1, 1,1,1,1,0,1,1,1, 1,1,1,1,0,1,1,1, 1,3,4,0,0,4,3,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,3,4,0,0,1,1,1, 1,1,4,1,5,1,1,1, 1,3,0,0,0,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,0,5,0,1,1,1, 1,1,0,1,4,0,0,1, 1,1,0,3,0,3,0,1, 1,0,0,4,4,0,0,1, 1,0,0,0,1,3,0,1, 1,1,1,0,0,0,1,1, 1,1,1,1,1,1,1,1 };
-
画地图
接下来,我们将设计好的地图画在控制台窗口上,也就是输出出来
这里就用到数组的遍历知识啦
这里我用的是switch,大家也可以用if-else
void drawMap() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { switch (map[GuanKa][i][j]) { case 0: printf(" "); break; case 1: printf("■"); break; case 3: printf("☆"); break; case 4: printf("★"); break; case 5: case 8: printf("♀"); break; case 7: printf("●"); break; } } printf("\n"); } }
-
确定人物的坐标
想要对人物进行操控,我们需要确定人物的坐标,所以我封装了两个函数来确定任务的x坐标以及y坐标,因为写数组习惯了,所以用i、j来表示横纵坐标
//寻找人物的i坐标 int findMen_i() { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { if (map[GuanKa][i][j] == 5 || map[GuanKa][i][j] == 8) return i; } } } //寻找人物的j坐标 int findMen_j() { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { if (map[GuanKa][i][j] == 5 || map[GuanKa][i][j] == 8) return j; } } }
-
游戏交互
接下来就是本次项目的难点,所谓的移动,就是将数组中的数字进行该表,例如0变成5,就意味着人往前走了一格(因为0表示空地,5表示人)
为了接下来的方便讲解,我给大家加上了宏替换
#define ♀ 5 #define ★ 4 #define ■ 1 #define ☆ 3 #define ● 7 #define 空地 0
接下来我们要分类讨论:
-
如果前方是空地或者☆,那我们就可以顺利走过去
if (map[GuanKa][i - 1][j] == 空地 || map[GuanKa][i - 1][j] == ☆) { map[GuanKa][i - 1][j] += ♀; map[GuanKa][i][j] -= ♀; }
-
如果人前方是●,那就要判断箱子前方的东西
-
如果箱子前方是空地或☆,那就直接走过去,并将箱子送到目的地
if (map[GuanKa][i - 1][j] == ★ || map[GuanKa][i - 1][j] == ●) { if (map[GuanKa][i - 2][j] == 空地 || map[GuanKa][i - 2][j] == ☆) { map[GuanKa][i][j] -= ♀; map[GuanKa][i - 1][j] += ■; map[GuanKa][i - 2][j] += ★; } }
-
接下来的下、左、右也是相对应的操作,考验的就是大家对数组的熟练程度,交互函数如下:
void GameCtrl() { int i = findMen_i(); int j = findMen_j(); int UserInt =_getch();//隐式输入,用到头文件#include<conio.h> switch (UserInt) { case 'w': case 'W': case 72: if (map[GuanKa][i - 1][j] == 空地 || map[GuanKa][i - 1][j] == ☆) { map[GuanKa][i - 1][j] += ♀; map[GuanKa][i][j] -= ♀; } if (map[GuanKa][i - 1][j] == ★ || map[GuanKa][i - 1][j] == ●) { if (map[GuanKa][i - 2][j] == 空地 || map[GuanKa][i - 2][j] == ☆) { map[GuanKa][i][j] -= ♀; map[GuanKa][i - 1][j] += ■; map[GuanKa][i - 2][j] += ★; } } break; case 's': case 'S': case 80: if (map[GuanKa][i + 1][j] == 空地 || map[GuanKa][i + 1][j] == ☆) { map[GuanKa][i + 1][j] += ♀; map[GuanKa][i][j] -= ♀; } if (map[GuanKa][i + 1][j] == ★ || map[GuanKa][i + 1][j] == ●) { if (map[GuanKa][i + 2][j] == 空地 || map[GuanKa][i + 2][j] == ☆) { map[GuanKa][i][j] -= ♀; map[GuanKa][i + 1][j] += ■; map[GuanKa][i + 2][j] += ★; } } break; case 'a': case 'A': case 75: if (map[GuanKa][i][j - 1] == 空地 || map[GuanKa][i][j - 1] == ☆) { map[GuanKa][i][j - 1] += ♀; map[GuanKa][i][j] -= ♀; } if (map[GuanKa][i][j - 1] == ★ || map[GuanKa][i][j - 1] == ●) { if (map[GuanKa][i][j - 2] == 空地 || map[GuanKa][i][j - 2] == ☆) { map[GuanKa][i][j] -= ♀; map[GuanKa][i][j - 1] += ■; map[GuanKa][i][j - 2] += ★; } } break; case 'd': case 'D': case 77: if (map[GuanKa][i][j + 1] == 空地 || map[GuanKa][i][j + 1] == ☆) { map[GuanKa][i][j + 1] += ♀; map[GuanKa][i][j] -= ♀; } if (map[GuanKa][i][j + 1] == ★ || map[GuanKa][i][j + 1] == ●) { if (map[GuanKa][i][j + 2] == 空地 || map[GuanKa][i][j + 2] == ☆) { map[GuanKa][i][j] -= ♀; map[GuanKa][i][j + 1] += ■; map[GuanKa][i][j + 2] += ★; } } break; }
PS:上面的数字则是上、下、左、右健所对应的数字编码
-
-
判断关卡
最后呢就是简单的判断游戏关卡啦,也是简单的数组遍历
int Gamenum() { int flag = 1; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (map[GuanKa][i][j] == 4) { flag = 0; return flag; } } } }
最后只要把个个函数都写到main()函数中
int main() { designWin(); while (1) { drawMap(); if (Gamenum()) { GuanKa++; if (GuanKa == 3) { printf("恭喜通关\n"); system("pause"); break; } else { printf("按任意键进入下一关!\n"); } } GameCtrl(); } return 0; }
这就是所有流程啦,希望大家能点点赞,更希望对大家的复习有用。
完整的源码我会写在后面,方便大家复制使用,编译的游戏我也会上传到我的资源上提供大家下载
PS:最后我发现宏定义的字符是不能用的,所以还是要老老实实的改成数字吧#include<stdio.h> #include<conio.h> #include<stdlib.h> //关卡 int GuanKa = 0; //地图 int map[3][8][8] ={ 1,1,1,1,1,1,1,1, 1,3,4,0,0,4,3,1, 1,1,1,1,0,1,1,1, 1,1,1,1,5,1,1,1, 1,1,1,1,0,1,1,1, 1,1,1,1,0,1,1,1, 1,3,4,0,0,4,3,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,3,4,0,0,1,1,1, 1,1,4,1,5,1,1,1, 1,3,0,0,0,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,0,5,0,1,1,1, 1,1,0,1,4,0,0,1, 1,1,0,3,0,3,0,1, 1,0,0,4,4,0,0,1, 1,0,0,0,1,3,0,1, 1,1,1,0,0,0,1,1, 1,1,1,1,1,1,1,1 }; //窗口设计 void designWin() { system("title 推箱子(控制台版本)"); system("color E0"); system("mode con cols=24 lines=12"); } //画地图 void drawMap() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { switch (map[GuanKa][i][j]) { case 0: printf(" "); break; case 1: printf("■"); break; case 3: printf("☆"); break; case 4: printf("★"); break; case 5: case 8: printf("♀"); break; case 7: printf("●"); break; } } printf("\n"); } } //寻找人的i坐标 int findMen_i() { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { if (map[GuanKa][i][j] == 5 || map[GuanKa][i][j] == 8) return i; } } } //寻找人的y坐标 int findMen_j() { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { if (map[GuanKa][i][j] == 5 || map[GuanKa][i][j] == 8) return j; } } } //判断游戏关卡 int Gamenum() { int flag = 1; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (map[GuanKa][i][j] == 4) { flag = 0; return flag; } } } } //游戏的控制操作 void GameCtrl() { int i = findMen_i(); int j = findMen_j(); int UserInt =_getch(); switch (UserInt) { case 'w': case 'W': case 72: if (map[GuanKa][i - 1][j] == 0 || map[GuanKa][i - 1][j] == 3) { map[GuanKa][i - 1][j] += 5; map[GuanKa][i][j] -= 5; } if (map[GuanKa][i - 1][j] == 4 || map[GuanKa][i - 1][j] == 7) { if (map[GuanKa][i - 2][j] == 0 || map[GuanKa][i - 2][j] == 3) { map[GuanKa][i][j] -= 5; map[GuanKa][i - 1][j] += 1; map[GuanKa][i - 2][j] += 4; } } break; case 's': case 'S': case 80: if (map[GuanKa][i + 1][j] == 0 || map[GuanKa][i + 1][j] == 3) { map[GuanKa][i + 1][j] += 5; map[GuanKa][i][j] -= 5; } if (map[GuanKa][i + 1][j] == 4 || map[GuanKa][i + 1][j] == 7) { if (map[GuanKa][i + 2][j] == 0 || map[GuanKa][i + 2][j] == 3) { map[GuanKa][i][j] -= 5; map[GuanKa][i + 1][j] += 1; map[GuanKa][i + 2][j] += 4; } } break; case 'a': case 'A': case 75: if (map[GuanKa][i][j - 1] == 0 || map[GuanKa][i][j - 1] == 3) { map[GuanKa][i][j - 1] += 5; map[GuanKa][i][j] -= 5; } if (map[GuanKa][i][j - 1] == 4 || map[GuanKa][i][j - 1] == 7) { if (map[GuanKa][i][j - 2] == 0 || map[GuanKa][i][j - 2] == 3) { map[GuanKa][i][j] -= 5; map[GuanKa][i][j - 1] += 1; map[GuanKa][i][j - 2] += 4; } } break; case 'd': case 'D': case 77: if (map[GuanKa][i][j + 1] == 0 || map[GuanKa][i][j + 1] == 3) { map[GuanKa][i][j + 1] += 5; map[GuanKa][i][j] -= 5; } if (map[GuanKa][i][j + 1] == 4 || map[GuanKa][i][j + 1] == 7) { if (map[GuanKa][i][j + 2] == 0 || map[GuanKa][i][j + 2] == 3) { map[GuanKa][i][j] -= 5; map[GuanKa][i][j + 1] += 1; map[GuanKa][i][j + 2] += 4; } } break; } system("cls"); } int main() { designWin(); while (1) { drawMap(); if (Gamenum()) { GuanKa++; if (GuanKa == 3) { printf("恭喜通关\n"); system("pause"); break; } else { printf("按任意键进入下一关!\n"); } } GameCtrl(); } return 0; }