C语言贪吃蛇大作战
贪吃蛇大作战
1997 年,诺基亚公司发布了贪吃蛇游戏,并将其内置于诺基亚 6110 手机中,使这款游戏迅速风靡全球,成为一代经典。一般的观点认为,贪吃蛇是手机游戏的鼻祖。
与传统单人贪吃蛇不同的是,本题中的贪吃蛇游戏为双人对战。请你编写程序控制贪吃蛇,在动态变化的场地中与对手比拼,在最短的时间内尽可能多地吃掉食物。
游戏规则:
游戏在一张二维地图上展开,地图上有蛇、墙和障碍物、道具、食物,如图1所示。蛇有2条:白蛇(口口口)和粉蛇(■■■),初始长度为3格。食物由●表示。墙和障碍物由■表示。道具分为两种:第1种为“倍速道具▲”,全场1个,吃该道具后,速度加倍,50 步后恢复原速度;第二种道具为“斜走道具★”,全场 2 个,正常情况下,蛇移动方向为上、下、左、右4个方向,但吃该道具后,还可以斜着走,即上、下、左、右、上左、下左、上右、下右8 个方向都可以行进,该道具吃后永久有效。蛇头碰到墙或障碍物、自己的身体、对方的身体均被判定为死亡。游戏具体实例请见附件 2。
源码
https://pan.baidu.com/s/1pq1Nwwo0hlc_J84F93HM4A?pwd=1111
游戏每面(也可以称为关卡) 随机放置 10 个食物。第一面只有食物没有障碍物和道具第二面开始出现随机放置的障碍物和道具。
胜负判定:
先吃到 35 个食物的一方获胜,在此期间若任何一条蛇死亡,判对方获胜。此外,若距任意一方吃到食物后 200 步内双方均未再吃到食物,则判超时,此时吃食物多的一方获胜,若两条蛇吃的食物一样多,则判为平局。
代码实现:
老师提供程序框架和图形显示,学生只需按接口要求编写相关函数,实现操控贪吃蛇的核心算法即可,无需负责图形显示。实现语言为 C/C++,不限编译器与开发环境。本题程序由命令行界面模拟图形界面,用命令行界面的 n+2行 +4 列二维网格表示游戏地图,通过 printf(“”等画游戏地图中的一个点格。这里需特别注意的是,由于“ ”等特殊字符在命令行中占2个字符的宽度,所以命令行的每 2列对应游戏地图的 1列。综上,游戏地图的坐标系如图 2 所示,其相邻两点的列坐标值相差 2 而不是 1。例如图 2 中粉蛇 3 个点组成,其坐标分别为(3.6)、(3.4)、(3,2)。第0行、第n+1行、第0列、第m+2 列为四周的墙。
你的任务是编写程序控制贪吃蛇,即根据当前的游戏地图和蛇的位置,做出决策,给出下一步贪吃蛇行进的方向。从而吃掉食物并躲避障碍物和对方。为此你至少需要编写如下 2个函数:
(1)machine_move函数
int machine_move (point snake[5][100], int len[5], int direct[5], int t, GamePanel gp)
该函数的功能是:即根据当前的游戏地图、贪吃蛇当前的位置和行进方向,返回下一步应行进的方向。其中point为结构体struct point{intx;inty;},表示游戏地图中某点的行列坐标。snake数组表示蛇的坐标,具体地,由于一条蛇由多个点/格组成,故snake[t]i]表示第t条蛇的第i个点(下标从1开始),len[t]表示蛇t的长度,即第t条蛇由地图中的snakelt]f1]…snakelt]len[t点格组成。若图2中的粉蛇编号为t,则len[t]=3 ,且 snakelt][1].x=3,snakelt][1].y=6; snakelt][2].x=3snake[t][2],y=4; snakelt][3].x=3,snakelt][31.y=2。t表示你所控制的蛇的编号,由于最多是二人对战,最多有2条蛇,即t只有两种可能取值0或1。direct[t]为一个整数,表示第t条蛇当前行进的方向。函数的返回值为一个整数,表示接下来应该行进的方向。
结构体GamePanel表示当前游戏地图。其定义如下:
struct GamePanel
{
int n; //地图规模
int m; //地图规模
int totalfoodnum; //当前地图中的食物总数
int wallnum; //障碍物总数
int success_num; //获胜所需吃的食物数
int speednum; //当前地图中倍速道具数
int step_speed; //玩家吃倍速道具后,走的步数,此变量值不超过50
int obliquenum; //当前地图中斜走道具数
int speedowner; //倍速道具的拥有者,值为0或1
int obliqueowner[5]; //斜走道具的拥有者,obliqueowner[t]==1表示蛇t拥有斜走道具,obliqueowner[t]==0表示蛇t没吃斜走道具
int currentfoodnum; //当前地图中所剩食物数
point food[20]; //当前地图中所有食物的坐标
point wall[20]; //当前地图中所有障碍物的坐标
point speedprops; //当前地图中倍速道具的坐标
point obliqueprops[2]; //当前地图中倍速斜走的坐标
int panel[50][100]; //游戏盘面,panel[i][j]的值为0,1,2,3,4,分别表示地图中点i,j为空位置,食物,障碍物,倍速道具,斜走道具
};
(2)check函数
bool check(point snake[5][100], int len[5], int t, GamePanel gp, int direction)
该函数的功能是:判断在贪吃蛇当前位置和游戏地图下,下一步若以 direction 方向行进,是否可行。如可行则返回 true,如不可行 (即按此方向前进会导致贪吃蛇死亡) 则返回 fase。参数中snake、len、t、gp 的含义同 (1),direction 表示下一步拟行进的方向,含义如表1所示。这里需注意的是,当贪吃蛇能斜走的时候,类似图 3 的情形,贪吃蛇是不能向右上方通过的,无论点格1和2是障碍物还是蛇自己或对方的身体。但图4 的情形贪吃蛇则可以向右上方通过。其他方向同理。
最后,将你的 machine.h 文件,修改为 machine+编号.h,例如你的编号是 5,则修改为machine5.h,并在超星作业里提交该 machine5.h 头文件。
上述处理的原因是:我们会将一个班内所有同学的 machine.h 文件放入同一个项目工程里进行编译、运行和对战,所以每个同学的头文件名不能相同,且任意两个头文件中的函数名、全局变量名、类或结构体名都不能相同,否则会出现重名的编译错误。
请注意不要提交诸如“#include 头文件”、main函数等。函数中不允许通过 printf、cout等输出信息。machine_move 和 heck 函数的参数均为值参数,对参数的修改在函数执行完毕后不会保存。
课程设计报告也需以超星作业的方式提交,模板与 A 题相同,不建议长篇大论,1-2 页即可。