你没有提到哪一行是第 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 之间的数字.