既然是让步数最多,又由于对问题的简化局面中每次只会有一个食物,且无除边界外的障碍物。
可以想到比较 trick 的做法,当行数 n 或列数 m 为偶数时,可以构造哈密顿回路使得蛇必定可以在铺满整个地图后结束游戏。
当行数和列数都为奇数时,不存在哈密顿回路。所以只能设计估价函数来判断当前蛇应该走的方向。
一个比较简单容易想到的估价函数是,让蛇往最短路的方向走,并尽量让蛇走上一次移动的方向。
代码
下面的代码运行时会让你输入行数 n 和列数 m ,然后就可以看到智能(障)蛇了。
//蛇长度初始是5 H代表蛇的头部 X是蛇的身体//输入行数为 n 列数为 m //0 1 2 3 分别代表右下左上#include<bits/stdc++.h>#define inf 1e9#define rep(i,l,r) for (int i=l;i<=r;i++)usingnamespacestd;
int n,m,mcnt=0,x=1,y=5,pre,rx,ry,len=5;
struct node{int x,y;};
queue<node> q;
char Map[1005][1005];
void makemap(){
puts("n=");
scanf("%d",&n);
system("cls");
puts("m=");
scanf("%d",&m);
system("cls");
rep(i,0,n+1) rep(j,0,m+1) Map[i][j]=' ';
rep(i,0,m+1) Map[0][i]=Map[n+1][i]='*';
rep(i,0,n+1) Map[i][0]=Map[i][m+1]='*';
rep(i,1,4) Map[1][i]='X',q.push((node){1,i});
Map[1][5]='H'; q.push((node){1,5});
}
void init(){
while (1){
if (mcnt) break;
rx=rand()%n+1,ry=rand()%m+1;
if (Map[rx][ry]==' ') Map[rx][ry]='M',mcnt++;
}
rep(i,0,n+1) {
rep(j,0,m+1) printf("%c",Map[i][j]); puts("");
}
}
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int solve(int i){
int xx=x+dx[i],yy=y+dy[i];
if (Map[xx][yy]!=' '&&Map[xx][yy]!='M') return0;
if (Map[xx][yy]!='M') {
Map[q.front().x][q.front().y]=' '; q.pop();
} else mcnt--,len++;
Map[x][y]='X';
Map[xx][yy]='H'; q.push((node){xx,yy}); x=xx; y=yy;
return1;
}
void trick(){
if (x==m&&y==2) {solve(2); return;}
if (x==1&&y==1) {solve(0); return;}
if (y==1) solve(3);
else {
if (y==2) {
if (!solve(0)) solve(1);
}
elseif (y==m){
if (!solve(2)) solve(1);
}
else {
if (!solve(0)) solve(2);
}
}
}
void trick2(){
if (x==1&&y==m) {solve(1); return;}
if (x==2&&y==1) {solve(3); return;}
if (x==1) solve(0);
else {
if (x==2) {
if (!solve(1)) solve(2);
}
elseif (x==n){
if (!solve(3)) solve(2);
}
elseif (!solve(1)) solve(3);
}
}
int main(){
srand(time(NULL));
makemap();
pre=0;
while (1){
init();
int time=clock();
while (clock()-time<100);
int mn=inf,mni=-1;
int xx=x+dx[pre],yy=y+dy[pre];
if ((n&1)==0) {trick(); goto o;}
if ((m&1)==0) {trick2(); goto o;}
if (abs(xx-rx)+abs(yy-ry)<mn&&(Map[xx][yy]==' '||Map[xx][yy]=='M')) {
mn=abs(xx-rx)+abs(yy-ry); mni=pre;
}
rep(i,0,3) {
int xx=x+dx[i],yy=y+dy[i];
if (abs(xx-rx)+abs(yy-ry)<mn&&(Map[xx][yy]==' '||Map[xx][yy]=='M')) {
mn=abs(xx-rx)+abs(yy-ry); mni=i;
}
}
solve(mni); pre=mni;
if (mni==-1) {puts("GAME OVER"); break;}
o:;
if (len==n*m) {puts("GAME OVER"); break;}
system("cls");
}
}