[10.10] 練習問題

1から100までの間から選んだ秘密の数を、ユーザにあててもらうプログラムを書いてください。このプログラムは、入力した数が当たるまで、何回でも繰り返してユーザに入力を求めます。
初めてのPerl p.175

以下が自分なりの解答です。

print "1から100までランダムに選んだ数を、当てるプログラムです。\n";

my $n = int(1 + rand 100);
print "$n\n"; #デバッグ用処理

print "1から100までの数を入力してください。\n終了したいときは quit 、 exit と入力するか、何も入力しないでください。\n";
chomp( my $ans = <STDIN> );


until ( ($ans eq $n) || ($ans eq 'quit') || ($ans eq 'exit') || ($ans == "") ) {
    if ($ans > $n ) {
	print "入力した数は大きすぎます。\n";
    } else {
	print "入力した数は小さすぎます。\n";
    }

    print "数を入力してください。\n終了したいときは quit 、 exit と入力するか、何も入力しないでください。\n";
    chomp( $ans = <STDIN> );
}

空文字列判定処理に手間取って、時間切れに。

それとよく考えたら、「正解の場合」と「終了したい場合」の二通りがあるのに、until命令の条件を同列に並べるのは駄目駄目だな。
明確に分けないと。


そして下記のコードが、解答を参考に作成したプログラムです。

print "1から100までランダムに選んだ数を、当てるプログラムです。\n";

#1から100までのランダムな数を生成
my $random = int(1 + rand 100);
print "$random\n"; #デバッグ用処理


#数入力処理、判定処理
while (1) {
    print "1から100までの数を入力してください。\n終了したいときは quit か exit,
あるいは何も入力しないでください。\n";
    chomp(my $num = <STDIN>);
    if ($num =~ /quit|exit|^\s*$/i) {
	print "ギブアップです。ランダムな数は $random でした。\n";
	last;
    } elsif ($num =~ /[^0-9]+/) {
	print "数字を入力してください。\n\n";
	next;
    } elsif ($num < $random) {
	print "$numは小さすぎます!\n\n";
	next;
    } elsif ($num == $random) {
	print "正解です!\n";
	last;
    } else {
	print "$numは大きすぎます!\n\n";
    }
}

解答を見ずにプログラムを書いているとき、最も厄介だったのが「数字」と「文字列」の判定部分でした。
Perlは他の言語とは違い変数の型に明確な区別がないので、「数字」と「文字列」判定はプログラムを書く限りずっと付きまとうのでしょうね。
ここのあたりは特に慎重にやらなきゃ。


それにしても正規表現を用いて「文字列」か判定するなんて、驚きました。
はじめて見たもんで…。
ですが

($ans eq 'quit') || ($ans eq 'exit')

なんて延々と書くよりは、よっぽどわかりやすい&書きやすいですよね。