第7回 正誤判定とゲーム化
🏆 第7回 正解判定を入れてゲームを完成させよう
HITとBLOWを表示できるようになりました。
最後に、入力が正解と一致したらループを終了し、正解メッセージを表示します。
1.文字列は == で比較しない
C言語の文字列は、char型の配列です。
次のように書いても、文字列の中身を正しく比較したことにはなりません。
if (answer == input)
{
/* 正解 */
}
配列名は、配列の先頭位置として扱われるためです。
文字列の中身を比較するには、strcmpを使います。
2.ここでC言語: strcmp
strcmpは、2つの文字列を先頭から比較する関数です。
#include <string.h>
strcmp(answer, input)
戻り値は次のようになります。
| 戻り値 | 意味 |
|---|---|
| 0より小さい | 1つ目の文字列が辞書順で前 |
| 0 | 2つの文字列が完全に一致 |
| 0より大きい | 1つ目の文字列が辞書順で後 |
正解かどうかだけを確認する場合は、戻り値が0か調べます。
if (strcmp(answer, input) == 0)
{
printf("正解です。\n");
}
3.ここでC言語: break
breakは、現在実行している繰返しを途中で終了します。
while (1)
{
if (正解した)
{
break;
}
}
breakを実行すると、whileの次の処理へ進みます。
4.入力ループを完成させる
入力エラーがない場合だけ、HITとBLOWを数えます。
結果を表示した後、文字列が完全に一致しているか確認します。
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);
if (strcmp(answer, input) == 0)
{
break;
}
}
}
printf("おめでとう!正解は%sでした。\n", answer);
printf("ゲーム終了!\n");
5.完成プログラム
#define _CRT_SECURE_NO_WARNINGS
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void MakeProblem(char answer[5])
{
char temp[] = "0123456789";
int i;
for (i = 0; i < 100; i++)
{
int index1 = rand() % 10;
int index2 = rand() % 10;
char work;
work = temp[index1];
temp[index1] = temp[index2];
temp[index2] = work;
}
for (i = 0; i < 4; i++)
{
answer[i] = temp[i];
}
answer[4] = '\0';
}
int CheckAnswerError(char input[])
{
int i;
int j;
if (strlen(input) != 4)
{
return 1;
}
for (i = 0; i < 4; i++)
{
if (!isdigit((unsigned char)input[i]))
{
return 2;
}
}
for (i = 0; i < 4; i++)
{
for (j = i + 1; j < 4; j++)
{
if (input[i] == input[j])
{
return 3;
}
}
}
return 0;
}
void ShowInputError(int error)
{
if (error == 1)
{
printf("4桁で入力してください。\n");
}
else if (error == 2)
{
printf("0~9の数字だけを入力してください。\n");
}
else if (error == 3)
{
printf("同じ数字を2回使わないでください。\n");
}
}
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;
}
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;
}
int main(void)
{
char answer[5];
char input[255];
srand((unsigned int)time(NULL));
MakeProblem(answer);
printf("HIT & BLOW GAME\n");
printf("ゲーム開始!\n");
/* デバッグ中は次の行を有効にすると確認しやすい */
/* printf("正解:%s\n", answer); */
while (1)
{
int error;
int hit;
int blow;
printf("\n予想した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);
if (strcmp(answer, input) == 0)
{
break;
}
}
}
printf("\nおめでとう!正解は%sでした。\n", answer);
printf("ゲーム終了!\n");
return 0;
}
6.疑似言語と完成コードを比べる
○ HIT_AND_BLOW
・問題を作る
■ hit ≠ 4
│ ・4桁を入力する
│ ・入力エラーを調べる
│
│ ▲ 入力エラーがある
│ │ ・入力エラーを表示する
│ ├────────────────
│ │ ・HITとBLOWを数える
│ │ ・HITとBLOWを表示する
│ ▼
■
・正解メッセージを表示する
疑似言語で考えた処理が、それぞれ関数やif、whileとしてC言語へ置き換わりました。
7.ゲームを発展させよう
完成後は、次の機能を追加できます。
- 正解までの挑戦回数を表示する
- 過去の入力とHIT・BLOWを履歴として表示する
- 入力エラーごとに詳しい説明を出す
- 桁数を変更できるようにする
- タイトル画面や結果画面を付ける
- 関数を別の
.cファイルへ分ける - ヘッダーファイルを作る
- DxLibなどを使ってグラフィック付きにする
🏁 全7回のまとめ
このゲーム制作では、次のC言語の仕組みを使用しました。
char型の配列による文字列- 終端文字
\0 strlenによる文字数確認randとsrandによる乱数- 配列要素の交換
- 配列を関数へ渡す方法
whileによる入力ループreturnによるエラー番号の返却isdigitによる数字判定- 二重ループによる重複・BLOW判定
strcmpによる文字列比較breakによるループ終了
最初に作った疑似言語の流れを、少しずつC言語へ変換することで、HIT&BLOWゲームが完成しました。


No Comments