由于上篇关于贪吃蛇的做法,我已将自己的做法详述地介绍,所以此片不做多余的介绍关于贪吃蛇,这里主要介绍贪吃蛇的进阶版。
首先,我们要思考如何写出一条智能设,使它‘思考’,所以想想,蛇每打算走一步,都先想想是往四个方向的哪个走,所以它先计算每个方向到食物的位置,然后选出最小的方向,但最小的方向也可能有它的身体或墙,所以必须判断一下,看看是否有障碍,如果有,就在另外三条中选择,以此内推,先写出伪代码。
控制方向
// Hx,Hy: 头的位置
// Fx,Fy:食物的位置
function whereGoNext(Hx,Hy,Fx,Fy) {
// 用数组movable[3]={“a”,”d”,”w”,”s”} 记录可走的方向
// 用数组distance[3]={0,0,0,0} 记录离食物的距离
// 分别计算蛇头周边四个位置到食物的距离。H头的位置,F食物位置
// 例如:假设输入”a” 则distance[0] = |Fx – (Hx-1)| + |Fy – Hy|
// 如果 Hx-1,Hy 位置不是Blank,则 distance[0] = 9999
// 选择distance中存最小距离的下标p,注意最小距离不能是9999
// 返回 movable[p]
}
程序框架
输出字符矩阵
WHILE not 游戏结束 DO
wait(time)
ch=whereGoNext(Hx,Hy,Fx,Fy)
CASE ch DO
‘A’:左前进一步,break
‘D’:右前进一步,break
‘W’:上前进一步,break
‘S’:下前进一步,break
END CASE
输出字符矩阵
END WHILE
输出 Game Over!!!
开始,先计算距离
int cal_dis(int m,int n)
{
int ins_x = snake_x[snake_length-1];
int ins_y = snake_y[snake_length-1];
int dis;
dis = abs(food_x-(ins_y-m))+abs(food_y-(ins_x-n));// notice
return dis;
}
int abs(int a)
{
if(a>=0)
return a;
return -a;
}
选择最小
int*get_min(int*a,int*b,int*c,int*d)
{
int*jmin;
jmin = *a<=*b?a:b;
jmin = *jmin<=*c?jmin:c;
jmin = *jmin<=*d?jmin:d;
return jmin;
}
然后选择方向
int snake_where_to_go(int min1,int dist_a,int dist_s,int dist_d,int dist_w)
{
if(min1 == dist_a)
{
snakeHeadMove(-1,0);
if(map[snake_y[snake_length-1]][snake_x[snake_length-1]-1]!='x'&&map[snake_y[snake_length-1]][snake_x[snake_length-1]-1]!='*')
{
gameover();
return 1;
}
else
return 0;
}
if(min1 == dist_s)
{
snakeHeadMove(0,1);
if (map[snake_y[snake_length-1]+1][snake_x[snake_length-1]]!='x'&&map[snake_y[snake_length-1]+1][snake_x[snake_length-1]]!='*')
{
gameover();
return 1;
}
else
return 0;
}
if(min1 == dist_d )
{
snakeHeadMove(1,0);
if( map[snake_y[snake_length-1]][snake_x[snake_length-1]+1]!='x'&&map[snake_y[snake_length-1]][snake_x[snake_length-1]+1]!='*')
{
gameover();
return 1;
}
else
return 0;
}
if(min1 == dist_w)
{
snakeHeadMove(0,-1);
if(map[snake_y[snake_length-1]-1][snake_x[snake_length-1]]!='x'&&map[snake_y[snake_length-1]-1][snake_x[snake_length-1]]!='*')
{
gameover();
return 1;
}
else
return 0;
}
return 0;
}
蛇的控制逻辑
while(!input)
{
int i,j,mid;
char ins;
distan[0]= cal_dis(0,1);
distan[1]= cal_dis(-1,0);
distan[2]= cal_dis(0,-1);
distan[3]= cal_dis(1,0);
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
*min = 999;
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
*min = 999;
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
*min = 999;
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
break;
}
printf("Game over!!!");
所以我们得到的智能蛇的完全代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define max_length 100
#define snake_body 'x'
#define snake_head 'H'
void output(void);
void put_money(void);
int*get_min(int*a,int *b,int *c,int *d);
int judge(int a ,int b);
int abs(int a);
int snake_where_to_go(int min,int dist_a,int dist_s,int dist_d,int dist_w);
int cal_dis(int m,int n);
void snakeHeadMove(int m,int n);
//int get_min1(int a,int b,int c);
//int get_min2(int a,int b);;
int min_dis(void);
int food_x=0,food_y=0;
int gameover(void);
void snakemove(void);
int min_x=0,min_y=0;
char map[12][12]=
{"***********",
"*xxxxH *",
"* *",
"* * *",
"* * *",
"* * *",
"* * *",
"* * *",
"* *",
"* *",
"* *",
"***********"};//initialize the picture
int snake_length=5;
int distan[4]={0};
int snake_x[max_length]={1,2,3,4,5};
int snake_y[max_length]={1,1,1,1,1};
int main()
{
int *min,i=0;
char input=0,c;
put_money();
output();//output the picture
while(!input)
{
c = getch();//read the botton
switch (c) //move the snake head
{
case 'w': snakeHeadMove(0,-1); break;
case 's': snakeHeadMove(0,1); break;
case 'a': snakeHeadMove(-1,0); break;
case 'd': snakeHeadMove(1,0); break;
case 'z': goto part;
}
input = gameover();
if(input) break;//judge if game is over
/*while(getchar() != '\n')//cancel the '\n' when to entry the botton
break;*/
}
part :
while(!input)
{
int i,j,mid;
char ins;
distan[0]= cal_dis(0,1);
distan[1]= cal_dis(-1,0);
distan[2]= cal_dis(0,-1);
distan[3]= cal_dis(1,0);
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
*min = 999;
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
*min = 999;
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
*min = 999;
min = get_min(&distan[0],&distan[1],&distan[2],&distan[3]);
i = snake_where_to_go(*min,distan[0],distan[1],distan[2],distan[3]);
if(i)
continue;
break;
}
printf("Game over!!!");
}
int*get_min(int*a,int*b,int*c,int*d)
{
int*jmin;
jmin = *a<=*b?a:b;
jmin = *jmin<=*c?jmin:c;
jmin = *jmin<=*d?jmin:d;
return jmin;
}
int snake_where_to_go(int min1,int dist_a,int dist_s,int dist_d,int dist_w)
{
if(min1 == dist_a)
{
snakeHeadMove(-1,0);
if(map[snake_y[snake_length-1]][snake_x[snake_length-1]-1]!='x'&&map[snake_y[snake_length-1]][snake_x[snake_length-1]-1]!='*')
{
gameover();
return 1;
}
else
return 0;
}
if(min1 == dist_s)
{
snakeHeadMove(0,1);
if (map[snake_y[snake_length-1]+1][snake_x[snake_length-1]]!='x'&&map[snake_y[snake_length-1]+1][snake_x[snake_length-1]]!='*')
{
gameover();
return 1;
}
else
return 0;
}
if(min1 == dist_d )
{
snakeHeadMove(1,0);
if( map[snake_y[snake_length-1]][snake_x[snake_length-1]+1]!='x'&&map[snake_y[snake_length-1]][snake_x[snake_length-1]+1]!='*')
{
gameover();
return 1;
}
else
return 0;
}
if(min1 == dist_w)
{
snakeHeadMove(0,-1);
if(map[snake_y[snake_length-1]-1][snake_x[snake_length-1]]!='x'&&map[snake_y[snake_length-1]-1][snake_x[snake_length-1]]!='*')
{
gameover();
return 1;
}
else
return 0;
}
return 0;
}
int cal_dis(int m,int n)
{
int ins_x = snake_x[snake_length-1];
int ins_y = snake_y[snake_length-1];
int dis;
dis = abs(food_x-(ins_y-m))+abs(food_y-(ins_x-n));// notice
return dis;
}
int abs(int a)
{
if(a>=0)
return a;
return -a;
}
void output(void)// output the picture
{
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
int i =0;
while(i<12)
{
printf("%s\n",map[i]);
i++;
}
printf("if you want to play you self,press 'a' 's' 'd' 'w'\n");
printf("if you want to look intelligent snake ,press 'z'\n");
}
void put_money(void)//put the money randomly
{
srand((unsigned int)time(0));
while(map[food_x][food_y]=='*'||map[food_x][food_y]==snake_body||map[food_x][food_y]==snake_head)
{
food_x = rand()%10 + 1;
food_y = rand()%10 + 1;
}
map[food_x][food_y] = '$';
}
void snakeHeadMove(int m,int n)// move the snake head
{
snake_x[snake_length]=snake_x[snake_length-1]+m;
snake_y[snake_length]=snake_y[snake_length-1]+n;
}
int gameover(void)
{
int i,j,mid;
char ins;
if(map[snake_y[snake_length]][snake_x[snake_length]]==snake_body||map[snake_y[snake_length]][snake_x[snake_length]]=='*')
return 1;//return 1 if snake is dead
else if(map[snake_y[snake_length]][snake_x[snake_length]]=='$')//eat the money
{
mid = snake_length;
map[snake_y[mid]][snake_x[mid]] = snake_body;//put 'x' in the front of head
ins = map[snake_y[mid-1]][snake_x[mid-1]];
map[snake_y[mid-1]][snake_x[mid-1]] = map[snake_y[mid]][snake_x[mid]];
map[snake_y[mid]][snake_x[mid]] = ins;//change the position of snakehead and 'x'
snake_length++;//the length of snake add 1
put_money();//put money
output();
return 0;
}
else
{
snakemove();// move the snake
output();
return 0;
}
}
void snakemove(void)//move the snake
{
int i,j;
char ins;
for(i=snake_length;i > 0;i--)
{
ins=map[snake_y[i]][snake_x[i]];
map[snake_y[i]][snake_x[i]]=map[snake_y[i-1]][snake_x[i-1]];
map[snake_y[i-1]][snake_x[i-1]]=ins;//move
}
for(j=0;j<=snake_length;j++)//change the ordinate of snake
{
snake_x[j]=snake_x[j+1];
snake_y[j]=snake_y[j+1];
}
snake_x[snake_length]=0;
snake_y[snake_length]=0;
}
终于,我们可以看到我们的贪吃蛇即可以自己躲避障碍物(就算是自己添加的,也只需在代码中补充一点点就可以了),但这条蛇不能主动地选出最佳路线,可能会走到死胡同,如何选择路线,请读者自行思悟(作者能力有限),当然这篇博客较于上一篇还是有些省略,请读者仔细思考上面的代码,再写出自己的智能贪吃蛇