数当てゲーム

# 数当てゲーム
最近C言語の学習を始めました。
「ゲーム開発で学ぶC言語入門」という本でC言語を学習しています。
その中でゲームとして２番目に作成するのが数当てゲームです(この本の中で一番初めに作ったのはクイズゲームでした)。
今回は書籍にあったコードを参考にして、**知り合いや友人など周りの方に遊んでもらえる**ように自分なりに書いてみたものです。
↓のリンクをクリックするとそのままソースファイルと実行ファイル(exe)をダウンロードできます。よかったら遊んでください。

※追記：ちなみに今回はよく考えず拡張子をVisualStudioのデフォルトの.cppにしてしまいましたが、調べてみるとCとC++ではコンパイル方法が違うため拡張子はちゃんと.cにすべきということがわかりました。今回は.cppのままいきます。

https://raw.githubusercontent.com/zumomo-zzZ/number-guessing/master/number-guessing.cpp

https://raw.githubusercontent.com/zumomo-zzZ/number-guessing/master/x64/Debug/number-guessing.exe


### 工夫したポイント
・かんたんモード(正解と近い数字が入力された際にヒントを出す)、ふつうモード(通常のよく知られている数当てゲーム)を用意し、**プレイヤーが難易度を選べるようにした**。さらに、提示されているモードを選ばなかった際に**隠しモード**が作動するようにした。
・プレイヤーは基本的に整数の入力しか求められないが、文字やスペースや改行コードが入力された際も適切に動作するようにした。

### 今後やりたい機能追加
・途中でゲームをやめたくなった際に中断できるコマンドを用意したい。
・~~最後に「もう一度プレイしますか？」とプレイヤーに質問して、画面を閉じないまま繰り返しプレイできるようにしたい。~~ 25/1/18 繰り返し遊べるように機能追加しました！
・整数を入力すべきタイミングで文字を入力した際に、バグのような演出をしたい。scanf("%d", &num);に文字を入力したときの無限ループを10秒間ぐらいただただ流し続けたい。そしてそれが止まったあとに文字を赤くしたりして「おい、こっちが提示した文章ちゃんと読んでんのかコラ」という警告を出したい。
・文字を一文字ずつ表示したい。文章がまるごとパッと表示されるより読みやすくなるし対話してる感が出ることを期待。
・プレイヤーの入力チェックで同じようなコードが繰り返し使われているので、うまいこと関数化したい。
・わざと不正な入力を試すタイプのプレイヤー向けに、不正な値が入力された回数をカウントして、最後それを表示したい。数当てゲームとは直接カンケー無い隠し要素ww
・あと、わざと不正な入力を試すタイプのプレイヤー向けに、怖いアニメーションとか用意して「お前繰り返しそんなことして俺と気が合いそうだな？コラ」みたいなメッセージも出したい。そうです、私がわざと不正な入力を試すタイプのプレイヤーですw

### ソースコード
```
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>

int isValidInteger(char* str) {
	if (str[0] == '-' || str[0] == '+') {
		str++;
	}
	while (*str) {
		if (!isdigit(*str)) {  // 数字以外の文字があれば無効
			return 0;
		}
		str++;
	}
	return 1;
}

int main(void) {
	int keepPlaying = 1;

	while(keepPlaying == 1){
		int count = 1;
		char input[256];
		int r = 0;
		int r_max = 99;	
		int mode;
		int answer;

		printf("こんにちは。数当てゲームです。\n");
		printf("モードを選んでください。(0:かんたん, 1:ふつう)\n");
		printf("※ かんたんモードでは、答えの±5以内の数字を入力すると「惜しいです！」と表示されます。\n");

		srand((unsigned int)time(NULL));

		fgets(input, sizeof(input), stdin);
		input[strcspn(input, "\n")] = '\0';

		while (1) {
			if (input[0] == '\0')
			{
				printf("何か入力してください。\n");
				fgets(input, sizeof(input), stdin);
				input[strcspn(input, "\n")] = '\0';
			}
			else if (!(isValidInteger(input)))
			{
				printf("\nモード選択では(0:かんたん, 1:ふつう)のどちらかを半角数字で入力してください。\n");
				fgets(input, sizeof(input), stdin);
				input[strcspn(input, "\n")] = '\0';
			}
			else
			{
				break;
			}
		}

		mode = atoi(input);
		if (mode == 0) {
			printf("\nそれでは、かんたんモードで開始します。れっつご～！\n\n");
		}
		else if (mode == 1) {
			printf("\nそれでは、ふつうモードで開始します。れっつご～！\n\n");
		}
		else {
			printf("\nこちらの提示を無視した好奇心旺盛なあなたには鬼畜モードをご提供させていただきます。\n");
			printf("LET DIE!!!!\n\n");
		}

		if (!(mode == 1 || mode == 0))
		{
			r_max = RAND_MAX;
		}
		r = 1 + rand() % r_max;

		printf("私が思い浮かべた数字を当ててください。\n");
		printf("その数は1～%dのいずれかの整数です。\n", r_max);

		while (1) {
			// プレイヤーが回答を入力
			fgets(input, sizeof(input), stdin);
			input[strcspn(input, "\n")] = '\0';
			while (1) {
				if (isValidInteger(input) == 1) {
					break;
				}
				else
				{
					printf("1～%dの整数を半角数字で入力してください。\n", r_max);
					fgets(input, sizeof(input), stdin);
					input[strcspn(input, "\n")] = '\0';
				}
			}
			answer = atoi(input);

			if (answer < r)
			{
				if ((mode == 0) && ((answer <= r + 5) && (answer >= r - 5)))
				{
					printf("\n惜しいです！それより少しだけ大きい数字です。\n");
				}
				else {
					printf("\nそれより大きい数字です。\n");
				}
			}
			else if (answer > r)
			{
				if ((mode == 0) && ((answer <= r + 5) && (answer >= r - 5))) {
					printf("\n惜しいです！それより少しだけ小さい数字です。\n");
				}
				else
				{
					printf("\nそれより小さい数字です\n");
				}
			}
			else {
				printf("正解です！\n\n");
				break;
			}
			count++;
		}
		printf("あなたは%d回で正解しました。\n", count);
		printf("もう一度プレイしますか？(1:続行, 0:終了)\n");

		fgets(input, sizeof(input), stdin);
		input[strcspn(input, "\n")] = '\0';

		if (strcmp(input, "1") == 0) {
			printf("\n\n続行します。\n\n");
		}
		else {
			keepPlaying = 0;
		}
	}
	printf("終了します。\n");
	getchar();

}