#1 楼
未使用的导入-警告您正在使用Eclipse。 Eclipse和NetBeans是IDE的IDE,它们可能会(除了将它们关闭之外)还向您发出有关代码的警告。不要使用
Main
。因此,您应该删除它。您的IDE会不时给您其他警告。如果您看一下它给您的警告,它将对调试(“嘿,您在这里在null变量上调用函数!”)和清理代码(“使用
java.util.Random
代替String.isEmpty()
”-我知道NetBeans甚至只允许您单击一个按钮,它就会为您修复。)重复代码-重构
只要有可能,请尽量不要多次声明。
执行此功能。
public boolean guess(int guess) {
tries++;
if (guess == randomNumber) {
if (tries > 1) {
System.out.println("You got the number in " + tries + " tries.");
return true;
} else {
System.out.println("You got the number in " + tries + " try.");
return true;
}
} else if (guess > randomNumber) {
System.out.println("Too high try again");
return false;
} else if (guess < randomNumber) {
System.out.println("Too low try again ");
return false;
}
return false;
}
应该做什么:
增加尝试次数乘以1。如果猜测正确,则报告尝试次数。如果猜测不正确,请报告该数字是低于还是高于隐藏数字。如果猜测正确,则返回true;如果猜测不正确,则返回false。
现在,您只是将一个int与另一个int进行比较,因此无需将
string == ""
定义为但是,我们可以做的是从分支中删除重复的代码。 if (tries > 1) {
System.out.println("You got the number in " + tries + " tries.");
return true;
} else {
System.out.println("You got the number in " + tries + " try.");
return true;
}
该代码可以变成这样:
/>
if (tries > 1) {
System.out.println("You got the number in " + tries + " tries.");
} else {
System.out.println("You got the number in " + tries + " try.");
}
return true;
由于它是一个简单的字符串,您可以做的另一件事是使用三进制:
System.out.println("You got the number in " + tries + ((tries > 1) ? " tries." : " try."));
return true;
对于“太高,太低的部分”也可以做类似的事情。
但这是另一种特殊情况...
如果数字不等于且不小于到某个值,那么显然它必须大于该值。
因此代码
if(is equal){
print got number in x tries
return true
} else if(is lower){
print try higher
return false
} else if(is higher){
print try lower
return false
}
最终的代码片段看起来像这样:
if(is equal){
print got number in x tries
return true
} else if(is lower){
print try higher
return false
} else {
print try lower
return false
}
您甚至可能要考虑将整个消息打印导出到单独的功能:值:
public boolean guess(int guess) {
tries++;
if (guess == randomNumber) {
System.out.println("You got the number in " + tries + ((tries > 1) ? " tries." : " try."));
return true;
} //implicit else because return would end the function
if (guess > randomNumber) {
System.out.println("Too high try again");
} else {
System.out.println("Too low try again ");
}
return false;
}
将大型功能转换为几个较小的功能,每个功能都比起初使用的原始功能更容易掌握。
评论
\ $ \ begingroup \ $
我个人认为printTooHigh是过多的功能拆分。
\ $ \ endgroup \ $
– Almo
2014年10月31日,下午3:22
\ $ \ begingroup \ $
@Almo现在还可以,但是稍后您将不得不使某种消息框出现,或者出现i18n问题,或者不仅仅是一个打印语句。无论如何,通过提取函数,我们可以使guess函数在单个抽象级别上运行-情况1做到了,情况2做到了,情况3做到了,而不是混合了函数调用和print语句。
\ $ \ endgroup \ $
– Pimgd
14-10-31在8:23
\ $ \ begingroup \ $
非常感谢您的答复。您对如何缩短收益的解释很有帮助。另外,感谢您向我展示了三元数据,我之前从未听说过,不过将来肯定会使用它!
\ $ \ endgroup \ $
– jjacobson
2014年10月31日上午11:02
\ $ \ begingroup \ $
@jjacobson请记住,三元仅用于诸如此类的简单事情;通过非常快速地包含三元,代码会变得非常复杂。
\ $ \ endgroup \ $
– Pimgd
2014年10月31日在11:05
\ $ \ begingroup \ $
@Pimgd感谢您的注意。我将仔细阅读它们,以便可以正确使用它们。
\ $ \ endgroup \ $
– jjacobson
2014年10月31日11:10
#2 楼
这是您计划要做的一个很好的实现。事物的命名很清楚,并且代码可以很好地拆分为方法。主类
我可能会对用户的预期进行更清晰的解释一开始要做的事情,以及您的“输入上限”。通常,这是打破您最好的ascii艺术的借口。
如果您的用户不输入整数,该怎么办?这将破坏您的程序,因此请进行一些错误处理,请您容易出错的肉包再次尝试并使其正确。您的检查方法是将
scan.nextInt()
放在try / catch块中并捕获InputMismatchException
。当您问玩家是否要再次玩时,请将
running
设置为true,但是游戏类
每次调用
rand
时,您都在播种generateRandomNumber()
,这并不是真的成为一个问题,因为您没有快速/经常调用该方法,但实际上您应该只在程序中播种一次随机数生成器,否则您将一遍又一遍地开始让它返回相同的值,因此也许将您的Random rand = new Random()
移至构造函数?在
guess()
中,我将第一部分重新排列为: if (guess == randomNumber) {
if (tries > 1) {
System.out.println("You got the number in " + tries + " tries.");
} else {
System.out.println("You got the number in " + tries + " try.");
}
return true;
}
您在重复减少自己的负担,返回值相同。下一部分也一样,我将有:
else if (guess > randomNumber) {
System.out.println("Too high try again");
} else if (guess < randomNumber) {
System.out.println("Too low try again ");
}
return false;
评论
\ $ \ begingroup \ $
“如果您的用户不输入整数,该怎么办?”您会收到一个InputMismatchException。
\ $ \ endgroup \ $
– Pimgd
14-10-30在10:26
\ $ \ begingroup \ $
非常感谢您的答复。我曾考虑过用户输入错误的信息,并问我的教授是否应该牢记这一点。自从我们的第一个项目以来,他告诉我这次不必担心。否则我肯定会做到这一点。
\ $ \ endgroup \ $
– jjacobson
2014年10月31日10:50
#3 楼
这对我来说看起来不错。我特别喜欢Game
是它自己的类。这是正确的决定,所以做得很好。在这种情况下,这意味着不写入Game
;将输出上移至System.out
,您也正在执行输入。尽管在像这样的小程序中并没有太大的区别,但它通常会导致可重用,可测试的代码,并且是进入代码的一种好习惯。现在,您可以使
main
最终。这意味着一旦分配给它,其值就无法更改。它使您的意图对阅读您的代码的人很清楚,并且编译器会告诉您是否违反了该规则。#4 楼
由于多余使用了两个标志变量main()
和win
,因此running
函数笨拙。通常,使用标志变量来控制执行流是不好的样式。还有更多更自信的方法可以到达目的地:要运行游戏至少一次,然后可能一次又一次地使用do-while循环。
在可行的情况下,编写循环条件以执行正确的测试。
恰好三个分支之一必须申请。 (您最终的
Game.guess()
应该是不可访问的。)“ try”的多元性可以看作是要通过return false;
解决的国际化问题。 (相对于某些其他语言,英语的复数形式比较简单。MessageFormat
为应对这种复杂性作了更好的准备。您不妨利用为解决复数问题而构建的内置库。)public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Please enter the upper limit: ");
Game game = new Game(scan.nextInt());
do {
game.reset();
System.out.println("Please enter a guess ");
while (!game.guess(scan.nextInt())) {
// Loop until a correct guess
}
System.out.println("Would you like to play again y/n?");
} while (scan.next().equalsIgnoreCase("y"));
System.out.println("Game over");
}
#5 楼
不错的开始!您应该将所有游戏控制逻辑移至
Game
,以便您的主循环为while (!game.isGameOver())
{
game.nextMove()
}
您可以编写代码“你想玩另一个吗?”很好地超出了这个循环。因此,
Player
会要求Game
作为输入:class Game
{
public Game (Player p)
{
player = p;
}
Player player;
public void nextMove()
{
//or something similar
guess(player.getNextInput());
}
}
您可以将所有IO(
Player
等)移至System.out
类,因为Player
不需要了解现在,您可以轻松实现
Game
或TestPlayer
,而无需更改游戏逻辑中的任何内容。由于
AIPlayer
是游戏逻辑,它应该返回guess()
知道,并通知玩家。例如Game
,其中可能包含一些代码(枚举),变量和一条消息。 public MoveResult
{
public static enum {TOO_HIGH, TOO_LOW, RIGHT}
String message;
}
在
MoveResult
中 public void nextMove()
{
//or something similar
MoveResult result = guess(player.getNextInput());
player.notify(result);
}
#6 楼
我的第一印象是您的代码看起来不错:简洁一致的样式,合理的方法长度,良好的变量名。唯一让我惊讶的事情(其他人没有提到)完全没有文档。当您是唯一一个从事快速,小型项目的开发人员时,可以省略评论。当您进行长期项目时,或者与其他开发人员一起工作时,应该使用经过深思熟虑的文档。我写的文档为我(和我的同事)节省了比我花费更多的时间。在编写该程序时,我会重新考虑程序并经常发现设计中的缺陷,然后可以对其进行改进(请参阅橡皮鸭调试)。在您仍在学习时养成良好的习惯将是有益的。至于文档的内容,请阅读您使用的任何库的Javadocs(尤其是从Sun / Oracle和Apache之类的大型提供程序中)。
评论
\ $ \ begingroup \ $
您可以通过添加一些代码和更多参考来改善您的答案。
\ $ \ endgroup \ $
–bhathiya-perera
2014年10月31日15:16
评论
对于初学者来说,这是相当不错的。我想你会好的。欢迎使用代码审查!我很难不对使用K&R支撑的格式良好的代码发表评论。哦,等等,我就是这样。 :)对于初学者来说确实不错! :D
@Almo Allman是必去之路