iT邦幫忙

2022 iThome 鐵人賽

DAY 9
0
自我挑戰組

C++30日挑戰之旅系列 第 9

DAY9 用C++來完成猜數字遊戲(下)

  • 分享至 

  • xImage
  •  

題目:

選擇一個四位數字讓對方猜謎,四個位數的數字必須不同,例如: 0941
若對方猜的數字,數字正確位置不對為1B、如果數字跟位置都正確1A,例如5904: 1A 2B,且當4A遊戲結束


解法:

#include <iostream>
#include <ctime>
#include<iostream>
using namespace std;

bool checkNumber(int x);
int generateNumber();
bool cmpNumber(int x, int y);

int main()
{
    int x, s, a;
    s=time(0);//設置seed值
    srand(s);
    x = generateNumber();//目標數字
    c:
    cin >> a;//猜測數字
    switch(a)
    {
        case 0:
        {
            cout << x << endl;
            return 0;
            break;
        }
        default:
        {
            if(cmpNumber(a,x)==true)
                return 0;
            else
                goto c;
            break;
        }
    }
}

bool checkNumber(int x)
{
    int d1, d2, d3, d4;
    d1 = x / 1000;
    d2 = (x / 100) % 10;
    d3 = (x / 10) % 10;
    d4 = x % 10;
    if(x<=9876&&x>=123)
    {
        if((d1!=d2)&&(d2!=d3)&&(d3!=d4)&&(d4!=d1)&&(d1!=d3)&&(d2!=d4))
            return (true);
        else
            return (false);
    }

    else
        return (false);
}

int generateNumber()
{   
    int num;
    a:
    num = rand() % 9754 + 123;
    if(checkNumber(num)==false)
        goto a;
    else
        return num;
}

bool cmpNumber(int x, int y)
{
    int g1, g2, g3, g4;
    g1 = y / 1000;
    g2 = (y / 100) % 10;
    g3 = (y / 10) % 10;
    g4 = y % 10;

    int d1, d2, d3, d4;
    d1 = x / 1000;
    d2 = (x / 100) % 10;
    d3 = (x / 10) % 10;
    d4 = x % 10;

    int i, j;
    i = 0;
    j = 0;
    if(g1==d2||g1==d3||g1==d4)
        j++;
    else if(g1==d1)
        i++;
    
    if(g2==d1||g2==d3||g2==d4)
        j++;
    else if(g2==d2)
        i++;

    if(g3==d1||g3==d2||g3==d4)
        j++;
    else if(g3==d3)
        i++;
    
    if(g4==d1||g4==d2||g4==d3)
        j++;
    else if(g4==d4)
        i++;

    cout << i << "A" << j << "B" << endl;
    if(i==4)
        return (true);
    else
        return (false);
}

解釋與詳細介紹

第二部分:主功能解析-解答數字生成generateNumber()

我們接續昨天的部分,進到了第二部分,主功能解析!首先介紹generateNumber()解答數字生成的部分:

int generateNumber()
{   
    int num;
    a:
    num = rand() % 9754 + 123;
    if(checkNumber(num)==false)
        goto a;
    else
        return num;
}

我們希望以random的num作為我們這次猜測的"正解",所以需要先檢查其是否符合checkNumber()函式(介於0123到9876且沒有數字重複)。若是符合的話就會使這個num成為正解,否則就會持續進行直到產生一個符合這個條件的num。而這個函式的屬性"int"就是代表回傳的num屬性(整數)。

第三部分:主功能解析-位數檢查checknum()

再來進行到checknum()位數檢查的部分:

bool checkNumber(int x)
{
    int d1, d2, d3, d4;//四位數
    d1 = x / 1000;//最高位(最左項)
    d2 = (x / 100) % 10;//左數來第二項
    d3 = (x / 10) % 10;//左數來第三項
    d4 = x % 10;//最尾項
    if(x<=9876&&x>=123)//代表值符合0123~9876
    {
        if((d1!=d2)&&(d2!=d3)&&(d3!=d4)&&(d4!=d1)&&(d1!=d3)&&(d2!=d4))
            return (true);//每位皆不相同
        else
            return (false);
    }

    else
        return (false);
}

checknum()屬於一個boolean值,也就是呼叫這個函式時他會回傳"true"(1)或"false"(0)的答案。前敘的d1, d2, d3, d4分別代表位數,而d1~d4在"賦值"時便是以"千"、"百"、"十"、"個"的方式告訴程式,也就是運用除法和餘數的方式。再判斷當其符合0123~9876的if迴圈內"每位數是否皆相異"的條件。若是符合,checknum()便可以回傳true,否則會回傳false(代表有位數重複出現或是範圍錯誤,不在0123~9876間)

第四部分:主功能解析-猜測數字與正解比對cmpNumber()

下一個則是cmpNumber(),猜測數字與正解比對的函式:

bool cmpNumber(int x, int y)
{
    int g1, g2, g3, g4;//使用者猜測值的四個位數
    g1 = y / 1000;
    g2 = (y / 100) % 10;
    g3 = (y / 10) % 10;
    g4 = y % 10;

    int d1, d2, d3, d4;//答案的四個位數
    d1 = x / 1000;
    d2 = (x / 100) % 10;
    d3 = (x / 10) % 10;
    d4 = x % 10;

    int i, j;
    i = 0;//i代表"幾A"(位子和值都對)
    j = 0;//j代表"幾B"(值對位子不對)
    if(g1==d2||g1==d3||g1==d4)//出現B的情況
        j++;
    else if(g1==d1)//出現A的情況
        i++;
    
    if(g2==d1||g2==d3||g2==d4)
        j++;
    else if(g2==d2)
        i++;

    if(g3==d1||g3==d2||g3==d4)
        j++;
    else if(g3==d3)
        i++;
    
    if(g4==d1||g4==d2||g4==d3)
        j++;
    else if(g4==d4)
        i++;

    cout << i << "A" << j << "B" << endl;//輸出幾"A"幾"B"
    if(i==4)
        return (true);//對的情況
    else
        return (false);//錯的情況,繼續猜
}

cmpNumber()函式同樣是boolean屬性,代表他也是回傳對錯值。在這個函式中我們分別先令g1, g2, g3, g4為使用者當次猜的四個數字、d1, d2, d3, d4為正解的四個數字,並定義i代表"幾A"(位子和值都對)、j代表"幾B"(值對位子不對),並用if/else的迴圈將"每個位數的所有A或B的可能"條件列出,並對應到i、j的遞增,輸出"幾A幾B",最後再配合這個函式的boolean值,true代表四個數字皆正確且位置也正確、false則是沒有達到前述狀況的其他情形。這樣在呼叫這個函式時就可以達到比較並輸出結果的效果了。

第五部分:主功能解析-主函式結合main()

最後我們再來看主程式中是如何結合這些函式加以應用的:

int main()
{
    int x, s, a;
    s=time(0);//seed
    srand(s);
    x = generateNumber();//目標數字
    c://猜測部分
    cin >> a;//猜測數字
    switch(a)
    {
        case 0:
        {
            cout << x << endl;
            return 0;
            break;
        }
        default:
        {
            if(cmpNumber(a,x)==true)
                return 0;
            else
                goto c;//回到猜測部分
            break;
        }
    }
}

可以看到一開始我們先讓s以time(0)為seed值產生一個變數值,並將猜測的部分(也就是cin>>a)作為程式段c:(方便之後直接跳回的程式記號),並用generateNumber()產生目標正解。在猜測的部分使用者會先輸入一值(以"a"變數作為代表),我們定義了一個switc()函式去將猜測值分為兩個結果,一個便是case 0,也就是猜對(四位數值與位置皆對)後會執行的區段;與default:部分goto c(重複猜測的部分)。這樣就可以完成一個簡單的

第六部分:成果展示

https://ithelp.ithome.com.tw/upload/images/20220910/20151593bhNKZy5oji.png

這樣就可以用程式完成一個幾A幾B的猜數字遊戲了~也可以自己延伸加入猜測的次數限制機制來增加遊戲刺激性o(*≧▽≦)ツ是不是很好玩呢!那我們明天再見囉~


上一篇
DAY8 用C++來完成猜數字遊戲(上)
下一篇
DAY10 利用陣列(Array)輸出亂數們的統計數值
系列文
C++30日挑戰之旅43
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言