どの行が25行目であるかについては言及していません。それは重要かもしれません。
しかし、あなたのwhile
声明を見てください。と比較$guess
して$target
いるが、まだ設定していないことに注意してください$guess
。それはあなたのループの中に設定されています。while
これが、未定義の変数を取得する理由です。
どこに設定されているかもわかりません$counter
。それも問題になる可能性があります。
while
ループをもう少し詳しく見てみましょう。
while ( $guess < $target ) {
blah, blah, blah
}
が存在すると仮定すると$guess
、ユーザーが。よりも大きい数を推測するまでループします$target
。それはあなたが望むものですか?いいえ、ユーザーに8ターンを与えたいとおっしゃいましたが、それだけです。あなたが欲しいのは、次のようなものです。
my $count = 1;
while ( $count <= 8 ) {
$count++;
blah, blah, blah
}
これを行うためのもう少し良い方法は、forループを使用することです。
for ( my $count = 1; $count <= 8; $count++ ) {
blah, blah, blah
}
ただし、これらのCスタイルのforループは非常にパスです。1..8
さらに、構文を使用してこれを行うためのより明確な方法があります。これは言うのと同じ(1, 2, 3, 4, 5, 6, 7, 8)
です。クリーンで理解しやすいです:
for my $counter (1..8) {
blah, blah, blah
}
(注:このタイプのループを実行するときforeach
に、キーワードの代わりにキーワードを使用して、Cスタイルのforループと区別する人もいます。ただし、一部の人(咳!ダミアンコンウェイ、咳!)は、使用しないためfor
に眉をひそめます。foreach
本当に明快さを追加しません。)
ロジックの別の側面を見てみましょう。
if ($guess eq $target) {
print "\nCongratulations! You guessed the secret number $target in $counter";
}
elsif ($guess > $target) {
print "\nYour guess, $guess, is too high.";
}
elsif ($guess < $target) {
print "\nYour guess, $guess, is too low.";
}
else { #Do this if the guess isn't equal to, greater than or less than the target
print "You lose. The number was $target.";
}
あなたのelse
条項はいつ実行されますか?答えは決してありません。結局のところ、が$guess
より大きい、等しい、またはより小さい場合を除いて、実行することはできません$target
。また、あなたが負けたとしても、あなたはまだそのループにいます。
あなたがおそらくやりたいことは、あなたが負けたラインをループの外に置くことです。そうすれば、8番目の推測とループが終了した後、あなたはあなたがスピルを失うことになります。
また、この行を見てみましょう:
chomp ( $guess = <> );
print "Enter guess $counter: ";
まず、これ<>
はnullファイルハンドル演算子であり、次のものとは大きく異なり<STDIN>
ます。
nullファイルハンドル<>は特別です。これは、sedとawk、およびファイル名のリストを取得する他のUnixフィルタープログラムの動作をエミュレートするために使用でき、それらすべてからの入力の各行に対して同じことを行います。<>からの入力は、標準入力、またはコマンドラインにリストされている各ファイルからの入力です。仕組みは次のとおりです。最初に<>が評価されると、@ ARGV配列がチェックされ、空の場合は$ ARGV [0]が「-」に設定されます。これを開くと、標準の入力が得られます。@ARGV配列は、ファイル名のリストとして処理されます。
あなたが欲しいのはです<STDIN>
。
また、プロンプトを印刷する前に入力を取得していることに注意してください。あなたは本当に代わりにこれをしたいです:
print "Enter guess $counter: ";
chomp ($guess = <STDIN>);
また、$|
バッファリングをオフにするには、ゼロ以外の値に設定する必要があります。それ以外の場合$guess
は、プロンプトが表示される前に入力する必要があります。
Modern::Perl
これが私のシステムでは動作しない改訂されたプログラムです、それで私はそれをカバーするために3つの別々のプラグマを使用します:
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use constant {
UPPER_RANGE => 100,
MAX_GUESSES => 8,
};
$| = 1;
my $target = int ( ( rand UPPER_RANGE ) + 1 );
for my $counter (1..MAX_GUESSES) {
print "Enter guess #$counter: ";
chomp ( my $guess = <STDIN> );
if ($guess == $target) {
say "Congratulations! You guessed the secret number $target in $counter turns";
exit;
}
elsif ($guess > $target) {
say "Your guess, $guess, is too high.";
}
else {
say "Your guess, $guess, is too low.";
}
}
say "You lose. The number was $target.";
私がカバーしなかったいくつかのこと:
- 数値比較を行うときは、文字列用では
==
なく演算子を使用してください。eq
- できるとき
say
の代わりに使用します。print
このsay
コマンドはprint
、NLを自動的に最後に配置することを除けば似ています。
exit;
私があなたが勝ったと述べた後、注意してください。その時点でプログラムを終了したいと思います。
- 必要になるまで、すべての変数を宣言しないことに注意してください。私のプログラムでは、ループの内側と外側の両方に存在する間、ループの内側
$guess
に$counter
のみ存在します。for
$target
for
- 不思議な数字
use constant
を避けるのを手伝います。たとえば、ループが最大の推測になっていることを理解するのに役立ちますが、なぜ8に行くのかは説明されていません。また、定数を変更するだけで、突然、1から1000までの数値を10回変更できます。 。1..MAX_GUESSES
1..8