猜数字

计算机想一个不重复的四位数,人来猜.每次计算机告诉数也对,位置也对的数的个数和数对但位置不对的个数.

例如计算机想的是3194,人猜的是1234,则计算机输出2 1.

人需要在8次之内猜出来.

编这样的程序很简单,可是问题反过来,人想一个数,让计算机在8次之内猜出来. 这个问题就难的多的多了.

我在大三时候想出了下面的办法:

#include<stdio.h>
#include<math.h>
#include<time.h>
int P[5040][5],record[8][2],T,num=5040,A,B,ans[4],key[4],next,guess[8][4],
    judgetype[14][3]={{0,0},{0,1},{0,2},{0,3},{0,4},{1,0},{1,1},{1,2},{1,3},{2,0},{2,1},{2,2},{3,0},{4,0}};

void Initiate()
{
    int i,j,k,v,p=0,digital[10]={0};
    for(i=0;i<=9;i++)
    {
        digital[i]=1;
        for(j=0;j<=9;j++)
        {
            if(digital[j]) continue;
            digital[j]=1;
            for(k=0;k<=9;k++)
            {
                if(digital[k]) continue;
                digital[k]=1;
                for(v=0;v<=9;v++)
                    if(!digital[v])
                    {
                        P[p][0]=1;
                        P[p][1]=i;
                        P[p][2]=j;
                        P[p][3]=k;
                        P[p][4]=v;
                        p++;
                    }
                digital[k]=0;
            }
            digital[j]=0;
        }
        digital[i]=0;
    }
    srand((unsigned)(time(NULL))/2);    
    for(i=0;i<4;i++)
        while(1)
        {
            guess[0][i]=rand()%10;
            for(j=0;j<i;j++)
                if(guess[0][i]==guess[0][j]) break;
            if(j==i) break;
        }
    for(i=0;i<4;i++)
        printf("%d ",guess[0][i]);
    printf("  ");
    scanf("%d%d",&record[0][0],&record[0][1]);
    T=0;
}

void teminate(int b)
{
    if(b) printf("我猜对了!\n");
    else  printf("你是个骗子!!!\n");
        exit(0);
}
getjudge()
{
    int i,j;
    A=0;B=0;
    for(i=0;i<4;i++)
        for(j=0;j<4;j++)
            if(ans[i]==key[j])
            {
                B++;
                break;
            }
    for(i=0;i<4;i++)
        if(ans[i]==key[i])
        {
            A++;
            B--;
        }
}

void exclude()
{
    int i,j;
    for(i=0;i<4;i++)
       ans[i]=guess[T][i];
    for(i=0;i<5040;i++)
    {
        if(P[i][0]==0) continue;
        for(j=0;j<4;j++)
            key[j]=P[i][j+1];
        getjudge();
        if(A!=record[T][0]||B!=record[T][1])
        {
            P[i][0]=0;
            num--;
        }
        else    next=i;
    }
}

void choose()
{
    int i,j,k;
    double H=0,Hmax=0;
    for(i=0;i<5040;i++)
        if(P[i][0]) break;
    next=i;
    for(;i<5040;i++)
    {
        H=0;
        for(k=0;k<4;k++)
            ans[k]=P[i][k+1];
        for(k=0;k<14;k++)
            judgetype[k][2]=0;
        for(j=0;j<5040;j++)
        {
            if(P[j][0]==0) continue;
            for(k=0;k<4;k++)
                key[k]=P[j][k+1];
            getjudge();
            for(k=0;k<14;k++)
                if(A==judgetype[k][0]&&B==judgetype[k][1]) judgetype[k][2]++;
        }
        for(k=0;k<14;k++)
            if(judgetype[k][2]==0) continue;
            else
                H-=judgetype[k][2]*log(1.0*judgetype[k][2]/num);
        if(H>Hmax)
        {
            Hmax=H;
            next=i;
        }
    }
}

void main()
{
    int i;
    Initiate();
    while(1)
    {
        for(i=0;i<14;i++)
            if(record[T][0]==judgetype[i][0]&&record[T][1]==judgetype[i][1])
                break;
        if(i==14) teminate(0);
        if(i==13) teminate(1);
        exclude();
        if(num==0)
            teminate(0);
        else if(num!=1)
            choose();
        T++;
        for(i=0;i<4;i++)
            guess[T][i]=P[next][i+1];
        for(i=0;i<4;i++)
            printf("%d ",P[next][i+1]);
        printf("  ");
        scanf("%d%d",&record[T][0],&record[T][1]);
    }
}
原文地址:https://www.cnblogs.com/saieuler/p/2692337.html