数当てゲーム(Hit&Blow)プログラムの作成

最初に必要な処理をサブルーチンにまとめていくことから始めてみましょう。

ユーザーが当てるプログラムは完成しました。

次は、コンピュータに当てさせることを考えてみましょう。

候補数リストを使って質問を選択させることを考えます。

質問の評価@

個数が最大である分類が質問の回数に影響すると考え、候補数リストの最大値で評価します。ただし、質問が候補リストにある場合には、値に-1の修正を行います。

候補数リストの回数だけ繰り返し、最大値を求めます。

評価@サブルーチン

# 評価@サブルーチン
sub hyoka1 {
	my @kouhosu=@_; # 候補数リストを受け取る
	my $i;
	
	my $max=0; # 最大値を0に初期化

	for ($i=0; $i<=12; $i++) { # 候補数リストの個数分繰り返し
		if ($kouhosu[$i]>$max) { # 現在の最大値を越えたら最大値を更新
			$max=$kouhosu[$i];
		}
	}
	if ($kouhosu[12]==1) { # 候補リストに含まれる場合
		$max=$max-1;
	}

	return $max;
}

質問の評価A

個数nの候補リストから答えを見つけるのに必要な質問の回数は、log(n)に比例すると考え、n*log(n)の総和で評価します。ただし、質問が候補リストにある場合には、値に-2*log2の修正を行います。

候補数リストの回数だけ繰り返し、n*log(n)の値を加算していきます。

評価Aサブルーチン

# 評価Aサブルーチン
sub hyoka2 {
	my @kouhosu=@_; # 候補数リストを受け取る
	my $i;
	
	my $sum=0; # 合計値を0に初期化

	for ($i=0; $i<=12; $i++) { # 候補数リストの個数分繰り返し
		if ($kouhosu[$i]!=0) { # 0のlogは取れないので0の場合には処理を飛ばす
			$sum=$sum+$kouhosu[$i]*log($kouhosu[$i]);
		}
	}
	if ($kouhosu[12]==1) { # 候補リストに含まれる場合
		$sum=$sum-2*log(2);
	}

	return $sum;
}

質問の選択

すべての質問に関して評価を行い、最も評価値の低くなる質問を返すサブルーチンを作成します。

質問の選択サブルーチン

# 質問の選択サブルーチン
sub select_question {
	my @kouho=@_; # 候補リストを受け取る
	my $min=10000; # 最小値を10000に初期化
	my @kouhosu;
	my @question;
	
	foreach $question (@allkouho) { # すべての質問について繰り返し
		@kouhosu=&count_kouho($question, @kouho); # 質問で候補を分類
		$hyoka=&hyoka2(@kouhosu); # 評価A
		if ($hyoka<$min) { # 現在の最小値を下回ったら最小値とその質問を更新
			$min=$hyoka;
			$min_question=$question;
		}
	}
	return $min_question;
}

メインルーチンの修正

ユーザーからの入力部分をコメントアウトして、質問の選択サブルーチンを呼ぶように変更します。

#$number=&input; # 入力
$number=&select_question(@kouho); # 質問の選択サブルーチン