第一版 第 8 章 :  程式碼  13




解答 :
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <ctime>

using namespace std ;


const int DIGIT_NO = 4 ;
const int MAX_NO   = 10000 ;


// 字串轉整數
int  atoi( const string& a ) {
    int  no = 0 ;
    for ( int i = 0 ; i < a.size() ; ++i )  no = no * 10 + ( a[i] - '0' ) ;
    return no ;
}

// 整數轉字串
string  itoa( int a ) {

    string  no(DIGIT_NO,'0') ;

    int r ;
    for ( int i = 1 ; i <= DIGIT_NO ; i++ ) {
        r = a % 10 ;
        no[DIGIT_NO-i] = r + '0' ;
        a = a / 10 ;
    }

    return  no  ;
    
}


// 檢查字串數字是否為有效數
bool  valid_number( string no ) {
    int i , j ;
    for ( i = 0 ; i < DIGIT_NO ; ++i ) {
        for ( j = i+1 ; j < DIGIT_NO ; ++j ) {
            if ( no[i] == no[j] ) return false ;
        }
    }
    return true ;
}


// 檢查整數是否為有效數
bool  valid_number( int no ) {    return  valid_number(itoa(no)) ; }


// 產生一有效整數    
int  create_number() {
    int no ;
    while( 1 ) {
        no = rand() % MAX_NO ;
        if ( valid_number(no) ) return no ;
    } 
}


// 產生一靠近 n 的有效字串整數
string  generate_next_number( string n ) {

    int no ;

    if ( n.size() ) {

        no = atoi(n) ;
        do {
            ++no ;
            if ( no > 9876 ) no = 123 ;
        } while ( ! valid_number(no) ) ;

    } else {

        no = create_number() ;

    }

    return  itoa(no) ;

}

// 記錄結果 r (xAyB) 於 a[i] 與 b[i]     
void  record_answer( string r , int a[] , int b[] , int i ) {

    int k ;
    for ( k = 1 ; k < 4 ; ++k ) {
        if ( r[k] == 'a' || r[k] == 'A' ) break ;
    }

    a[i] = ( k == 4 ? 0 :  r[--k] - '0' ) ;


    for ( k = 1 ; k < 4 ; ++k ) {
        if ( r[k] == 'b' || r[k] == 'B' ) break ;
    }

    b[i] = ( k == 4 ? 0 :  r[--k] - '0' ) ;
    
}

// 比較兩字串數字 no1 與 no2 為幾個 na 幾個 nb
void  string_number_comparison( string no1 , string no2 , int& na , int& nb ) {
    int i , j ;
    na = 0 ;
    for ( i = 0 ; i < DIGIT_NO ; ++i ) {
        if ( no1[i] == no2[i] ) ++na ;
    }

    nb = 0 ;
    for ( i = 0 ; i < DIGIT_NO ; ++i ) {
        for ( j = 0 ; j < DIGIT_NO ; ++j ) {
            if ( i == j ) continue ;
            if ( no1[i] == no2[j] ) {
                ++nb ;
                break ;
            }
        }
    }
}

// 檢查字串數字 no 是否為滿足所有猜過條件的數字
bool  good_guess( string no , string guess_number[] , int a[] , int b[] , int n ) {
    int  i , na , nb ;
    for ( i = 0 ; i <= n ; ++i ) {
        string_number_comparison(no,guess_number[i],na,nb) ;
        if ( na != a[i] || nb != b[i] ) return false ;
    }
    return true ;
}

        

int main() {

    const int MAX = 20 ;
    
    string  no , result ;
    string  guess_number[MAX] ;
    int     i , j , a[MAX] , b[MAX] ;

    srand( static_cast<unsigned int>(time(NULL)) ) ;

    string  initial_number = generate_next_number(no) ;

    no = initial_number ;
    
    i = 0 ;
    
    do {

        guess_number[i] = no ;
        cout << i+1 << "> " << no << "\n" << ">> "  ;
        cin >> result ;
        record_answer(result,a,b,i) ;

        if ( a[i] == 4 ) break ;

        do {
            no = generate_next_number(no) ;
            if ( no == initial_number ) {
                cout << "\n> no such number exists !" << endl ;
                return 1 ;
            }
        } while ( ! good_guess(no,guess_number,a,b,i) ) ;

        cout << endl ;

        ++i ;
        
    } while ( 1 ) ;

    
    return 0 ;
    
}