博弈树

下棋属于一种博弈游戏,博弈过程可以用树(博弈树)来表示。假设游戏由两个人( A 和 B )玩,开始由某个人从根结点开始走,两个人轮流走棋,每次只能走一步, 下一步棋只能选择当前结点的孩子结点,谁先走到叶子结点为胜。例如,对于下图所示的博弈树,若 A 先走,可以选 f , B 若选 h ,则 A 选 j 胜。

编写一程序,让计算机和人下棋。当计算机走下一步时,可以根据以下情况决定下一步:

(1) 若存在可以确保取胜的一个孩子结点,则选择该结点作为下一步;

(2) 若存在多个可以确保取胜的孩子结点,则选择其中高度最小的结点作为下一步(若有多个选择,则选最左边的结点);

(3) 若不存在可以确保取胜的一个孩子结点,则选择高度最大的孩子结点作为下一步(若有多个选择,则选最左边的结点);

例: (下面的黑体为输入)

(a,(b,(x)),(c,(d),(e,(g),(h)),(f)))

a

b

x

c

d

e

g

h

f

Who play first(0: computer; 1: player )?

1

player:

c

computer: d

Sorry, you lost.

Continue(y/n)?

y

Who play first(0: computer; 1: player )?

1

player:

x

illegal move.

player:

b

computer: x

Sorry, you lost.

Continue(y/n)?

y

Who play first(0: computer; 1: player )?

0

computer: c

player:

f

Congratulate, you win.

Continue(y/n)?

n

 测试输入关于“测试输入”的帮助期待的输出关于“期待的输出”的帮助时间限制关于“时间限制”的帮助内存限制关于“内存限制”的帮助额外进程关于“{$a} 个额外进程”的帮助
测试用例 1以文本方式显示
  1. (a,(b,(x)),(c,(d),(e,(g),(h)),(f)))↵
  2. 1↵
  3. c↵
  4. y↵
  5. 1↵
  6. x↵
  7. b↵
  8. y↵
  9. 0↵
  10. f↵
  11. n↵
以文本方式显示
  1. a↵
  2. b↵
  3. x↵
  4. c↵
  5. d↵
  6. e↵
  7. g↵
  8. h↵
  9. f↵
  10. Who play first(0: computer; 1: player )?↵
  11. player:↵
  12. computer: d↵
  13. Sorry, you lost.↵
  14. Continue(y/n)?↵
  15. Who play first(0: computer; 1: player )?↵
  16. player:↵
  17. illegal move.↵
  18. player:↵
  19. computer: x↵
  20. Sorry, you lost.↵
  21. Continue(y/n)?↵
  22. Who play first(0: computer; 1: player )?↵
  23. computer: c↵
  24. player:↵
  25. Congratulate, you win.↵
  26. Continue(y/n)?↵
1秒64M0
测试用例 2以文本方式显示
  1. (a,(b,(c,(d),(e)),(f)),(g,(h),(i)),(j,(k,(m),(n),(o),(p,(r))),(x,(y,(z)))))↵
  2. 1↵
  3. j↵
  4. y↵
  5. y↵
  6. 1↵
  7. b↵
  8. y↵
  9. 0↵
  10. k↵
  11. n↵
以文本方式显示
  1. a↵
  2. b↵
  3. c↵
  4. d↵
  5. e↵
  6. f↵
  7. g↵
  8. h↵
  9. i↵
  10. j↵
  11. k↵
  12. m↵
  13. n↵
  14. o↵
  15. p↵
  16. r↵
  17. x↵
  18. y↵
  19. z↵
  20. Who play first(0: computer; 1: player )?↵
  21. player:↵
  22. computer: x↵
  23. player:↵
  24. computer: z↵
  25. Sorry, you lost.↵
  26. Continue(y/n)?↵
  27. Who play first(0: computer; 1: player )?↵
  28. player:↵
  29. computer: f↵
  30. Sorry, you lost.↵
  31. Continue(y/n)?↵
  32. Who play first(0: computer; 1: player )?↵
  33. computer: j↵
  34. player:↵
  35. computer: m↵
  36. Sorry, you lost.↵
  37. Continue(y/n)?↵
1秒64M0
测试用例 3以文本方式显示
  1. (a,(b,(c,(d),(e)),(f)),(g,(h),(i)),(q,(k,(m),(n),(o),(p,(r))),(x,(y,(z)))))↵
  2. 1↵
  3. q↵
  4. x↵
  5. y↵
  6. n↵
以文本方式显示
  1. a↵
  2. b↵
  3. c↵
  4. d↵
  5. e↵
  6. f↵
  7. g↵
  8. h↵
  9. i↵
  10. q↵
  11. k↵
  12. m↵
  13. n↵
  14. o↵
  15. p↵
  16. r↵
  17. x↵
  18. y↵
  19. z↵
  20. Who play first(0: computer; 1: player )?↵
  21. player:↵
  22. computer: x↵
  23. player:↵
  24. illegal move.↵
  25. player:↵
  26. computer: z↵
  27. Sorry, you lost.↵
  28. Continue(y/n)?↵
1秒64M0

 

#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
  
int illegalplay=0,flag=0,i=0,p=0,s=0,m=0,t1,m1=1,r[50],k1[30]={0},k[30]={0},t[30]={0};  
typedef enum{ATOM,LIST} Elemtag;  
typedef struct GLNode  
{  
    Elemtag tag;  
    union  
    {  
        char atom;  
        struct  
        {  
            struct GLNode *hp,*tp;  
        }ptr;  
    }asp;  
}GList;  
  
Elemtag Node(char *s)  
{  
    return  strlen(s)==1 ? (ATOM):(LIST);  
}  
  
char *Gethead(char *s)  
{  
    int i,j,l;  
    char *t;  
    t = (char*) malloc(sizeof(char)*80);  
    l=strlen(s)-1;  
    for(i=1,j=0;i<=l;i++)  
    {  
        if(s[i]=='(') j++;  
        if(s[i]==')') j--;  
        if(j==0)    break;  
    }  
    for(j=0;j<=i-1;j++)  
    {  
        t[j]=s[j+1];  
    }  
    t[j]='\0';  
    return t;  
  
}  
  
char *Gettail(char *h)  
{  
    int i,j,l,w;  
    char *m;  
    m=(char*)malloc(sizeof(char)*80);  
    l=strlen(h)-1;  
    if(h[1]==')')  
    return((strcpy(m,"()"),m));  
    for(i=1,j=0;i<=l;i++)  
    {  
        if(h[i]=='(') j++;  
        if(h[i]==')') j--;  
        if(j==0)break;  
    }  
    if(h[i+1]==')'&&(i+1)==l)  
    {  
        return(strcpy(m,"()"),m);  
    }  
    else  
    {  
        m[0]='(';  
        for(w=1,j=i+2;j<=l;j++)  
        {  
            m[w++]=h[j];  
        }  
        m[w]='\0';  
        return (m);  
    }  
}  
  
GList *CreateGList(GList *L, char *S)  
{  
    if(!strcmp(S,"()"))  
    {  
        L=NULL;  
    }  
    else  
    {  
        L=(GList*)malloc(sizeof(GList));  
        L->tag=Node(S);  
        if(L->tag==ATOM) {L->asp.atom=S[0];}  
        else  
        {  
            L->asp.ptr.hp = CreateGList(L->asp.ptr.hp,Gethead(S));  
            L->asp.ptr.tp = CreateGList(L->asp.ptr.tp,Gettail(S));  
        }  
    }  
    return L;  
}  
  
void print(GList *L)  
{  
    if(L)  
    {  
        if(L->tag==ATOM)  
        {  
            printf("%c\n",L->asp.atom);  
        }  
        else  
        {  
            print(L->asp.ptr.hp);  
            print(L->asp.ptr.tp);  
        }  
    }  
    return ;  
}  
  
void initial(GList *L)  
{     
    GList *v;  
    if(L==NULL||L->tag==ATOM)return;  
    else  
    {  
        if(L->asp.ptr.hp->tag==ATOM)  
        {  
            for(v=L->asp.ptr.tp;v!=NULL;r[m]++,v=v->asp.ptr.tp);  
            m++;  
        }  
            initial(L->asp.ptr.hp);  
            initial(L->asp.ptr.tp);  
    } return;  
}  
  
int depth(GList *p,int t1)  
{  
    GList *q;  
    for(q=p->asp.ptr.tp;q;q=q->asp.ptr.tp)  
    {  
        if(q->asp.ptr.hp->asp.ptr.hp->tag==ATOM)  
        {  
            depth(q->asp.ptr.hp,t1+1);  
            if(q->asp.ptr.hp->asp.ptr.tp==NULL)  
            {  
                k[s++]=t1+1;  
            }  
        }  
    }  
}  
  
GList *playWhichOne(GList *p, char chequer)  
{  
        GList *q=p->asp.ptr.tp;  
        for(;q;q=q->asp.ptr.tp)  
        {  
            if(q->asp.ptr.hp->asp.ptr.hp->tag==ATOM&&q->asp.ptr.hp->asp.ptr.hp->asp.atom==chequer)   
            {  
                return(q->asp.ptr.hp);  
            }  
        }  
        printf("illegal move.\n");  
        illegalplay=1;  
        return p ;  
}  
  
GList *continuePlay(GList *p)  
{  
        int i1,i3=0,j1=0,w=0,flag1,temp,flag=1,kj,ko,max=0;  
        GList *q;  
        while(flag)  
        {  
            for(q=p->asp.ptr.tp;q;q=q->asp.ptr.tp)  
            {  
                ko=0;kj=0;s=0;  
                for(i1=0;i1<30;i1++)  
                {  
                    k[i1]=0;  
                }  
                depth(q->asp.ptr.hp,1);  
                for(i1=0,temp=0;k[i1];i1++)  
                {  
                    if(k[i1]%2==0)  
                    {  
                        ko++;  
                    }  
                    else  
                    {  
                        kj++;  
                    }  
                    if(temp<k[i1])  
                    {  
                        temp=k[i1];  
                    }  
                }  
                k1[i3++]=temp;  
                if(temp==0)  
                {  
                    printf("computer: %c\n",q->asp.ptr.hp->asp.ptr.hp->asp.atom);  
                    printf("Sorry, you lost.\n");  
                    return NULL;  
                }  
                if(ko==0&&kj>0)  
                {  
                    t[w++]=temp;  
                }  
                if(kj==0&&ko>0)  
                {  
                    t[w++]=temp;  
                }  
                if(kj>0&&ko>0)  
                {  
                    t[w++]=-1;  
                }  
            }  
            for(i1=0,temp=0,max=0;t[i1];i1++)  
            {  
                if(t[i1]!=-1)   
                {  
                    if(t[i1]%2!=0&&t[i1]>max)  
                    {  
                        max=t[i1];  
                        temp=i1;  
                    }  
                }  
            }  
            if(temp!=0)  
            {  
                for(j1=0;j1<=temp;j1++)  
                {  
                    p=p->asp.ptr.tp;  
                }  
                printf("computer: %c\n",p->asp.ptr.hp->asp.ptr.hp->asp.atom);  
                return p->asp.ptr.hp;  
            }  
            for(i1=0,temp=0;t[i1];i1++)  
            {  
                if(t[i1]==-1&&k1[i1]>temp)  
                {  
                    temp=i1;  
                    max=t[i1];  
                }  
            }  
            if(temp!=0)  
            {  
                for(j1=0;j1<=temp;j1++)  
                {  
                    p=p->asp.ptr.tp;  
                }  
                printf("computer: %c\n",p->asp.ptr.hp->asp.ptr.hp->asp.atom);  
                return p->asp.ptr.hp;  
            }  
            printf("Congratulate, you win.\n");  
        }  
}  
  
int main()  
{  
    int n1;  
    char s[100],c='y',chequer;  
    GList *L=NULL,*p;  
    gets(s);  
    L=CreateGList(L,s);  
    print(L);  
    initial(L);  
    while(c=='y')  
    {  
        p=L;  
        printf("Who play first(0: computer; 1: player )?\n");  
        scanf("%d",&n1);  
        if(n1==1)  
        {  
                B:  
                printf("player:\n");  
                getchar(); //吸收上一个回车   
                scanf("%c",&chequer);    
                p=playWhichOne(p,chequer); //判断玩家出的是哪一个   
                if(illegalplay==1)  //非法输入   
                {  
                    illegalplay=0;  
                    goto B;  
                }  
                if(p->asp.ptr.tp==NULL)  //我没得下了   
                {  
                    printf("Congratulate, you win.\n");  
                    goto A;  
                }  
        }  
        if(p!=NULL)  
        {  
                p=continuePlay(p);  
                if(p!=NULL) //没下完   
                {  
                        goto B;  
                }  
        }  
    A:  printf("Continue(y/n)?\n"); //继续下吗?   
        for(n1=0;n1<30;n1++)  
        {  
                t[n1]=0;  
        }  
        getchar();  
        scanf("%c",&c);  
    }  
    return 0;  
}  

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值