Skip to main content

第6回 HITとBLOWカウント

🎯 第6回 HITとBLOWを数えよう

問題作成と入力エラーチェックまで完成しました。

今回は、正解と入力を比較して、HITとBLOWを数えます。

正解:1 2 3 4
入力:1 3 2 5
結果:1 HIT 2 BLOW

1.HITを数える

HITは、数字と位置の両方が一致している状態です。

answer[0] と input[0]
answer[1] と input[1]
answer[2] と input[2]
answer[3] と input[3]

同じ添え字同士を比較すればよいため、1本のfor文で数えられます。

int CountHit(char answer[], char input[])
{
    int count = 0;
    int i;

    for (i = 0; i < 4; i++)
    {
        if (answer[i] == input[i])
        {
            count++;
        }
    }

    return count;
}

count++の意味

count++;

これは、countへ1を加える処理です。

count = count + 1;

と同じ意味です。


2.BLOWを数える

BLOWは、数字は正解に含まれているが、位置が違う状態です。

入力の1文字について、正解の4文字全部を調べる必要があります。

そのため、二重ループを使います。

input[0] と answer[0]~answer[3]
input[1] と answer[0]~answer[3]
input[2] と answer[0]~answer[3]
input[3] と answer[0]~answer[3]

3.HITをBLOWに数えない

数字が同じだけでは、HITまでBLOWとして数えてしまいます。

そこで、次の2条件を確認します。

  1. 数字が同じ
  2. 添え字が違う
if (input[i] == answer[j] && i != j)
{
    count++;
}

&&は、「両方の条件が成立する」という意味です。


4.BLOWを数える関数

int CountBlow(char answer[], char input[])
{
    int count = 0;
    int i;
    int j;

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            if (input[i] == answer[j] && i != j)
            {
                count++;
            }
        }
    }

    return count;
}

今回のゲームでは、正解にも入力にも数字の重複がありません。 (そのため前の回で頑張ったのだよ!) そのため、同じ数字が何度も数えられることはありません。

💡 入力エラーチェックを先に行ったことで、HIT・BLOW関数の中では「4文字で、数字だけで、重複なし」と考えて処理できます。


5.入力ループへ判定を追加する

while (1)
{
    int error;
    int hit;
    int blow;

    printf("予想した4桁の数字を入力:");
    scanf("%254s", input);

    error = CheckAnswerError(input);

    if (error != 0)
    {
        ShowInputError(error);
    }
    else
    {
        hit = CountHit(answer, input);
        blow = CountBlow(answer, input);

        printf("HIT :%d\n", hit);
        printf("BLOW:%d\n", blow);
    }
}

実行例は次のようになります。

正解:1234
予想した4桁の数字を入力:1325
HIT :1
BLOW:2

6.手作業で確認してから実行する

プログラムを実行する前に、次の結果を自分で考えてください。

正解を1234に固定して確認します。

入力 HIT BLOW
1234 4 0
4321 0 4
1256 2 0
1325 1 2
5678 0 0

デバッグ中は、MakeProblemを呼ばずに正解を固定しても構いません。

char answer[5] = "1234";

乱数の問題では毎回正解が変わるため、判定処理を確認しにくいからです。


7.疑似言語との対応

・hit ← HIT数を数える(answer, input)
・blow ← BLOW数を数える(answer, input)
・hitとblowを表示する

C言語では次の部分です。

hit = CountHit(answer, input);
blow = CountBlow(answer, input);

printf("HIT :%d\n", hit);
printf("BLOW:%d\n", blow);

🏁 今回のまとめ

  • HITは同じ添え字同士を比較する
  • BLOWは入力と正解の全組合せを比較する
  • BLOWではi != jを確認してHITを除外する
  • &&は2つの条件が両方成立する場合
  • カウントは0から始め、一致するたびにcount++する
  • エラーチェックを先に行うと、判定関数を単純にできる

次回は、正解したときに入力ループを抜け、ゲームを完成させます。