Java 使用随机发生器投掷硬币
我正试图编写一个模拟抛硬币的程序。第一次投币时,我希望程序退出。while循环中的第一个语句将掷硬币一次。然后我有一个if语句,它说如果我刚才掷的硬币是退出程序的。但是我的程序没有按我想要的方式运行。有时Java 使用随机发生器投掷硬币,java,Java,我正试图编写一个模拟抛硬币的程序。第一次投币时,我希望程序退出。while循环中的第一个语句将掷硬币一次。然后我有一个if语句,它说如果我刚才掷的硬币是退出程序的。但是我的程序没有按我想要的方式运行。有时 我的问题是,在while循环中,我是每1个周期掷硬币一次还是两次?硬币是否在while循环中翻转一次,然后在if条件下再次翻转?我已经测试过了,但每次都有不同的错误,结果也不一样,我不知道为什么 if条件是否适合我在程序中尝试执行的操作 import acm.program.*; import
我的问题是,在while循环中,我是每1个周期掷硬币一次还是两次?硬币是否在while循环中翻转一次,然后在if条件下再次翻转?我已经测试过了,但每次都有不同的错误,结果也不一样,我不知道为什么
if条件是否适合我在程序中尝试执行的操作
import acm.program.*;
import acm.util.*;
public class CoinToss extends ConsoleProgram{
public void run(){
while (true){
println(flipCoin());
if (flipCoin() == "heads"){
break;
}
}
}
public String flipCoin(){
String flip = rgen.nextBoolean() ? "heads" : "tails";
return flip;
}
public RandomGenerator rgen = RandomGenerator.getInstance();
}
每次调用
flipCoin()
时,该方法都会运行,因此它会在println(flipCoin())行上运行一次代码>和一次打开if(flipCoin()=“heads”)
。两次调用的结果可能不同,您应该存储结果,然后使用结果,因此:
while (true){
String result=flipCoin();
System.out.println(result);
if (result.equals("heads")){
break;
}
}
还请注意,将==与字符串一起使用(在大多数情况下)将始终给出false;这是因为==
询问它们是否是字面上相同的对象,而不是它们的内容是否相等(两张纸上都可以写“hi”,但它们不是同一张纸).equals
比较两个字符串的内容(即,如果它们说的是同一个单词)
<>我尽可能地将修改保持在您的代码附近,但您可能需要考虑以下可能的改进:
break
可以有合法用途,但通常是不必要的,您可以通过以下方式避免:
String result=flipCoin();
while (result.equals("heads")==false){
System.out.println(result);
result=flipCoin();
}
>p>再次使用字符串作为标识符有其位置,但考虑所有可用的不同的资本(头、头、头),枚举可能是更好的选择。
不,这是错误的。您的代码当前正在翻转一枚硬币,打印值,然后翻转另一枚硬币以测试退出。问题是,如果你连续翻转两个线圈,你不一定总能得到相同的结果
更好的方法是:
for(;;)
if(rgen.nextBoolean()) {
println("heads");
break;
} else
println("tails");
您不需要单独的方法来实际翻转硬币,因为该方法已经存在,称为rgen.nextBoolean()
。让方法返回一个字符串,然后处理该字符串,效率非常低。虽然效率与此无关,但不要养成这样的坏习惯,否则以后可能会被它咬到
编辑:针对一些评论,这里有一种更通用、面向对象的方法:
public enum CoinFlipResult {
HEADS, TAILS;
@Override
public String toString(){
switch(this){
case HEADS: return "heads"; break;
case TAILS: return "tails"; break;
}
} //could have just done `name().toLowerCase()`, but I like this better
}
public CoinFlipResult flipCoin(){
if(rgen.nextBoolean())
return CoinFlipResult.HEADS;
else
return CoinFlipResult.TAILS;
}
@Override
public void run(){
CoinFlipResult flip;
do {
flip = flipCoin();
println(flip);
} while(flip != CoinFlipResult.HEADS)
}
Me不喜欢不必要的break
s和不要将字符串与==进行比较:
String result = null;
do {
result = flipCoin()
println(result);
} while (!"tails".equals(result));
我建议为“heads”和“tails”引入字符串常量在while循环中运行flipCoin()两次。同时请注意,您将字符串与==进行比较,请改用.equals()。对于我的个人文化,我是唯一一个不喜欢使用break
语句的人吗?如果可以避免的话?@Bartdude是否有更优雅的方式退出程序而不是break?@Jessica使用导致break
的条件,作为while
循环中条件的一部分@巴特杜德:是的,break
和continue
只是goto
的花式版本,谢谢!我不敢相信我犯了那个错误。我的书中甚至有一节说,不要让.equals和==概念相互混淆。造成这一(常见)错误的原因之一是您的方法flipCoin()不仅翻转硬币,而且还获取硬币的状态。理想情况下,获取状态的操作应该与更改硬币状态的操作分开。这两个操作之间缺乏分离,因此很容易犯这样的错误。@RajeshJAdvani我同意,大概是一个Coin类,它有单独的.flip()和.getSide()方法。当然,这是相当多的开销,可能是值得的though@RichardTingle根据我的经验,对于大多数小的例子,像这种面向对象的设计,通常比像这样的直接方法有更多的开销。但在大多数情况下,随着例子的发展,这是值得的。哦,还有什么特别的原因要将布尔方法的结果与false进行比较吗?@MarcoForberg如果head和tails由enum表示(比如head和tails),那么为了清楚起见,您希望返回enum而不是布尔值,并将返回的值与特定的边进行比较。使用boolean
进行比较是必要的,但是添加带有特定比较的枚举会使犯错误变得更加困难。@MarcoForberg一旦我阅读了其中一个答案,我立即意识到我的错误。真不敢相信我把==和.equals搞混了。谢谢您的帮助。@AJMansfield为什么要空for循环,因为这实际上是一段时间(真的)?此外,您还使多行无括号-???成为一种艺术形式,在不使用大括号的情况下将5行代码放入for循环。我印象深刻,但我不确定这对于可读性是否是一件好事:关于“方法返回字符串,然后处理字符串”,我同意它的速度较慢,但并非绝对是一件坏事,您实际上暗示了true==heads,但从未真正显式声明过它,这个假设可能会导致一个更大的程序,直到您开始必须在程序的一部分中有转换点true==heads,而在另一部分中true==tails。即使这些部分从未相遇,也更难阅读。当然字符串比较是不好的,可以避免,但是我认为有更好的方法来避免it@RichardTingle我添加了一个更好的版本。@RichardTingle IDK,我只是更喜欢它。@AJMansfield对此无可争辩,我们都有不同的编码风格+1用于枚举示例