前言
之前写了一个贪吃蛇的小游戏(命令行窗口),现在开始写一个简单的AI,大多资料都是从网上查找的,但是绝对不会抄,会自己实现和在基础上改进吧。
资料
网上的资料我看得懂的有四种方法:贪婪法、BFS、DFS和A*法
实现及改进
贪婪法就是走曼哈顿距离,即abs(x-food_x)+abs(y-food_y)最小且不会撞到墙或者是撞到自己身上。
int moveChangeX[4]={0,0,-1,1};
int moveChangeY[4]={-1,1,0,0};
char moveOper[4]= {'D','A','S','W'};
char moveAI_greedy() {
int x;
int y;
int min=INT_MAX,min_i;
for(int i=0; i<4; i++) {
x=snake->x+moveChangeX[i];
y=snake->y+moveChangeY[i];
if(!gameover()) {
int dist=fabs(x-moneyX)+fabs(y-moneyY);
if(min>dist) {
min=dist;
min_i=i;
}
}
}
if(min!=INT_MAX)
return moveOper[min_i];
else return 0;
}
BFS法就是广度优先搜索,将每个蛇头可以走到的地方插进队列中,直到搜索到食物的位置,再反向将这条路径存进栈中,但是这种方法有可能会暂时找不到路径,所以根据网上的资料,可以加一个闲逛机制,就是如果找不到路的话,就先闲逛一下。
void moveAI_BFS(void){
int tempMap[10][10];
bool isVisited[10][10];
for(int i=0;i<10;++i){
for(int j=0;j<10;++j){
isVisited[i][j]=false;
tempMap[i][j]=0;
}
}
struct snakePoint* temp=snake;
while(temp!=NULL) {
tempMap[temp->y][temp->x]=-1;
temp=temp->next;
}
clearMoveArr(moveArr);
queue<pair<int,int>> q;
int x,y;
int temp_x,temp_y;
tempMap[snake->y][snake->x]=0;
isVisited[snake->y][snake->x]=true;
q.push(make_pair<int,int>(snake->x,snake->y));
while(!q.empty()){
pair<int,int> p=q.top();
q.pop();
x=p.first;
y=p.second;
if(x==moneyX&&y==moneyY){
break;
}
for(int i=0;i<4;++i){
temp_x=x+moveChangeX[i];
temp_y=y+moveChangeY[i];
if(tempMap[temp_y][temp_x]!=-1&&isVisited[y][x]==false){
q.push(make_pair<int,int>(temp_x,temp_y));
tempMap[temp_y][temp_x]=tempMap[y][x]+1;
isVisited[temp_y][temp_x]=true
}
}
}
}