A*算法及困境部分改进的贪吃蛇

1.A*算法描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
2.A*算法实现


struct father
{
    int fx;int fy;
};//用于保存父区域 

struct father fathers[12][12];
int openlist[12][12];
int closelist[12][12];
int F[12][12];
int G[12][12];
int H[12][12];
int block[12][12];
void turn(int x,int y,int cx,int cy)
{
    fathers[x][y].fx=cx;
    fathers[x][y].fy=cy;
}
void cal(int x,int y,int cx,int cy)
{
    int add;
    if(x+y==cx+cy||x-y==cx-cy)
    add=14;
    else
    add=10;
    int amount=G[cx][cy]+add;
    if(amount<G[x][y])
    {
    turn(x,y,cx,cy); 
    G[x][y]=amount;
    F[x][y]=amount+H[x][y];
    }

}
void testing(int x,int y,int cx,int cy)//即(2)的第三步的操作 
{
    if(block[x][y]==1||closelist[x][y]==1)
    return;
    else
    {
    if(openlist[x][y]==0)   
    {
        openlist[x][y]=1;
        turn(x,y,cx,cy); 
    }
    else
    {
        cal(x,y,cx,cy);
    }

    }   
}
int abs(int x)
{
    return x>0?x:(-x);
}//返回的是某数的绝对值 
void Astar(int x,int y,int dx,int dy)//(x,y)即初始位置, (dx,dy)为目标位置 
{
    int i,j;
    int v,w;
    for(v=1;v<=10;v++)
    for(w=1;w<=10;w++)
    H[v][w]=abs(dx-v)*10+abs(dy-w)*10;
    F[x][y]=-1;
    G[x][y]=0;
    openlist[x][y]=1;//即(1)步骤 

    while(1)//即(2)步骤 
    {
    int i,j;int minf=50000,cx,cy;
    for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    {
        if(openlist[i][j]==1)
        {
            if(F[i][j]<minf)
            {
                minf=F[i][j];
                cx=i;
                cy=j;
            }
        }
     } //F值最小点(cx,cy);//即(2)的第一步 
     openlist[cx][cy]=0;
     closelist[cx][cy]=1;//即(2)的第二步 
     testing(cx+1,cy,cx,cy);
     testing(cx-1,cy,cx,cy);
     testing(cx,cy+1,cx,cy);
     testing(cx,cy-1,cx,cy);
     testing(cx-1,cy-1,cx,cy);
     testing(cx-1,cy+1,cx,cy);
     testing(cx+1,cy-1,cx,cy);
     testing(cx+1,cy+1,cx,cy); //均为(2)的第三步 
     if(openlist[dx][dy]==1)//即为(2)的第四步 
     break;
}

}

3.构造蛇身队列的实现

typedef struct queue{
    int x;
    int y;
    struct queue *next;
}queue ,*ptr;//定义了一个队列,神奇的是,front->next 指向蛇尾,rear指向蛇头 
queue q;
ptr front;
ptr rear;
int count;
int tt=0;
void enterq(int m,int n)
{
    queue *e;
    e=(struct queue *)malloc(sizeof(struct queue));
    e->x=m;
    e->y=n;
    e->next=NULL;
    rear->next=e;
    rear=e;
    count++;

}
void leaveq()
{
    front->next=front->next->next;
    count--;
    if(count==0)
    rear=front;
}

4.在本实例中,记“$”所在位置为(remainofx,remainofy)//为什么是remain后面有说明,可以理解为(remainofx,remainofy)为大目标,(xx,yy)为当前的小目标
5.在非蛇身区域设点的实现

void set()
{
    if(flag==1)
    {
    int fff,i,j;
    do
    {
        srand((unsigned)time(NULL));
         i=rand()%10+1;
         j=rand()%10+1;
        ptr p=front->next;
        fff=0;
        while(p!=NULL)
        {
            if(p->x==i&&p->y==j)
            fff=1;
            p=p->next;
        }
    }
    while(fff==1);
    remainofx=i;remainofy=j; 
    }
    else
    return ;
}

6.输入某字符后对蛇身队列的操作

void f(char c)
{
    int tmpx=rear->x;
    int tmpy=rear->y;
    leaveq();
    if(c=='w')
        enterq(tmpx,tmpy+1); 
    if(c=='s')
        enterq(tmpx,tmpy-1); 
    if(c=='a')
        enterq(tmpx-1,tmpy); 
    if(c=='d')
        enterq(tmpx+1,tmpy); 
    flag=0;
}//这个是假如蛇下一步没吃到的话,对队列的操作 
void eatenf(char c)
{
    int tmpx=rear->x;
    int tmpy=rear->y;
    if(c=='w')
        enterq(tmpx,tmpy+1); 
    if(c=='s')
        enterq(tmpx,tmpy-1); 
    if(c=='a')
        enterq(tmpx-1,tmpy); 
    if(c=='d')
        enterq(tmpx+1,tmpy); 
    if(rear->x==remainofx&&rear->y==remainofy)
    {
        flag=1;
    }   
    set();
}//这个是假如蛇下一步吃到的话,对队列的操作

7.打表实现

int map[120][120];
int wjudge;//这个是是否胜利判断 
void display()
{
    int i,j;
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    map[i][j]=0;
    ptr p=front;
    p=p->next;
    map[remainofx][remainofy]=3;
    map[rear->x][rear->y]=2;
    while(p!=rear)  
    {
        map[p->x][p->y]=1;
        p=p->next;
    }
    printf("\n\n\n");
    printf("\t\t\t\t************\n");
    for(j=10;j>=1;j--)
    {
        printf("\t\t\t\t*");
    for(i=1;i<=10;i++)
    {
        if(map[i][j]==3)
        printf("$");
        if(map[i][j]==2)
        printf("H");
        if(map[i][j]==1)
        printf("O");
        if(map[i][j]==0)
        printf(" ");        
    }
        printf("*\n");
    }
    printf("\t\t\t\t************\n\n");
    int gg=0;
    for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    if(map[i][j]==0||map[i][j]==3)
    gg=1;
    if(gg==0)
    wjudge=1;
}//用于打表 

8.游戏是否结束判断


int gameoverjudge()
{
    ptr p=front->next;
    if(rear->x<1||rear->x>10||rear->y<1||rear->y>10)
    return 1;
    while(p!=rear)
    {
        if(p->x==rear->x&&p->y==rear->y)
            return 1;
                p=p->next;
    }
    return 0;
}

9.头是否碰到自身判断


int CollisionWithItselfTest(char c)
{
    if(c=='w')
    if(rear->y==10) return 1;
    if(c=='s')
    if(rear->y==1) return 1;
    if(c=='a')
    if(rear->x==1) return 1;
    if(c=='d')
    if(rear->x==10) return 1;       
    ptr p=front->next;
    if(c=='w')
    {
        while(p!=rear)
        {
            if(p->x==rear->x&&p->y==rear->y+1)
            return 1;
            p=p->next;
        }
    }
        if(c=='s')
    {
        while(p!=rear)
        {
            if(p->x==rear->x&&p->y==rear->y-1)
            return 1;
            p=p->next;
        }
    }
        if(c=='a')
    {
        while(p!=rear)
        {
            if(p->x==rear->x-1&&p->y==rear->y)
            return 1;
            p=p->next;
        }
    }
        if(c=='d')
    {
        while(p!=rear)
        {
            if(p->x==rear->x+1&&p->y==rear->y)
            return 1;
            p=p->next;
        }
    }
    return 0;
}

10.最简单的求距离最短走法实现

char whereGoNext()
{   
ptr p;
p=front->next;
while(p->next!=rear)
p=p->next;//p为头前一个坐标地址 
char movable[5]={"wsad"};
int distance[4];
distance[0]=(xx-(rear->x))*(xx-(rear->x))+(yy-(rear->y+1))*(yy-(rear->y+1));
distance[1]=(xx-(rear->x))*(xx-(rear->x))+(yy-(rear->y-1))*(yy-(rear->y-1));
distance[2]=(xx-(rear->x-1))*(xx-(rear->x-1))+(yy-(rear->y))*(yy-(rear->y));
distance[3]=(xx-(rear->x+1))*(xx-(rear->x+1))+(yy-(rear->y))*(yy-(rear->y));
if(rear->x==p->x&&rear->y+1==p->y)
distance[0]=99;
if(rear->x==p->x&&rear->y-1==p->y)
distance[1]=99;
if(rear->x-1==p->x&&rear->y==p->y)
distance[2]=99;
if(rear->x+1==p->x&&rear->y==p->y)
distance[3]=99;
int b=0;
for(;b<4;b++)
if(CollisionWithItselfTest(movable[b])==1)
distance[b]=99;
int which;
int i=0;int min=10000;
for(;i<4;i++)
{
    if(distance[i]<min)
    {
        min=distance[i];
        which=i;
    }
}
return movable[which];
}

11.对蛇身队列操作的选择

int functionselecter(char c)
{
    if(c=='w')
        if(rear->y+1==remainofy&&rear->x==remainofx)
        return 0;
    if(c=='s')
        if(rear->y-1==remainofy&&rear->x==remainofx)
        return 0;
    if(c=='a')
        if(rear->y==remainofy&&rear->x-1==remainofx)
        return 0;
    if(c=='d')
        if(rear->y==remainofy&&rear->x+1==remainofx)
        return 0;
    return 1;
}

12.蛇头与”$”是否相邻判断


int adjacent()
{
    int rx=rear->x;int ry=rear->y;
    if(rx+1==xx&&ry==yy)
    return 1;
    if(rx+1==xx&&ry-1==yy)
    return 1;
    if(rx+1==xx&&ry+1==yy)
    return 1;
    if(rx==xx&&ry+1==yy)
    return 1;
    if(rx==xx&&ry-1==yy)
    return 1;
    if(rx-1==xx&&ry==yy)
    return 1;
    if(rx-1==xx&&ry+1==yy)
    return 1;
    if(rx-1==xx&&ry-1==yy)
    return 1;
    return 0;
}

13.通过递归进行判断:是否头与”$”间有通道(未考虑蛇身移动后有空位情况)

int indicator;
int mmmap[12][12];
int color[12][12];
int THEX;int THEY;
void approachable(int x,int y)
{
    if(x==THEX&&y==THEY)
    {
    indicator=1;
    return;         
    }
    if(x==0||y==0||x==11||y==11)
    return ;
    if(color[x+1][y]==0&&x<=9&&mmmap[x+1][y]==0)
    {color[x+1][y]=1;
    approachable(x+1,y);
    }
    if(color[x-1][y]==0&&x>=2&&mmmap[x-1][y]==0)
    {
        color[x-1][y]=1;
    approachable(x-1,y);
    }
    if(color[x][y+1]==0&&y<=9&&mmmap[x][y+1]==0)
    {
        color[x][y+1]=1;
    approachable(x,y+1);
    }
    if(color[x][y-1]==0&&y>=2&&mmmap[x][y-1]==0)
    {
        color[x][y-1]=1;
    approachable(x,y-1);
    }
}

14.将不能走到的点进行标记


void mark()
{
    int i,j;
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    color[i][j]=0;
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    mmmap[i][j]=0;
    ptr p=front->next;
    while(p!=rear)
    {
        mmmap[p->x][p->y]=1;    
        p=p->next;
    }
}

15.对困境部分进行改进(即当无通道时,将下一步的目标(xx,yy)设置为蛇可触及的且离”$”最远的四个直角边界点)(当上述设置失效(比如四点都被占了或蛇仍然无法走到),则设置下一步的目标(xx,yy)为头的上下左右中的任一空位)


void function()
{
        int i,j;
    int map[12][12];
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    map[i][j]=0;
    ptr p=front->next;

    int d[6];
    d[1]=(remainofx-1)*(remainofx-1)+(remainofy-1)*(remainofy-1);
     d[2]=(remainofx-10)*(remainofx-10)+(remainofy-1)*(remainofy-1);
     d[3]=(remainofx-10)*(remainofx-10)+(remainofy-10)*(remainofy-10);
     d[4]=(remainofx-1)*(remainofx-1)+(remainofy-10)*(remainofy-10);int in[6];int nn;for(nn=1;nn<=4;nn++)in[nn]=1;
    indicator=0;
    THEX=1;THEY=1;approachable(rear->x,rear->y);
    if(indicator==0)
    in[1]=0;
    indicator=0;
    THEX=10;THEY=1;approachable(rear->x,rear->y);
    if(indicator==0)
    in[2]=0;
    indicator=0;
    THEX=10;THEY=10;approachable(rear->x,rear->y);
    if(indicator==0)
    in[3]=0;
    indicator=0;
    THEX=1;THEY=10;approachable(rear->x,rear->y);
    if(indicator==0)
    in[4]=0;
    indicator=0;
    int a,b;int max=-1;
    for(a=1;a<=4;a++)
    {
    if(in[a]==1)
    {
        if(d[i]>max)
        {
            max=d[i];
            b=a;
        }
    }

    }

    if(max!=-1)
    {

    if(b==1)
    {
        xx=1;yy=1;return ;
    }
    if(b==2)
    {
        xx=10;yy=1;return;
    }
    if(b==3)
    {
        xx=10;yy=10;return ;
    }
    if(b==4)
    {
        xx=1;yy=10;return ;
    }
    }
    else{

    while(p!=rear)
    {
        map[p->x][p->y]=1;  
        p=p->next;
    }   
    if(map[rear->x-1][rear->y]==0&&rear->x>=2)
    {
    xx=xx-1;return ;
    }   
    if(map[rear->x+1][rear->y]==0&&rear->x<=9)
    {
    xx=xx+1;return ;    
    }
    if(map[rear->x][rear->y+1]==0&&rear->y<=9)
    {
    yy=yy+1;return ;
    }
    if(map[rear->x][rear->y-1]==0&&rear->y>=2)
    {
    yy=yy-1;return ;
    }
}
}

16.鉴于有时A*算法对近在眼前的目标反而运算慢,所以这里让蛇对近在眼前的目标直接吃掉

int QuickGet()
 {
    int rx=rear->x;
    int ry=rear->y;
    if(rx+1==remainofx&&ry==remainofy)
    return 1;
    if(rx==remainofx&&ry+1==remainofy)
    return 1;
    if(rx==remainofx&&ry-1==remainofy)
    return 1;
    if(rx-1==remainofx&&ry==remainofy)
    return 1;
    return 0;
 }

17.主函数

int main()
{
    memset(block,0,sizeof(block));
    int bb;
    for(bb=0;bb<=11;bb++)
    block[0][bb]=1;
    for(bb=0;bb<=11;bb++)
    block[bb][0]=1;
    for(bb=0;bb<=11;bb++)
    block[11][bb]=1;
    for(bb=0;bb<=11;bb++)
    block[bb][11]=1;//将四周设为A*中不可到达 


    count=1;
    wjudge=0; 
    front=&q;
    rear =&q;
    q.next=NULL;
    int x;
    for(x=1;x<=5;x++)
    enterq(x,10);//入队操作 
    flag=1;
    set();
    display();


    while(1)
    {
    DWORD start=GetTickCount();
    system("CLS");
    mark();
    indicator=0;
    THEX=remainofx;THEY=remainofy;          
    memset(block,0,sizeof(block));


    ptr qa=front->next;
    while(qa!=rear)
    {
    block[qa->x][qa->y]=1;
    qa=qa->next;
    }
    approachable(rear->x,rear->y);


    if(QuickGet()!=0)
    {
        xx=remainofx;
        yy=remainofy;
    }
    else    
    {
    if(indicator==0)
    {
    function(); 
    indicator=0;
    }
    else{       
    int i,j;
    for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    {
        fathers[i][j].fx=i;
        fathers[i][j].fy=j;
    }
        for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    {
        block[i][j]=0;
    }
    memset(openlist,0,sizeof(openlist));
    memset(closelist,0,sizeof(closelist));
    memset(F,0,sizeof(F));
    memset(G,0,sizeof(G));
    memset(H,0,sizeof(H));

    ptr p=front->next;
        while(p!=rear)
        {
            block[p->x][p->y]=1;
            p=p->next;
        }
            Astar(rear->x,rear->y,remainofx,remainofy); 

            xx=remainofx;yy=remainofy;
            while((fathers[xx][yy].fx==rear->x&&fathers[xx][yy].fy==rear->y)!=1&&(adjacent()==0))//这里的意思就是,通过父区域的回溯,从(remainofx,remainofy)开始,使(xx,yy)为蛇下一个移动的目标 
            {
            int tx=fathers[xx][yy].fx;
            int ty=fathers[xx][yy].fy;
            xx=tx;
            yy=ty;
        }
    }
    }


        char c=whereGoNext();
        switch(c)
        {
            case 'w':functionselecter(c)==1?f('w'):eatenf('w');break;
            case 's':functionselecter(c)==1?f('s'):eatenf('s');break;
            case 'a':functionselecter(c)==1?f('a'):eatenf('a');break;
            case 'd':functionselecter(c)==1?f('d'):eatenf('d');break;
            default:continue;
        }
        if(gameoverjudge()==1)
        {
            display();
            printf("\n\t\t\t\tGAMEOVER!!!!!!\n");
            break;
        }
        if(wjudge==1)
        {
            printf("\n\t\t\t\tWIN!!\n");
            break;
        }
        else
        display();
        DWORD end=GetTickCount();
        int time=end - start;
        if(time>=200)
        continue;
        else
    Sleep(200-time);//使每次更新的间隔都大概为0.2秒 
        }

    }

18.汇总

#include <stdio.h>
#include <malloc.h> 
#include <time.h>
#include <memory.h>
#include <windows.h>

int flag;
int xx,yy;
int remainofx,remainofy;



struct father
{
    int fx;int fy;
};//用于保存父区域 

struct father fathers[12][12];
int openlist[12][12];
int closelist[12][12];
int F[12][12];
int G[12][12];
int H[12][12];
int block[12][12];
void turn(int x,int y,int cx,int cy)
{
    fathers[x][y].fx=cx;
    fathers[x][y].fy=cy;
}
void cal(int x,int y,int cx,int cy)
{
    int add;
    if(x+y==cx+cy||x-y==cx-cy)
    add=14;
    else
    add=10;
    int amount=G[cx][cy]+add;
    if(amount<G[x][y])
    {
    turn(x,y,cx,cy); 
    G[x][y]=amount;
    F[x][y]=amount+H[x][y];
    }

}
void testing(int x,int y,int cx,int cy)//即(2)的第三步的操作 
{
    if(block[x][y]==1||closelist[x][y]==1)
    return;
    else
    {
    if(openlist[x][y]==0)   
    {
        openlist[x][y]=1;
        turn(x,y,cx,cy); 
    }
    else
    {
        cal(x,y,cx,cy);
    }

    }   
}
int abs(int x)
{
    return x>0?x:(-x);
}//返回的是某数的绝对值 
void Astar(int x,int y,int dx,int dy)//(x,y)即初始位置, (dx,dy)为目标位置 
{
    int i,j;
    int v,w;
    for(v=1;v<=10;v++)
    for(w=1;w<=10;w++)
    H[v][w]=abs(dx-v)*10+abs(dy-w)*10;
    F[x][y]=-1;
    G[x][y]=0;
    openlist[x][y]=1;//即(1)步骤 

    while(1)//即(2)步骤 
    {
    int i,j;int minf=50000,cx,cy;
    for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    {
        if(openlist[i][j]==1)
        {
            if(F[i][j]<minf)
            {
                minf=F[i][j];
                cx=i;
                cy=j;
            }
        }
     } //F值最小点(cx,cy);//即(2)的第一步 
     openlist[cx][cy]=0;
     closelist[cx][cy]=1;//即(2)的第二步 
     testing(cx+1,cy,cx,cy);
     testing(cx-1,cy,cx,cy);
     testing(cx,cy+1,cx,cy);
     testing(cx,cy-1,cx,cy);
     testing(cx-1,cy-1,cx,cy);
     testing(cx-1,cy+1,cx,cy);
     testing(cx+1,cy-1,cx,cy);
     testing(cx+1,cy+1,cx,cy); //均为(2)的第三步 
     if(openlist[dx][dy]==1)//即为(2)的第四步 
     break;
}

}
typedef struct queue{
    int x;
    int y;
    struct queue *next;
}queue ,*ptr;//定义了一个队列,神奇的是,front->next 指向蛇尾,rear指向蛇头 
queue q;
ptr front;
ptr rear;
int count;
int tt=0;
void enterq(int m,int n)
{
    queue *e;
    e=(struct queue *)malloc(sizeof(struct queue));
    e->x=m;
    e->y=n;
    e->next=NULL;
    rear->next=e;
    rear=e;
    count++;

}
void leaveq()
{
    front->next=front->next->next;
    count--;
    if(count==0)
    rear=front;
}
void set()
{
    if(flag==1)
    {
    int fff,i,j;
    do
    {
        srand((unsigned)time(NULL));
         i=rand()%10+1;
         j=rand()%10+1;
        ptr p=front->next;
        fff=0;
        while(p!=NULL)
        {
            if(p->x==i&&p->y==j)
            fff=1;
            p=p->next;
        }
    }
    while(fff==1);
    remainofx=i;remainofy=j; 
    }
    else
    return ;
}
void f(char c)
{
    int tmpx=rear->x;
    int tmpy=rear->y;
    leaveq();
    if(c=='w')
        enterq(tmpx,tmpy+1); 
    if(c=='s')
        enterq(tmpx,tmpy-1); 
    if(c=='a')
        enterq(tmpx-1,tmpy); 
    if(c=='d')
        enterq(tmpx+1,tmpy); 
    flag=0;
}//这个是假如蛇下一步没吃到的话,对队列的操作 
void eatenf(char c)
{
    int tmpx=rear->x;
    int tmpy=rear->y;
    if(c=='w')
        enterq(tmpx,tmpy+1); 
    if(c=='s')
        enterq(tmpx,tmpy-1); 
    if(c=='a')
        enterq(tmpx-1,tmpy); 
    if(c=='d')
        enterq(tmpx+1,tmpy); 
    if(rear->x==remainofx&&rear->y==remainofy)
    {
        flag=1;
    }   
    set();
}//这个是假如蛇下一步吃到的话,对队列的操作
int map[120][120];
int wjudge;//这个是是否胜利判断 
void display()
{
    int i,j;
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    map[i][j]=0;
    ptr p=front;
    p=p->next;
    map[remainofx][remainofy]=3;
    map[rear->x][rear->y]=2;
    while(p!=rear)  
    {
        map[p->x][p->y]=1;
        p=p->next;
    }
    printf("\n\n\n");
    printf("\t\t\t\t************\n");
    for(j=10;j>=1;j--)
    {
        printf("\t\t\t\t*");
    for(i=1;i<=10;i++)
    {
        if(map[i][j]==3)
        printf("$");
        if(map[i][j]==2)
        printf("H");
        if(map[i][j]==1)
        printf("O");
        if(map[i][j]==0)
        printf(" ");        
    }
        printf("*\n");
    }
    printf("\t\t\t\t************\n\n");
    int gg=0;
    for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    if(map[i][j]==0||map[i][j]==3)
    gg=1;
    if(gg==0)
    wjudge=1;
}//用于打表 

int gameoverjudge()
{
    ptr p=front->next;
    if(rear->x<1||rear->x>10||rear->y<1||rear->y>10)
    return 1;
    while(p!=rear)
    {
        if(p->x==rear->x&&p->y==rear->y)
            return 1;
                p=p->next;
    }
    return 0;
}
int CollisionWithItselfTest(char c)
{
    if(c=='w')
    if(rear->y==10) return 1;
    if(c=='s')
    if(rear->y==1) return 1;
    if(c=='a')
    if(rear->x==1) return 1;
    if(c=='d')
    if(rear->x==10) return 1;       
    ptr p=front->next;
    if(c=='w')
    {
        while(p!=rear)
        {
            if(p->x==rear->x&&p->y==rear->y+1)
            return 1;
            p=p->next;
        }
    }
        if(c=='s')
    {
        while(p!=rear)
        {
            if(p->x==rear->x&&p->y==rear->y-1)
            return 1;
            p=p->next;
        }
    }
        if(c=='a')
    {
        while(p!=rear)
        {
            if(p->x==rear->x-1&&p->y==rear->y)
            return 1;
            p=p->next;
        }
    }
        if(c=='d')
    {
        while(p!=rear)
        {
            if(p->x==rear->x+1&&p->y==rear->y)
            return 1;
            p=p->next;
        }
    }
    return 0;
}
char whereGoNext()
{   
ptr p;
p=front->next;
while(p->next!=rear)
p=p->next;//p为头前一个坐标地址 
char movable[5]={"wsad"};
int distance[4];
distance[0]=(xx-(rear->x))*(xx-(rear->x))+(yy-(rear->y+1))*(yy-(rear->y+1));
distance[1]=(xx-(rear->x))*(xx-(rear->x))+(yy-(rear->y-1))*(yy-(rear->y-1));
distance[2]=(xx-(rear->x-1))*(xx-(rear->x-1))+(yy-(rear->y))*(yy-(rear->y));
distance[3]=(xx-(rear->x+1))*(xx-(rear->x+1))+(yy-(rear->y))*(yy-(rear->y));
if(rear->x==p->x&&rear->y+1==p->y)
distance[0]=99;
if(rear->x==p->x&&rear->y-1==p->y)
distance[1]=99;
if(rear->x-1==p->x&&rear->y==p->y)
distance[2]=99;
if(rear->x+1==p->x&&rear->y==p->y)
distance[3]=99;
int b=0;
for(;b<4;b++)
if(CollisionWithItselfTest(movable[b])==1)
distance[b]=99;
int which;
int i=0;int min=10000;
for(;i<4;i++)
{
    if(distance[i]<min)
    {
        min=distance[i];
        which=i;
    }
}
return movable[which];
}

int functionselecter(char c)
{
    if(c=='w')
        if(rear->y+1==remainofy&&rear->x==remainofx)
        return 0;
    if(c=='s')
        if(rear->y-1==remainofy&&rear->x==remainofx)
        return 0;
    if(c=='a')
        if(rear->y==remainofy&&rear->x-1==remainofx)
        return 0;
    if(c=='d')
        if(rear->y==remainofy&&rear->x+1==remainofx)
        return 0;
    return 1;
}

int adjacent()
{
    int rx=rear->x;int ry=rear->y;
    if(rx+1==xx&&ry==yy)
    return 1;
    if(rx+1==xx&&ry-1==yy)
    return 1;
    if(rx+1==xx&&ry+1==yy)
    return 1;
    if(rx==xx&&ry+1==yy)
    return 1;
    if(rx==xx&&ry-1==yy)
    return 1;
    if(rx-1==xx&&ry==yy)
    return 1;
    if(rx-1==xx&&ry+1==yy)
    return 1;
    if(rx-1==xx&&ry-1==yy)
    return 1;
    return 0;
}
int indicator;
int mmmap[12][12];
int color[12][12];
int THEX;int THEY;
void approachable(int x,int y)
{
    if(x==THEX&&y==THEY)
    {
    indicator=1;
    return;         
    }
    if(x==0||y==0||x==11||y==11)
    return ;
    if(color[x+1][y]==0&&x<=9&&mmmap[x+1][y]==0)
    {color[x+1][y]=1;
    approachable(x+1,y);
    }
    if(color[x-1][y]==0&&x>=2&&mmmap[x-1][y]==0)
    {
        color[x-1][y]=1;
    approachable(x-1,y);
    }
    if(color[x][y+1]==0&&y<=9&&mmmap[x][y+1]==0)
    {
        color[x][y+1]=1;
    approachable(x,y+1);
    }
    if(color[x][y-1]==0&&y>=2&&mmmap[x][y-1]==0)
    {
        color[x][y-1]=1;
    approachable(x,y-1);
    }
}
void mark()
{
    int i,j;
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    color[i][j]=0;
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    mmmap[i][j]=0;
    ptr p=front->next;
    while(p!=rear)
    {
        mmmap[p->x][p->y]=1;    
        p=p->next;
    }
}
void function()
{
        int i,j;
    int map[12][12];
    for(i=0;i<12;i++)
    for(j=0;j<12;j++)
    map[i][j]=0;
    ptr p=front->next;

    int d[6];
    d[1]=(remainofx-1)*(remainofx-1)+(remainofy-1)*(remainofy-1);
     d[2]=(remainofx-10)*(remainofx-10)+(remainofy-1)*(remainofy-1);
     d[3]=(remainofx-10)*(remainofx-10)+(remainofy-10)*(remainofy-10);
     d[4]=(remainofx-1)*(remainofx-1)+(remainofy-10)*(remainofy-10);int in[6];int nn;for(nn=1;nn<=4;nn++)in[nn]=1;
    indicator=0;
    THEX=1;THEY=1;approachable(rear->x,rear->y);
    if(indicator==0)
    in[1]=0;
    indicator=0;
    THEX=10;THEY=1;approachable(rear->x,rear->y);
    if(indicator==0)
    in[2]=0;
    indicator=0;
    THEX=10;THEY=10;approachable(rear->x,rear->y);
    if(indicator==0)
    in[3]=0;
    indicator=0;
    THEX=1;THEY=10;approachable(rear->x,rear->y);
    if(indicator==0)
    in[4]=0;
    indicator=0;
    int a,b;int max=-1;
    for(a=1;a<=4;a++)
    {
    if(in[a]==1)
    {
        if(d[i]>max)
        {
            max=d[i];
            b=a;
        }
    }

    }

    if(max!=-1)
    {

    if(b==1)
    {
        xx=1;yy=1;return ;
    }
    if(b==2)
    {
        xx=10;yy=1;return;
    }
    if(b==3)
    {
        xx=10;yy=10;return ;
    }
    if(b==4)
    {
        xx=1;yy=10;return ;
    }
    }
    else{

    while(p!=rear)
    {
        map[p->x][p->y]=1;  
        p=p->next;
    }   
    if(map[rear->x-1][rear->y]==0&&rear->x>=2)
    {
    xx=xx-1;return ;
    }   
    if(map[rear->x+1][rear->y]==0&&rear->x<=9)
    {
    xx=xx+1;return ;    
    }
    if(map[rear->x][rear->y+1]==0&&rear->y<=9)
    {
    yy=yy+1;return ;
    }
    if(map[rear->x][rear->y-1]==0&&rear->y>=2)
    {
    yy=yy-1;return ;
    }
}
}

 int QuickGet()
 {
    int rx=rear->x;
    int ry=rear->y;
    if(rx+1==remainofx&&ry==remainofy)
    return 1;
    if(rx==remainofx&&ry+1==remainofy)
    return 1;
    if(rx==remainofx&&ry-1==remainofy)
    return 1;
    if(rx-1==remainofx&&ry==remainofy)
    return 1;
    return 0;
 }
int main()
{
    memset(block,0,sizeof(block));
    int bb;
    for(bb=0;bb<=11;bb++)
    block[0][bb]=1;
    for(bb=0;bb<=11;bb++)
    block[bb][0]=1;
    for(bb=0;bb<=11;bb++)
    block[11][bb]=1;
    for(bb=0;bb<=11;bb++)
    block[bb][11]=1;//将四周设为A*中不可到达 


    count=1;
    wjudge=0; 
    front=&q;
    rear =&q;
    q.next=NULL;
    int x;
    for(x=1;x<=5;x++)
    enterq(x,10);//入队操作 
    flag=1;
    set();
    display();


    while(1)
    {
    DWORD start=GetTickCount();
    system("CLS");
    mark();
    indicator=0;
    THEX=remainofx;THEY=remainofy;          
    memset(block,0,sizeof(block));


    ptr qa=front->next;
    while(qa!=rear)
    {
    block[qa->x][qa->y]=1;
    qa=qa->next;
    }
    approachable(rear->x,rear->y);


    if(QuickGet()!=0)
    {
        xx=remainofx;
        yy=remainofy;
    }
    else    
    {
    if(indicator==0)
    {
    function(); 
    indicator=0;
    }
    else{       
    int i,j;
    for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    {
        fathers[i][j].fx=i;
        fathers[i][j].fy=j;
    }
        for(i=1;i<=10;i++)
    for(j=1;j<=10;j++)
    {
        block[i][j]=0;
    }
    memset(openlist,0,sizeof(openlist));
    memset(closelist,0,sizeof(closelist));
    memset(F,0,sizeof(F));
    memset(G,0,sizeof(G));
    memset(H,0,sizeof(H));

    ptr p=front->next;
        while(p!=rear)
        {
            block[p->x][p->y]=1;
            p=p->next;
        }
            Astar(rear->x,rear->y,remainofx,remainofy); 

            xx=remainofx;yy=remainofy;
            while((fathers[xx][yy].fx==rear->x&&fathers[xx][yy].fy==rear->y)!=1&&(adjacent()==0))//这里的意思就是,通过父区域的回溯,从(remainofx,remainofy)开始,使(xx,yy)为蛇下一个移动的目标 
            {
            int tx=fathers[xx][yy].fx;
            int ty=fathers[xx][yy].fy;
            xx=tx;
            yy=ty;
        }
    }
    }


        char c=whereGoNext();
        switch(c)
        {
            case 'w':functionselecter(c)==1?f('w'):eatenf('w');break;
            case 's':functionselecter(c)==1?f('s'):eatenf('s');break;
            case 'a':functionselecter(c)==1?f('a'):eatenf('a');break;
            case 'd':functionselecter(c)==1?f('d'):eatenf('d');break;
            default:continue;
        }
        if(gameoverjudge()==1)
        {
            display();
            printf("\n\t\t\t\tGAMEOVER!!!!!!\n");
            break;
        }
        if(wjudge==1)
        {
            printf("\n\t\t\t\tWIN!!\n");
            break;
        }
        else
        display();
        DWORD end=GetTickCount();
        int time=end - start;
        if(time>=200)
        continue;
        else
    Sleep(200-time);//使每次更新的间隔都大概为0.2秒 
        }

    }

19.演示
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值