15.8: Example
- Page ID
- 54364
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)In this example, we will write a Fortran program to simulate the dice game of Twenty-Six1, which is a single player betting game with 10 dice. The main program will determine how many games to play, track the count of games won and lost, and display some win/loss statistics. A subroutine will be used to play the Twenty-Six game. The subroutine will be called as many times as requested.
The subroutine, twenty_six()
, will play the dice game Twenty-Six. To play the game, the player rolls the dice (1 to 6) and this initial roll is used as the “point” number. Then the player throws the ten dice 13 times. The score is the number of times that the point number is thrown. A random number between 1 and 6 will be used for each dice roll.
The routine will determine the payout based on the point count using the following table:
Point Count | Payout |
---|---|
10 or less | 10 |
13 | 5 |
26 | 4 |
27 | 5 |
28 | 6 |
29 | 8 |
30 | 10 |
Other | 0 |
The subroutine should display the dice (all 10 dice for each of 13 rolls), point count, game result, and payout. For example, if the point was 6, the subroutine might display the following:
Point: 6 Roll: 1 Dice: 4 6 5 3 3 1 1 3 3 2 Roll: 2 Dice: 1 6 3 3 4 1 4 4 2 6 Roll: 3 Dice: 3 2 6 4 5 3 2 1 5 4 Roll: 4 Dice: 5 6 4 1 4 6 6 2 4 4 Roll: 5 Dice: 4 6 6 4 5 3 6 1 5 5 Roll: 6 Dice: 3 1 4 5 6 5 3 3 3 4 Roll: 7 Dice: 6 6 5 6 1 5 5 6 5 5 Roll: 8 Dice: 4 1 3 4 1 4 4 6 2 5 Roll: 9 Dice: 4 4 2 1 1 4 3 1 5 4 Roll: 10 Dice: 5 6 1 2 4 1 1 2 1 1 Roll: 11 Dice: 2 3 2 4 1 3 3 6 5 1 Roll: 12 Dice: 1 1 6 5 4 5 1 6 6 5 Roll: 13 Dice: 6 4 4 5 3 3 5 3 3 5 Point Count: 22
For this example, the main will track the games won and lost.
Understand the Problem
The program will display an initial header and get the number of games to play. Specifically, we will need to prompt for the count of games and verify that the count is between 2 and 1,000,000 (arbitrarily chosen). Then, the program will call the twenty_six()
subroutine count times. After each game, the main will update the count of games won. The main will also track the payout and bank value status, which is initialized to 100 (chosen arbitrarily) and updated after each game is played.
An example main is provided as follows:
program diceGame !----------------------------------------------------------- ! Fortran program to simulate a dice game of Twenty-Six ! The main program: ! displays appropriate headers ! obtains and checks number of games to play ! loops to play 'count' number of games times implicit none integer, parameter :: initial_bank=100 integer :: num_games, games_won=0, games_lost=0 integer :: i, payout, bank integer, dimension(13,10) :: dice real :: win_pct write (*, '(/a/a/)') & "--------------------------------", & "Dice Game ""Twenty-Six"" Simulator." do write (*, '(2x, a )', advance = "no") & "Enter number games to simulate: " read (*,*) num_games if (num_games >= 2 .and. num_games <= 1000000) exit write (*, '(2x, a)') "Error, number of ", & "games must be between 1 and 1000000." write (*, '(2x, a)') "Please re-enter." end do bank = initial_bank call random_seed() do i = 1, num_games bank = bank - 1 call twentySix (payout) if (payout > 0) then games_won = games_won + 1 else games_lost = games_lost + 1 end if bank = bank + payout end do win_pct = ( real(games_won) / real(num_games) ) * 100.00 write (*,'(/a,/a/,3(2x,a,i9/),2(2x,a,i8/),2x,a,f4.1,a)') & "------------------------------------------------" & "Games Statistics:", & "Game Count: ", num_games, & "Games Won: ", games_won, & "Games Lost: ", games_lost, & "Initial Bank: ", initial_bank, & "Final Bank: ", bank, & "Win Percentage: ", win_pct, "%" contains ! ********************************************************* ! subroutine(s) goes here... ! ********************************************************* end program diceGame
Refer to Appendix C for additional information regarding the random number generation and initialization of the built-in random number generator.
Create the Algorithm
Since the main is provided, the algorithm will focus on the twenty-six game. Since the built-in random number generator provides random numbers between 0.0 and 1.0, they will need to be scaled and converted to an integer between 1 and 6 (for a dice). The initial point value must first be established followed by a loop to throw the ten dice 13 times in accordance with the game rules. The results will be stored in a two-dimensional array. While not strictly required, it does provide an additional example of how to use a two-dimensional array. Finally, the payout will be determined based on the game rules.
! Randomly select a number from 1 to 6 as the "point" number ! Throw ten dice 13 times ! results go into dice(13,10) array ! Score is the number of times that the point number ! is thrown ! determine payout
For convenience, the steps are written as program comments.
Implement the Program
Based on the algorithm, the below program could be created.
! ********************************************************* ! Subroutine to simulate twenty-six game. ! Randomly select a number from 1 to 6 as the “point” number ! Throw ten dice 13 times ! results go into dice(13,10) array ! Score is the number of times that the point number is thrown subroutine twentySix (payout) implicit none integer, dimension(13,10) :: dice integer, intent(out) :: payout integer :: point, pnt_cnt real :: x integer :: i, j ! determine point call random_number(x) point = int(x*6.0) + 1 ! roll dice pnt_cnt = 0 do i = 1, 13 do j = 1, 10 call random_number(x) dice(i,j) = int(x*6.0) + 1 if (dice(i,j) == point) pnt_cnt = pnt_cnt + 1 end do end do ! determine payout select case (pnt_cnt) case (:10) payout = 10 case (13,27) payout = 5 case (26) payout = 4 case (28) payout = 6 case (29) payout = 8 case (30) payout = 10 case default payout = 0 end select write (*,'(/,5x,a,/,5x,a,i2,/,5x,a,i2)') & "--------------------------------------", & "Point: ", point do i = 1, 13 write (*,'(8x, a, i2, 2x, a, 10(2x, i1),/)', & advance="no") "Roll: ", i, "Dice: ", & (dice(i,j), j=1,10) end do write (*,'(/,5x,a,i2)') "Point Count: ", pnt_cnt if (payout > 0) then write (*,'(5x,a,i2)') & "Game Result: WIN Payout = ", payout else write (*,'(5x,a,i2)') & "Game Result: LOSS Payout = ", payout end if write (*,'(5x,a,i6)') "Bank:", bank return end subroutine twentySix
The spacing and indentation are not required, but help to make the program more readable.
Test/Debug the Program
For this problem, the testing would involve executing the program using a file with a set of numbers where the correct results are either known ahead of time or can be calculated by hand in order to verify that the results are accurate.
- For more information, see: http://www.dice-play.com/Games/TwentySix.htm