模拟踢球问题的Java程序,试了好久还是失败…… 请各位帮忙找一下错误

chinpom 2007-11-18 04:00:34
问题描述:有甲乙两名球员在进行射门比赛,甲的进球概率为a(假设a=0.5),乙的进球概率为b(假设b=0.5)。甲先开始射门,进球后可以再射一次,否则轮到对手射门。若任何一名球员比对方先多进两个球,则比赛结束,进球多的球员获胜。求甲乙两方获胜的概率各是多少?

以下是我用Java写的程序(我先后试了好多种程序流程):


import java.util.Random;

/**
* FootballPlayer类是足球运动员的抽象表示
*
* @since 1.0
* @version 1.0
*/
public class FootballPlayer {
private Random r = new Random(); // 获得一个Random类的实例

/**
* 这是足球运动员射门的方法
*
* @param p为运动员进球的概率
* 若参数p不合法,则抛出IllegalArgumentException异常
* @return 如果本次射门进球就返回true,否则返回false
*/
public boolean shoot(double p) {
if (p <= 0.0 || p >= 1.0)
throw new IllegalArgumentException("足球运动员进球的概率不合法!");
double d = r.nextDouble();
if (d < p)
return true;
else
return false; // 如果随机双精度浮点数d小于p,表示射门进球,否则表示没有进球
}

}


/**
* 这是模拟踢球问题的主类
*
* @since 1.0
* @version 1.0
*/
public class FootballMatch {

/**
* 程序入口点
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
FootballPlayer player1 = new FootballPlayer();
FootballPlayer player2 = new FootballPlayer();

int player1WinCount = 0; // 运动员player1获胜的次数
int player2WinCount = 0; // 运动员player2获胜的次数

for (int i = 0; i < 10000; i++) { // 进行10000场比赛来统计甲乙两方获胜的概率
int player1Count = 0; // 运动员player1在本次比赛中的累计进球数
int player2Count = 0; // 运动员player2在本次比赛中的累计进球数

// 比赛规则:任何一方比对方多进两个球就算获胜,比赛也就结束
// 比赛开始,player1先踢
for (;;) {
while (player1.shoot(0.5)) {
player1Count++;
if (player1Count >= player2Count + 2) {
player1WinCount++;
break; // 满足player1获胜的条件,停止射门,跳出while循环
}
}
if (player1Count >= player2Count + 2) {
break; // 满足player1获胜的条件,跳出无限for循环
}

while (player2.shoot(0.5)) {
player2Count++;
if (player2Count >= player1Count + 2) {
player2WinCount++;
break; // 满足player2获胜的条件,停止射门,跳出while循环
}
}
if (player2Count >= player1Count + 2) {
break; // 满足player1获胜的条件,跳出无限for循环
}
}
}

double player1WinP = player1WinCount
/ (player1WinCount + player2WinCount); // 运动员player1获胜的概率
double player2WinP = player2WinCount
/ (player1WinCount + player2WinCount); // 运动员player2获胜的概率

System.out.println("运动员player1获胜的概率:" + player1WinP);
System.out.println("运动员player2获胜的概率:" + player2WinP);

}

}


以上程序在Windows XP+Eclipse 3.3+Jre 1.6环境上运行的结果为:
运动员player1获胜的概率:0.0
运动员player2获胜的概率:0.0

这样的结果显然是错误的,可是我总是找不出Bug。随便说明一下,这个踢球的问题是我读高中时我的一位同学提出的,他那时候花了三个星期,写了十几页的证明,推出了甲乙获胜的一般表达式。他计算的结果和在电脑上模拟一亿次的比赛结果所得出的概率只有万分之一左右的误差,那他当然是对了!现在想起来,就一个字“汗”……而我到了现在就连这样的小程序都写不对。
...全文
96 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Chivalry 2007-11-22
  • 打赏
  • 举报
回复
你不知道结帖阿
ajaxqiu 2007-11-22
  • 打赏
  • 举报
回复
楼主强人啊!!
lihaifeng0412 2007-11-20
  • 打赏
  • 举报
回复
ding xia
胡矣 2007-11-20
  • 打赏
  • 举报
回复
mark
Chivalry 2007-11-19
  • 打赏
  • 举报
回复
我写的这个
if (player1Count > = player2Count + 2) {
player1WinCount++;
break; // 满足player1获胜的条件,停止射门,跳出while循环
}
else
{
player2WinCount++;
break;
}


可能不符合规则,应该是
if (player1Count > = player2Count + 2) {
player1WinCount++;
break; // 满足player1获胜的条件,停止射门,跳出while循环
}

if (player2Count > = player1Count + 2) {
player2WinCount++;
break; // 满足player1获胜的条件,停止射门,跳出while循环
}
Chivalry 2007-11-19
  • 打赏
  • 举报
回复
看了一下你的注释,你的注视很详细,好习惯阿

自己要学会调试
我帮你调适了一下,再double player1WinP = player1WinCount
/ (player1WinCount + player2WinCount); // 运动员player1获胜的概率
double player2WinP = player2WinCount
/ (player1WinCount + player2WinCount); // 运动员player2获胜的概率


之前分别打印
System.out.println(player1WinCount);
System.out.println(player2WinCount);
发现他们的次数是正常的,(最起码用我改的是正常的)比如一个是1000,一个是9000
然后发现他们打出的概率仍然是0,你就要分析一下了
因为player1WinCount和player2WinCount都是整数,因此
player1WinCount/(player1WinCount + player2WinCount);
player2WinCount/(player1WinCount + player2WinCount);
都表示两个整数相整除,因为player1WinCount,player2WinCount肯定都小于(player1WinCount + player2WinCount),因此结果为整数0,再将整数0付给double 0仍为0

解决方法就是
(player1WinCount*1.0)/(player1WinCount + player2WinCount);
(player2WinCount*1.0)/(player1WinCount + player2WinCount);
乘上一个1.0并不影响结果,但是1.0是一个浮点数,因此程序将按照浮点数相除算出一个浮点数结果赋值给player1WinP和player2WinP

结果就打出来了
你用你的程序这样该试试看可以不,不可以的话,用我的程序试一下,如过两个都行,在比较一下两个的优缺点
我把你的程序改了一下,如下

for (int i = 0; i < 10000; i++) { // 进行10000场比赛来统计甲乙两方获胜的概率
// 比赛规则:任何一方比对方多进两个球就算获胜,比赛也就结束
// 比赛开始,player1先踢
while (true) {
if(player1.shoot(0.5))
{
player1Count++;
}
if(player2.shoot(0.5))
{
player2Count++;
}

if (player1Count >= player2Count + 2) {
player1WinCount++;
break; // 满足player1获胜的条件,停止射门,跳出while循环
}
else
{
player2WinCount++;
break;
}
}
}

double player1WinP = (player1WinCount*1.0)
/ (player1WinCount + player2WinCount); // 运动员player1获胜的概率
double player2WinP = (player2WinCount*1.0)
/ (player1WinCount + player2WinCount); // 运动员player2获胜的概率

System.out.println( "运动员player1获胜的概率: " + player1WinP);
System.out.println( "运动员player2获胜的概率: " + player2WinP);

}

Chivalry 2007-11-19
  • 打赏
  • 举报
回复
for (;;) {
while (player1.shoot(0.5)) {
不清楚你的思想,这样是做不到无限循环的,因为如果player1.shoot的返回值为false的话,程序就推出循环了
你可以写成while(true){
palyer1.shoot(0.5);
}

关键是没看懂你判断胜负的原理,你可以说一下你的原理是什么
Chivalry 2007-11-19
  • 打赏
  • 举报
回复
for (int i = 0; i < 10000; i++) { // 进行10000场比赛来统计甲乙两方获胜的概率
int player1Count = 0; // 运动员player1在本次比赛中的累计进球数
int player2Count = 0; // 运动员player2在本次比赛中的累计进球数

palyer1Count1和2的赋值放在循环里面,不就每执行一次循环,重新定义赋值为0了么
我帮你调了一下,把它放到循环的外面
结果是1.0 0.0,可能还不是你要的结果,剩下的你在自己调试一下

还有,无限循环建议不要使用for (;;) ,使用while(true)更清晰一些

23,407

社区成员

发帖
与我相关
我的任务
社区描述
Java 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧