学以致用——Java源码——抛双骰儿游戏综合评估(游戏步数与胜率的关系,公平性,平均步数等)(Game of Craps Evaluation)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hpdlzu80100/article/details/85255944

相比2008年版的需求,这次增加了不少功能。

程序的运行结果可以告诉我们以下问题的答案:

a) How many games are won on the first roll, second roll, …, twentieth roll and after the twentieth roll?

1. 赢局中的抛双骰总次数是如何分布的?(统计到二十次,二十次以上的赢局计入第二十步)

b) How many games are lost on the first roll, second roll, …, twentieth roll and after the twentieth roll?

2. 输局中的抛双骰总次数是如何分布的?(统计到第二十次,二十步以上的输局计入第二十步)

c) What are the chances of winning at craps? [Note: You should discover that craps is one of the fairest casino games. What do you suppose this means?]

3. 抛双骰游戏的胜率是多少?是否公平? (100万次,胜率在49.3%左右,基本公平(50%为绝对公平))

d) What is the average length of a game of craps?

游戏的平均抛双骰次数是多少? (3.3左右)

e) Do the chances of winning improve with the length of the game?

扫描二维码关注公众号,回复: 4713760 查看本文章

游戏步数增多时,是否提高了赢局的概率? (模拟结果告诉我们,如果第一步不能赢,后面各步都是输的概率高!

运行结果:

请输入抛双骰游戏的模拟次数(输入-1退出):1000000

已模拟运行游戏1000000次:

赢得游戏493084次,胜率:49.31%

一步即胜222236次,在胜场中占比:45.07%

平均每局游戏所用步数:3.38

 

赢得游戏所用总步数:1451779

输掉游戏所用总步数:1929127

详细分布如下:

 1步:    赢: 222236         22.22%             输: 110924         11.09%

 2步:    赢:  76949         7.69%              输: 110660         11.07%

 3步:    赢:  55278         5.53%              输:  79725         7.97%

 4步:    赢:  39443         3.94%              输:  57501         5.75%

 5步:    赢:  27902         2.79%              输:  41454         4.15%

 6步:    赢:  19865         1.99%              输:  29522         2.95%

 7步:    赢:  14414         1.44%              输:  21340         2.13%

 8步:    赢:  10290         1.03%              输:  15470         1.55%

 9步:    赢:   7379         0.74%              输:  11109         1.11%

10步:    赢:   5409         0.54%              输:   8104         0.81%

11步:    赢:   3932         0.39%              输:   5691         0.57%

12步:    赢:   2746         0.27%              输:   4133         0.41%

13步:    赢:   1974         0.20%              输:   3067         0.31%

14步:    赢:   1409         0.14%              输:   2245         0.22%

15步:    赢:   1077         0.11%              输:   1683         0.17%

16步:    赢:    803         0.08%              输:   1127         0.11%

17步:    赢:    538         0.05%              输:    850         0.08%

18步:    赢:    376         0.04%              输:    604         0.06%

19步:    赢:    298         0.03%              输:    459         0.05%

20步:    赢:    766         0.08%              输:   1248         0.12%

请输入抛双骰游戏的模拟次数(输入-1退出):1000000

已模拟运行游戏1000000次:

赢得游戏493184次,胜率:49.32%

一步即胜221928次,在胜场中占比:45.00%

平均每局游戏所用步数:3.38

 

赢得游戏所用总步数:1452104

输掉游戏所用总步数:1924298

详细分布如下:

 1步:    赢: 221928         22.19%             输: 111387         11.14%

 2步:    赢:  76915         7.69%              输: 111439         11.14%

 3步:    赢:  55135         5.51%              输:  79194         7.92%

 4步:    赢:  39732         3.97%              输:  56734         5.67%

 5步:    赢:  28268         2.83%              输:  41430         4.14%

 6步:    赢:  20115         2.01%              输:  29754         2.98%

 7步:    赢:  14432         1.44%              输:  21208         2.12%

 8步:    赢:  10301         1.03%              输:  15439         1.54%

 9步:    赢:   7427         0.74%              输:  11129         1.11%

10步:    赢:   5187         0.52%              输:   8090         0.81%

11步:    赢:   3720         0.37%              输:   5798         0.58%

12步:    赢:   2819         0.28%              输:   4204         0.42%

13步:    赢:   1932         0.19%              输:   2944         0.29%

14步:    赢:   1455         0.15%              输:   2225         0.22%

15步:    赢:   1098         0.11%              输:   1604         0.16%

16步:    赢:    698         0.07%              输:   1166         0.12%

17步:    赢:    550         0.06%              输:    815         0.08%

18步:    赢:    392         0.04%              输:    612         0.06%

19步:    赢:    306         0.03%              输:    462         0.05%

20步:    赢:    774         0.08%              输:   1182         0.12%

请输入抛双骰游戏的模拟次数(输入-1退出):

参考文章:

掷双骰儿游戏的公平性分析(Evaluate the justice of Craps game),https://blog.csdn.net/hpdlzu80100/article/details/2305264

代码如下:

import java.security.SecureRandom;
import java.util.Scanner;

//Java How to Program, 10th/e, Exercise 7.18: Game of Craps
//by [email protected]
/**
 * 7.18 (Game of Craps) Write an application that runs 1,000,000 games of craps
 * (Fig. 6.8) and answers the following questions:
 * a) How many games are won on the first roll, second roll, …, twentieth roll and after the twentieth roll?
 * b) How many games are lost on the first roll, second roll, …, twentieth roll and after the twentieth roll? 
 * c) What are the chances of winning at craps?
 * 	  [Note: You should discover that craps is one of the fairest casino games. What do you suppose this means?] 
 * d) What is the average length of a game of craps? 
 * e) Do the chances of winning improve with the length of the game?
 */

	public class GameCrapsEvaluation 
	{
	   // create secure random number generator for use in method rollDice
	   private static final SecureRandom randomNumbers = new SecureRandom();

	   // enum type with constants that represent the game status
	   private enum Status {CONTINUE, WON, LOST};

	   // constants that represent common rolls of the dice
	   private static final int SNAKE_EYES = 2;
	   private static final int TREY = 3;
	   private static final int SEVEN = 7;
	   private static final int YO_LEVEN = 11;
	   private static final int BOX_CARS = 12;
	   
	   private static int winTimes = 0; 
	   private static int stepsTillWinTotal = 0; 
	   private static int stepsTillLoseTotal = 0;
	   private static int stepsContinueTotal = 0;
	   private static int stepsContinueSinglePlay = 0;
	   private static double winPercentage = 0.0; //赢得游戏的概率
	   private static double averageLength = 0.0; //平均每局游戏所用步数
	   private static int winTimesOneShot = 0; //一步即胜次数
	   private static int[] stepsTillWinFrequency = new int[21]; //赢局的游戏步数
	   private static int[] stepsTillLoseFrequency = new int[21]; //输局的游戏步数
	   
	   public static void main(String[] args)
	   {
			int playTimes=0;
			Scanner input=new Scanner(System.in);
			
			do{
				initialize();
				System.out.print("请输入抛双骰游戏的模拟次数(输入-1退出):");
				playTimes =input.nextInt();
				if(playTimes ==-1){
					System.out.printf("已退出程序");
					break;
				}
					
				for (int i=0;i<playTimes; i++) {
					//System.out.printf("第%d次游戏开始%n", i+1);
					playCraps();   //模拟游戏
					//System.out.printf("第%d次游戏结束%n", i+1);
				}	
				//计算统计值
				winPercentage = (double)winTimes/playTimes*100;
				averageLength = (double)(stepsTillWinTotal + stepsTillLoseTotal)/playTimes;
				
				System.out.printf("已模拟运行游戏%d次:%n", playTimes);
				System.out.printf("赢得游戏%d次,胜率:%.2f%%%n", winTimes, winPercentage);
				System.out.printf("一步即胜%d次,在胜场中占比:%.2f%%%n", winTimesOneShot,
						(double)winTimesOneShot/winTimes*100);
				System.out.printf("平均每局游戏所用步数:%.2f%n%n", averageLength);
				System.out.printf("赢得游戏所用总步数:%d%n", stepsTillWinTotal);
				System.out.printf("输掉游戏所用总步数:%d%n", stepsTillLoseTotal);
				System.out.printf("详细分布如下:%n");
				for (int i=1; i<21; i++)
					System.out.printf("%2d步:\t赢:%7d\t%.2f%%\t\t输:%7d\t%.2f%%%n",i,stepsTillWinFrequency[i],
							(double)stepsTillWinFrequency[i]/playTimes*100,
							stepsTillLoseFrequency[i],
							(double)stepsTillLoseFrequency[i]/playTimes*100);
				
	   }while (playTimes != -1);
			
			input.close();

	   }

	   // plays one game of craps
	   public static void playCraps()
	   {
		  stepsContinueSinglePlay = 0; //每局游戏开始时重置为0
	      int myPoint = 0; // point if no win or loss on first roll
	      Status gameStatus; // can contain CONTINUE, WON or LOST

	      int sumOfDice = rollDice(); // first roll of the dice

	      // determine game status and point based on first roll 
	      switch (sumOfDice) 
	      {
	         case SEVEN: // win with 7 on first roll
	         case YO_LEVEN: // win with 11 on first roll           
	            gameStatus = Status.WON;
	            ++stepsTillWinTotal;
	            ++stepsTillWinFrequency[1];
	            ++winTimesOneShot;
	            break;
	         case SNAKE_EYES: // lose with 2 on first roll
	         case TREY: // lose with 3 on first roll
	         case BOX_CARS: // lose with 12 on first roll
	            gameStatus = Status.LOST;
	            ++stepsTillLoseTotal;
	            ++stepsTillLoseFrequency[1];
	            break;
	         default: // did not win or lose, so remember point         
	            gameStatus = Status.CONTINUE; // game is not over
	            myPoint = sumOfDice; // remember the point
	            ++stepsContinueTotal;
	     	    ++stepsContinueSinglePlay;
	            //System.out.printf("Point is %d%n", myPoint);
	            break;
	      } 

	      // while game is not complete
	      while (gameStatus == Status.CONTINUE) // not WON or LOST
	      { 
	         sumOfDice = rollDice(); // roll dice again

	         // determine game status
	         if (sumOfDice == myPoint) { // win by making point
	        	gameStatus = Status.WON;
	        	 ++stepsTillWinTotal; 
	        	 ++stepsTillWinFrequency[++stepsContinueSinglePlay<20 ? stepsContinueSinglePlay: 20];
	         }
	         else 
	            if (sumOfDice == SEVEN) {// lose by rolling 7 before point
	               gameStatus = Status.LOST;
	               ++stepsTillLoseTotal;
	               ++stepsTillLoseFrequency[++stepsContinueSinglePlay<20 ? stepsContinueSinglePlay: 20];
	            }
	            else
	            {
	            	++stepsContinueTotal;
	            	++stepsContinueSinglePlay;}
	      } 

	      // display won or lost message
	      if (gameStatus == Status.WON) {
	         //System.out.println("Player wins");
	         stepsTillWinTotal +=stepsContinueTotal; //如果最终赢了,continue状态的计数次数算到赢得游戏所需步数
	         stepsContinueTotal = 0; //单次游戏结束,将continue状态的计数器置0
	         ++winTimes;
	      }
	      else {
	         //System.out.println("Player loses");
	         stepsTillLoseTotal +=stepsContinueTotal; //如果最终赢了,continue状态的计数次数算到赢得游戏所需步数
	         stepsContinueTotal = 0; //单次游戏结束,将continue状态的计数器置0
	      }
	     
	   }

	   // roll dice, calculate sum and display results
	   public static int rollDice()
	   {
	      // pick random die values
	      int die1 = 1 + randomNumbers.nextInt(6); // first die roll
	      int die2 = 1 + randomNumbers.nextInt(6); // second die roll

	      int sum = die1 + die2; // sum of die values

	      // display results of this roll
	      //System.out.printf("Player rolled %d + %d = %d%n", 
	        // die1, die2, sum);

	      return sum; 
	   }
	   
	   
	   public static void initialize()
	   {
		 //开始新的模拟,全局变量清零
		   winTimes = 0; 
		   stepsTillWinTotal = 0; 
		   stepsTillLoseTotal = 0;
		   stepsContinueTotal = 0;
		   winTimesOneShot = 0; //一步即胜次数

		   for (int i=0;i<21;i++)
			   {
			   stepsTillWinFrequency[i] = 0; 
			   stepsTillLoseFrequency[i] = 0;
			   }
	   }
	} // end class Craps

猜你喜欢

转载自blog.csdn.net/hpdlzu80100/article/details/85255944
今日推荐