回 帖 发 新 帖 刷新版面

主题:[原创]就解猜数字问题(谁都会!)完美正式版

/************************************************************************
文件名:    解猜数字题
文件描述:  就解猜数字题
创建人:    陈泽丹,   2006年5月3日, (好惨,五一长假还忍不住心痒要编下程序,呵)
版本号:    1.0
修改次数:
************************************************************************/
/*-----------------------------------------------------------------------
问题描述:
随机给出一个数位上的数字不重复的四位数,让你猜,计算机每次给你提示这样的格
式的语句:xAyB (0<=x<=4, 0<=y<=4)
其中A表示数字正确位置也正确的,B表示数字正确位置不正确。
例如说: 1A2B  (表示1个数字正确位置也正确的,另有两个数字正确位置不正确)
现要求你编程尽可能在7次机会内猜出这个四位数。

解题思路:
把它分两步进行,1,先求这个四位数。2,再求这个四位数各位的
位置。另外,请注意,这两步是互相独立的子问题,故是可以同时进行解决的.

(好累,睡觉先了. 这么热心,要是还不能成精华贴, 那就太失人心喽,呵呵:)  )
------------------------------------------------------------------------*/
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
程序使用说明:
先对程序输入你第一次对游戏猜的那四个数.
再把游戏第一次的提示结果(A+B的和)告诉程序.
之后按程序说的办.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#include <iostream.h>
#include <iomanip.h>

const int times=15;                            //总的次数(可变动数值范围)
const int Max=10;                              //可选的数字
const int len=4;                               //数字的选择量
const int tot=210;                             //组合情况的总数
const int position_cord=24;                    //每组数字的排列情况总数
const int position_Max=4;                      //每次待排数字总量
const int position_len=4;                      //每次排的数字量
int number[1][Max];                            //组合设为二维数组以便日后改进
int cord[len];                                 //记录求组合时的中间变量
int total[tot][len];                           //用于记录组合数
int maybe[tot];                                //用于记录可能是答案的组合
int sum[tot];                                  //用于记录所有组合的结果
int p=0;                                       //total的一维指针
int pmaybe=0;                                  //maybe的一维指针
int count=0;                                   //对任意组合的数量进行统计
int guess[times][len];                         //记录每次猜的数字
int pguess=0;                                  //guess的一维指针
int A[times];                                  //记录每次游戏的A指示
int position[position_Max];                    //待排变量
int position_case[position_cord][position_len];//待排情况
int pcase=0;                                   //情况指针

void Init()
{
    p=0;
    pmaybe=0;
    count=0;
    pguess=0;
    pcase=0;
}

void Init_guess()
{
    for (int i=0; i<times; i++)
    {
        for (int j=0; j<len; j++)
            guess[i][j]=-1;
        A[i]=-1;
    }
}

void Init_maybe()
{
    for (int i=0; i<tot; i++)
        maybe[i]=-1;
    pmaybe=0;
}

void Init_number()
{
    for (int i=0; i<Max; i++)
        number[0][i]=0;
}

void set(int m, int n)
{
    int i;
    if (m == len )
    {
        for (i=0; i<len; i++)
            total[p][i]=cord[i];
        count++;
        p++;
    }
    else if ( n < Max)
    {
        for (i=0; i<2; i++)
        {
            if (i==0) { cord[m]=n; set(m+1,n+1); }
            else set(m,n+1);
        }
    }
}

void order(int n)
{
    int i, temp;
    if (n == position_len)
    {
        for (i=0; i<position_len ;i++)
            position_case[pcase][i]=position[i];
        pcase++;
    }
    else
    {
        for (i=n; i<position_Max; i++)
        {
            temp=position[n]; position[n]=position[i]; position[i]=temp;
            order(n+1);
            temp=position[n]; position[n]=position[i]; position[i]=temp;
        }
    }
}

void condition(int sum, int pnum)
{
    int sumk;
    int temp;
    Init_maybe();
    for (int i=0; i<tot; i++)
    {
        sumk=0;
        for (int j=0; j<len; j++)
        {
            temp=total[i][j];
            sumk+=number[pnum][temp];
        }
        if (sumk == sum) { maybe[pmaybe]=i; pmaybe++; }
    }
}

int answer(int sum, int pnum)
{
    condition(sum, pnum);
    pmaybe=0;
    int i=0,j=0;
    int temp;
    while(1)
    {
        if (maybe[pmaybe] == -1) break;
        i=maybe[pmaybe];
        for (j=0; j<len; j++)
        {
            temp=total[i][j];
            cout<<temp<<" ";
        }
        cout<<endl;
        pmaybe++;
    }
    if (pmaybe >= 1) return 1;
    return 0;
}

void sum_fun(int pnum)
{
    int sumk, temp;
    for (int i=0; i<tot; i++)
    {
        sumk=0;
        for (int j=0; j<len; j++)
        {
            temp=total[i][j];
            sumk+=number[pnum][temp];
        }
        sum[i]=sumk;
    }
}

void set_number(int(* a)[len], int line)
{
    int i, temp;
    for (i=0; i<Max; i++)
        number[0][i]=number[0][i]*10;
    for (i=0; i<len; i++)
    {
        temp=a[line][i];
        if (pguess < times ) guess[pguess][i]=a[line][i];
        number[0][temp]++;
    }
    pguess++;
}

int position_order(int n, int pguess)
{
    if (pguess>=0)
    {
        int c=0;
        for (int i=0; i<len; i++)
            if ( position_case[n][i] == guess[pguess][i]) c++;
        if (c == 4) return 0; 
        if (c > A[pguess]) return 0;
        return position_order(n,pguess-1);
    }
    else return 1;
}

int set_maybe(int sum)
{
    condition(sum, 0);
    int i=0, right=0;
    int k=0;
    for (pmaybe=0; pmaybe<tot; pmaybe++)
    {
        i=maybe[pmaybe];
        for (int po=0; po<position_len; po++)
            position[po]=total[i][po];
        pcase=0;
        order(0);
        for (right=0; right<position_cord; right++)
            if ( position_order(right,pguess-1) ) {  k=1; break; }
        if ( k==1 ) break;
    }
    if (pmaybe == tot) { cout<<"该题目无解"<<endl; return 0; }
    set_number(position_case, right);
    cout<<"请向游戏输入:";
    for (int kk=0; kk<len; kk++)
        cout<<position_case[right][kk]<<" ";
    cout<<endl;
    return 1;
}

void first()
{
    int a[1][len], limit=0;
    while(limit<len)
    {
        cout<<"请输入你第一次猜时的第"<<limit+1<<"个数字:";
        cin>>a[0][limit];
        if (a[0][limit] >=0 && a[0][limit]<Max) limit++;
        else cout<<"输入数字不在范围内,请重输!"<<endl;
    }
    set_number(a, 0);
}


int fun()
{
    Init();
    Init_guess();
    Init_number();
    Init_maybe();
    first();
    int b=0;
    int result=0;
    set(0,0);
    cout<<"总组合情况: "<<count<<endl;

    cout<<"请输入游戏的第一次时A的提示情况:";
    cin>>A[pguess-1];
    if (A[pguess-1] == 4) 
    { 
        cout<<"\n谢谢使用本程序!"<<endl;
        return 1;
    }
    cout<<"请输入游戏的第一次时B的提示情况:";
    cin>>result;
    result=result+A[pguess-1];
    b=b*10+result;
    cout<<"第一次提示情况下可能的组合:"<<endl;
    for (int kk=2; kk<=times; kk++)
    {
        if (!answer(b,0) ) { cout<<"该题目无解"<<endl; break; }
        cout<<endl;
        set_maybe(b);

        cout<<"请输入游戏的第"<<kk<<"次的A的提示情况:";
        cin>>A[pguess-1];
        if (A[pguess-1] == 4) break;

        cout<<"请输入游戏的第"<<kk<<"次的B的提示情况:";
        cin>>result;
        result=result+A[pguess-1];
        b=b*10+result;
        cout<<"第"<<kk<<"次提示情况下可能的组合:"<<endl;
    }
    cout<<"\n谢谢使用本程序!"<<endl;
    return 1;
}

void main()
{
    cout<<"程序名:  解猜数字游戏."<<endl;
    cout<<"程序描述:解猜数字游戏(模拟人的逻辑解题)"<<endl;
    cout<<"创建人:  陈泽丹.   (完成时间:2006年5月3号凌晨4点54分)"<<endl;
    cout<<"QQ:       82314038"<<endl;
    cout<<"\n大家可以上这个网址:http://home.kele8.com/flashgame/showgame.asp?id=10139"<<endl;
    cout<<"测试程序运行效果。程序游戏偶就不写了,要程序游戏是偶写,解程序的也是偶写,难免有投机"<<endl;
    cout<<"之嫌, 呵呵."<<endl;
    cout<<"\n题外话:  欢迎组队开发软件! ( 好了,快天光了,呵呵,该是偶睡觉的时侯了:) 各位早安 )"<<endl;
    cout<<"---------------------------------------------------------------------------------------------------"<<endl;
    char a;
    do
    {
        fun();
        cout<<"若输入#退出本程序:";
        cin>>a;
        cout<<endl<<endl;
    }while (a != '#');
}

回复列表 (共37个回复)

沙发

/*=======================================================================
由于我对问题的资料有限,所以不知道它是否可以对一个数字重复猜的,如可以,还可
用以下方法.^-^

程序结果表明,5次时猜出在10个数字里猜出指定的4个数字的成功率是百分之百!

接下来就是测试这四个数字位置的问题了,呵呵,难得五一,出去玩会后再来完善程序好了.
呵呵.
=========================================================================*/
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
程序用法:

第一次: 猜1220
第二次: 猜3440
第三次: 猜5660
第四次: 猜7880
第五次: 猜9000
第六次: 任意
第七次: 任意


然后把从第1次到第N次各次A+B的和的结果,依次从左到右组成一个N位数(注意如大于10的数且首位为0,则首位的0不用组进去,你组进去,我担心输入时电脑会把它当八制进了.)
然后把这个N位数输入程序.
(N的大小由你定,N表示第N次机会, 1<=N<=7)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include <iostream.h>
#include <iomanip.h>

const int times=7;        //总的次数
const int Max=10;        //可选的数字
const int len=4;        //数字的选择量
const int tot=210;        //组合情况的总数
int number[times][Max]=
{
    1,        2,        0,        0,        0,        0,        0,        0,        0,        1,
    10,        20,        1,        2,        0,        0,        0,        0,        0,        1,
    100,    200,    10,        20,        1,        2,        0,        0,        0,        1,
    1000,    2000,    100,    200,    10,        20,        0,        0,        0,        1,
    10000,    20000,    1000,    2000,    100,    200,    10,        20,        1,        2,
    100000,    200000,    10000,    20000,    1000,    2000,    100,    200,    10,        20,
    1000000,2000000,100000,    200000,    10000,    20000,    1000,    2000,    100,    200
};                        //1到7次各数的出现情况
int cord[len];            //记录求组合时的中间变量
int total[tot][len];    //用于记录组合数
int maybe[tot];            //用于记录可能是答案的组合
int sum[tot];            //用于记录所有组合的结果
int sort[tot];            //用于对可能组合分类,并记录在sort里
int p=0;                //total的一维指针
int pmaybe=0;            //maybe的一维指针
int count=0;            //对任意组合的数量进行统计

void Init_maybe()
{
    for (int i=0; i<tot; i++)
        maybe[i]=-1;
    pmaybe=0;
}
void Init_sum_sort()
{
    for (int i=0; i<tot; i++)
        sum[i]=sort[i]=-1;
}

void set(int m, int n)
{   
    int i;
    if (m == len )
    {
        for (i=0; i<len; i++)
        {
            total[p][i]=cord[i];
        }
        count++;
        p++;
    }
    else if ( n < Max)
    {
        for (i=0; i<2; i++)
        {
            if (i==0) { cord[m]=n; set(m+1,n+1); }
            else set(m,n+1);
        }
    }
}

void output()
{   
    for (int i=0; i<tot; i++)
    {
        for (int j=0; j<4; j++)
            cout<<total[i][j];
        cout<<endl;
    }
}

void condition(int sum, int pnum)
{   
    int sumk;
    int temp;
    for (int i=0; i<tot; i++)
    {
        sumk=0;
        for (int j=0; j<len; j++)
        {
            temp=total[i][j];
            sumk+=number[pnum][temp];
        }
        if (sumk == sum) { maybe[pmaybe]=i; pmaybe++; }
    }
}

void answer(int sum, int pnum)
{   
    Init_maybe();
    condition(sum, pnum);
    pmaybe=0;
    int i=0;
    int j=0;
    int temp;
    while(1)
    {
        if (maybe[pmaybe] == -1) break;
        i=maybe[pmaybe];
        for (j=0; j<len; j++)
        {
            temp=total[i][j];
            cout<<temp+1<<"("<<number[pnum][temp]<<") ";
        }
        cout<<endl;
        pmaybe++;
    }
}

void sum_fun(int pnum)
{  
    int sumk, temp;
    for (int i=0; i<tot; i++)
    {
        sumk=0;
        for (int j=0; j<len; j++)
        {
            temp=total[i][j];
            sumk+=number[pnum][temp];
        }
        sum[i]=sumk;
    }
}

板凳


void fun()
{
    int i;
    cout<<"请输入进行查询的次数:";
    cin>>i;
    while(i)
    {
        int a, b;
        do
        {
            cout<<"请输入是进行到那一次(至少是第1次,至多是第7次):";
            cin>>b;
        }while(b>7 || b<1);
        cout<<"请输入提示的结果:";
        cin>>a;
        answer(a,b-1);
        i--;
    }
}
void main()
{
    count=0;
    set(0,0);
    cout<<"总组合情况: "<<count<<endl;
//    output();
    fun();
}

3 楼

我是初学者,先占楼支持楼主

4 楼

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <process.h>

#define N 10
#define SIZE 4

int main()
{
    int a, b, c, d, rad, cnt, i, j, A = 0, B = 0;
    char string1[SIZE], string2[SIZE];
    char choise;
    clrscr();
    while(1){
        srand(time(NULL));
        cnt = 0;
        do
            a = rand() % 10;
        while(a == 0);
        do
            b = rand() % 10;
        while(b == a);
        do
            c = rand() % 10;
        while(c == a || c == b);
        do
            d = rand() %10;
        while(d == a || d == b || d == c);
        rad = 1000 * a + 100 * b + 10 * c + d;
        itoa(rad, string1, 10);
        while(cnt < N){
            printf("please input the num: ");
            scanf("%s", string2);
            getchar();
            A = 0;
            B = 0;
            for(i = 0; i < SIZE; ++ i){
                if(string1[i] == string2[i])
                    ++ A;
                for(j = 0; j < 4; ++ j)
                    if(string1[i] == string2[j])
                        ++ B;
                if(A == 4){
                    printf("you win the game!");
                    break;
                }
            }
            B = B - A;
            printf("%s\t%c%d%c%d\n", string2, 'A', A, 'B', B);
            ++ cnt;
        }
        printf("Sorry! you have lost!, please try again!");
        printf("\n");
        printf("Play again!  A");
        printf("Quit! Q");
        choise = getchar();
        if(choise == 'Q' || choise == 'q')
            exit(1);
        if(choise != 'A' && choise != 'a'){
            printf("Error!");
            exit(1);
        }
    }

}

我用c语言写的,不过我对界面不满意,我是见到别人电子词典上有这个游戏,才写的这个,如果那位朋友有意可以弄个界面!



5 楼

楼上的程序的游戏程序是正确的,不过似乎有一点点美中不足,
考虑这样的情况:
计算机给出的随机数是: 5678
然后人们猜的是: 5555
那么楼上的程序就变成 1A3B.
但光看数字相同的话,我觉得应该就是一个而已...
问题的资料没谈这点,呵呵,所以也不好评价.
首位应该可以为0;
:)

6 楼

谢谢,指出错误!
一定改正!

7 楼

如果首位为0的话还算不算数字,
我也是看到别人的电子词典上的小游戏写的,个人觉得首位还是不能为0!

8 楼

今天打完饭回来时,突然想到一个问题!4楼的出游戏的算法应该不行的...虽然问题没说到重复时如何算的问题,但细想一下发现根本就不用说.

还是考虑那种情况:
计算机给出的随机数是: 5678
然后人们猜的是: 5555
那么4楼上的程序就变成 1A3B.
可是当人们猜的是:5867时,
4楼上的程序的提示就依然是:1A3B
有岐义.
在该前提下,同理还将存在其它岐义,如:6666,7777,8888...6657, 7788,之类的,
岐义将有不少...

所以如有重复应该就是只能算一个的.

9 楼

楼主抱歉:
    上次回帖的时候就应该告诉你的,我看到的的游戏是:10次之内如果没有猜中,就算失败,所以我认为四位数字是不能重复出现的,也就是说----10个数字中,每个数字仅能用一次.因为如果允许重复出现,则10次猜中的几率是很小的,是不符和的规则的.
    
我不知道楼主的游戏规则是什么?

请楼主暂时不要结贴,我这两天一直在上辅导班,在给我两天时间我把我的代码再整理一下,让楼主看看.

然后咱们再交流!

共勉!

10 楼

猜的时侯不能猜重复的,如出现可以猜重复的,那也只能算一次才对.不然游戏的提示会有岐义.
和的规则为不可猜重复的解答原因,这点我觉得不是很精确,因为也许有人能想出另解的.我一直相信这世上一定有很多没露面的高手...就像第一个写出汉诺塔的家伙,呵...

没什么啦,不急的.
正事要紧,有时间不妨才来解决这些课外题啦.
我不会结贴的.^-^
事实上,我最近也较忙,正做赶做一个flash.

我来回复

您尚未登录,请登录后再回复。点此登录或注册