贪吃蛇的实现及其简单AI设计



设计要求:用代码实现经典游戏贪吃蛇,要求蛇能够按用户的输入做出相应的上下左右行进动作,获取食物,记录得分;并以此为基础设计简单AI,要求该AI能够在游戏中自动寻路,并得到尽量高的分数。

作为经典的一个小游戏,贪吃蛇的实现较为简单,但其AI设计比较复杂,需要考虑多种情况,主要在于蛇对路径的分析及如何获取食物,在这方面需要多花时间。

先把蛇和食物做成类,然后在里面添加成员变量和函数,描述蛇的状态信息和行为方法,在主函数里面调用方法来实现贪吃蛇。

然后添加适当的函数并运用恰当的算法实现AI,主要考虑用BFS算法找出蛇头到食物的路径,但在某些情况下蛇头到食物并没有路径,这是需要再利用BFS找出蛇头到蛇尾的路径,每走一步,尝试去找蛇头到食物的路径,有的话就去,没有就接着追蛇尾。但在一些特殊情况下,蛇头到食物和蛇尾均没有路径,这时就让蛇头在可行的区域“闲逛“,并不断尝试去找路径,直到找到为止。

用链表来表示蛇:
typedef int Elemtype;
typedef struct LNode
{
	Elemtype i;
	Elemtype j;//蛇体结点位置
	struct LNode *next;
}LNode,*LinkList;
用队列来实现BFS寻路算法:
typedef struct
{
	int x;
	int y;//点的位置
}Qpoint;
typedef struct
{
	Qpoint *base;
	int front; 
	int rear;  
}SqQueue;  
用栈来储存路径信息:
typedef struct points
{
	int x;
	int y;
}sElemtype,point;//路径中点的位置信息
typedef struct STACK
{
	point *base;
	point *top;
	int stacksize;
}SqStack;

Food类的实现:
class Food
{
	int x;
	int y;//食物的位置
public:
Food();//构造函数
int getx();//获取食物的X坐标
int gety();//获取食物的Y坐标
void reNew();//重新产生食物
void display();//食物的打印
}
Snake类的实现:
class Snake
{
	LinkList head;//蛇头指针
	int direction;//蛇的运动方向1,2,3,4分别代表上下右左
	int score;//分数
public:
Snake();//构造函数
void gameover();//游戏结束画面
void judge();//判断游戏是否结束
int change();//根据用户输入改变蛇的运动方向
void Fordir(int d);//AI设计中根据输入改变运动方向
void move();//蛇的移动函数
int eat();//判断是否吃食物
void display();//蛇的打印
int IfinBody(int x,int y);//判断任意点是否与蛇身重合
int headIfinBody(int x,int y);//判断除掉蛇头的任意点是否与蛇身重合
int wander();//蛇的“闲逛“函数
LinkList gethead();//获取蛇头指针
LinkList gettail();//获取蛇尾指针
}
其他函数:
void reInit();//对游戏数据的更新
int BFS(int x,int y,int a,int b);/*寻找从点(x,y)到(a,b)的路径,若存在,则返回1,并将路径储存在栈中,若不存在则返回0*/
int SearchChange();//在AI设计中通过计算返回蛇应该运动的方向
void InitGame();//初始化游戏

在此过程中,遇到过一个比较大的困难,在用BFS找到食物后,没法让蛇头按照找到的路线去吃食物,后来我想到一个方法,原先的chess数组仅用来储存点是否被访问过的信息,1表示访问过,0表示未访问,我把chess的功能拓展了,0表示未访问,非0表示访问过了,其中1表示该节点的父节点在其上方,2表示在下方,3右方,4左方,也就是chess数组在原有功能的基础上还可以储存路径信息,使得蛇头的寻路得以实现。

虽然现在蛇能够较好的自动寻路,且得到200以上的分数,但是这并不是该AI的终点,还可以更深的挖掘,在AI控制下蛇死亡是因为在Wander是无路可走,对于这个问题,我心里有了大致的解决方案:每次在按BFS算法得出的路径运动前都用一条“虚拟的蛇“去探路,然后看这条蛇在吃完食物后,有没有路可走了,如果没有路就不去吃食物,而是去追蛇尾或者“闲逛”。当然目前还是个算法雏形,待我日后实现。


  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值