你没有提到哪一行是第 25 行!这可能很重要。
不过,看看你的while说法。请注意,您正在与 进行比较$guess,$target但尚未设置$guess。这是在你的while循环中设置的。这就是你得到未定义变量的原因。
我也没有看到在哪里$counter设置。这也可能是一个问题。
让我们仔细看看你的while循环:
while ( $guess < $target ) {
blah, blah, blah
}
假设有一个$guess,您将循环直到用户猜出一个大于 的数字$target。那是你要的吗?不,你说你想给用户八回合,就是这样。你想要的是更多类似的东西:
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关键字而不是for关键字,以将其与 C 样式的 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。此外,即使您确实失败了,您仍然处于该循环中。
您可能想要做的是将You lost线放在循环之外。这样,在第八次猜测并且你的循环结束后,你会得到You lost spiel。
另外,让我们看看这一行:
chomp ( $guess = <> );
print "Enter guess $counter: ";
首先,<>是null 文件句柄运算符,它与以下非常非常不同<STDIN>:
空文件句柄 <> 很特殊:它可以用来模拟 sed 和 awk 的行为,以及任何其他接受文件名列表的 Unix 过滤程序,对来自所有文件名的每一行输入执行相同的操作。<> 的输入要么来自标准输入,要么来自命令行中列出的每个文件。它是这样工作的:第一次评估 <> 时,检查 @ARGV 数组,如果它为空,则 $ARGV[0] 设置为“-”,打开时会为您提供标准输入。然后将@ARGV 数组作为文件名列表进行处理。
你想要的是<STDIN>.
另请注意,在打印提示之前您正在获取输入。你真的想这样做:
print "Enter guess $counter: ";
chomp ($guess = <STDIN>);
此外,您希望设置$|为非零值以关闭缓冲。否则,您可能仍需要$guess在看到提示之前输入您的。
这是修改后的程序Modern::Perl在我的系统上不起作用,所以我使用三个单独的 pragma 来覆盖它:
#! /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帮助避免神秘数字。例如,1..MAX_GUESSES帮助我理解循环会达到我的最大猜测,而1..8不能解释为什么我会去 8。另外,我可以简单地改变我的常数,突然你有 10 次改变猜测 1 到 1000 之间的数字.