2012年11月27日 星期二

基於 itoa() 之 任意 位數 與 基底 的猜數字輔助程式碼 in C/C++

應學弟x1000要求,翻出這段塵封已久的小程式。
修了一下,盡可能寫的好看點,字草勿怪 XD。
使用 Code::Blocks 編譯。附上專案檔與原始碼全文。

下載連結:
https://drive.google.com/uc?id=0B9fCXesD4ByFamdVRWJ3WEliY0E&export=download

原始碼:

#include <iostream>
#include <list>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

char* itos(int number, char* ptr, int radix, int digits)
{
    char temp[0xF];
    char format[0xF];

    itoa(number, temp, radix);
    sprintf(format,"%%0%ds",digits);
    sprintf(ptr, format, temp);

    return ptr;
}

bool isDuplicate(int number, int radix, int digits)
{
    char temp[0xF];
    char format[0xF];
    char encode[0xF];

    itoa(number, temp, radix);
    sprintf(format,"%%0%ds",digits);
    sprintf(encode, format, temp);

    for(char* p=encode; '\0'!=*(p+1); ++p)
        for(char* q=p+1; '\0'!=*q; ++q)
            if(*p==*q)
                return true;

    return false;
}

char* guessHint(char* guess, char* answer, char* hint)
{
    int a,b;
    a=b=0;
    //幾A
    for(char *p=guess, *q=answer; '\0'!=*p && '\0'!=*q; ++p, ++q)
        if(*p==*q)
            ++a;
    //幾B
    for(char* p=guess; '\0'!=*p; ++p)
        for(char* q=answer; '\0'!=*q; ++q)
            if(*p==*q)
                ++b;
    b-=a;

    sprintf(hint, "%dA%dB", a, b);

    return hint;
}

bool isPossible(char* guess, char* answer, char* hint)
{
    char t_hint[0xF];
    guessHint(guess, answer, t_hint);
    //AB大小寫轉換
    hint[1]=toupper(hint[1]);
    hint[3]=toupper(hint[3]);

    return !strcmp(hint,t_hint);
}

int main()
{
    puts("Assistant of Bulls and Cows. by PcGrek@2012.11.27");
    puts("For any radix and digits.[Based on itoa()]");

    int N_RADIX, N_DIGITS;
    //輸入基數(ex:10進制)
    puts("N_RADIX?");
    scanf("%d", &N_RADIX);
    //輸入位數
    puts("N_DIGITS?");
    scanf("%d", &N_DIGITS);

    list<int> database;

    //產生所有可能解
    {
        int number=1;
        for(int digits=0; digits<N_DIGITS; ++digits)
            number*=N_RADIX;

        for(int i=0; i<number; ++i)
            //檢查非重覆才存入
            if(!isDuplicate(i, N_RADIX, N_DIGITS))
                database.push_back(i);
    }

    //輸出剩餘的可能性
    puts("Possible Answers:");
    char answer[0xF];
    for (list<int>::const_iterator ptr=database.begin(); ptr!=database.end(); ++ptr)
        printf("%s\t",itos(*ptr, answer, N_RADIX, N_DIGITS));
    puts("");

    puts("Format: number hint");
    printf("example: %s 0A%dB\n", itos( *(database.begin()), answer, N_RADIX, N_DIGITS), N_DIGITS);
    puts("Guess:");

    char guess[0xF];
    char hint[0xF];

    while(~scanf("%s %s", guess, hint))
    {
        //刪除不可能的解
        for (list<int>::iterator ptr=database.begin(); ptr!=database.end();)
            if(isPossible( guess, itos(*ptr, answer, N_RADIX, N_DIGITS), hint))
                ++ptr;
            else
                ptr=database.erase(ptr);

        //輸出剩餘的可能性
        puts("Possible Answers:");
        for (list<int>::const_iterator ptr=database.begin(); ptr!=database.end(); ++ptr)
            printf("%s\t",itos(*ptr, answer, N_RADIX, N_DIGITS));
        puts("");

        if(database.size()<=1)
            break;
        else
            puts("Guess:");
    }

    if(database.empty())
        puts("Insoluble!");
    else
        printf("Ans=%s\n", itos(*database.begin(), answer, N_RADIX, N_DIGITS) );

    system("pause");
    return 0;
}

參考資料:
[1] 猜數字相關
http://pcgrek.blogspot.tw/2010/08/blog-post.html
[2] 如何過關? 忍者傳說:上忍考試第三部:結界之卷&TP修行:森林之封印。
How to break? Assistant of Ninja Saga Jounin Exam 3/5: The Kekkai & TP Training : The Kekkai(Seal) in the Forest.
http://pcgrek.blogspot.tw/2010/08/facebook-assistant-of-ninja-saga-jounin.html

沒有留言: