#! /usr/bin/env python3 # def snakes_and_ladders_simulation_test ( ): #*****************************************************************************80 # ## snakes_and_ladders_simulation_test() tests snakes_and_ladders_simulation(). # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 07 December 2022 # # Author: # # John Burkardt # import platform print ( '' ) print ( 'snakes_and_ladders_simulation_test():' ) print ( ' Python version: ' + platform.python_version ( ) ) print ( ' Test snakes_and_ladders_simulation().' ) n = 1000 snakes_histogram ( n ) # # Terminate. # print ( '' ) print ( 'snakes_and_ladders_simulation_test():' ) print ( ' Normal end of execution.' ) return def snakes_histogram ( n ): #*****************************************************************************80 # ## snakes_histogram() makes a game-length histogram for Snakes and Ladders. # # Discussion: # # For histograms, we plot the raw data, whereas for bar charts, we # plot the tallies. # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 07 December 2022 # # Author: # # John Burkardt # # Input: # # integer N, the number of games to play. # import matplotlib.pyplot as plt import numpy as np print ( '' ) print ( 'snakes_histogram():' ) print ( ' Simulate N one-player games of Snakes and Ladders.' ) print ( ' Use the simulation data to create histograms' ) print ( ' of the estimated PDF and CDF of the game length.' ) # # Simulate N games. # steps = np.zeros ( n ) for game in range ( 0, n ): steps[game] = snakes_one_game ( ) # # Report data. # print ( '' ) print ( ' Number of trials was n = ', n ) print ( ' Minimum number of steps was', np.min ( steps ) ) print ( ' Mean number of steps was ', np.mean ( steps ) ) print ( ' Maximum number of steps was', np.max ( steps ) ) print ( ' Standard deviation was ', np.std ( steps ) ) # # Histogram the PDF. # plt.clf ( ) nbins = 21 plt.hist ( steps, bins = nbins, density = True ) plt.grid ( True ) plt.title ( 'Game length PDF for ' + str ( n ) + ' Games of Snakes and Ladders' ) filename = 'snakes_pdf.png' print ( ' Graphics saved as "' + filename + '"' ) plt.savefig ( filename ) # # Histogram the CDF. # plt.clf ( ) nbins = 21 plt.hist ( steps, bins = nbins, density = True, cumulative = True ) plt.grid ( True ) plt.xlabel ( 'Game length' ) plt.ylabel ( 'CDF' ) plt.title ( 'Game length CDF for ' + str ( n ) + ' Games of Snakes and Ladders' ) filename = 'snakes_cdf.png' print ( ' Graphics saved as "' + filename + '"' ) plt.savefig ( filename ) return def snakes_ladder_setup ( ): #*****************************************************************************80 # ## snakes_ladder_setup() defines the snakes and ladders for the game. # # Discussion: # # The two vectors could be merged into one. # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 07 December 2022 # # Author: # # John Burkardt # # Output: # # integer SNAKE(101), LADDER(101), define the snakes and # ladders. If a player lands on square I, then if SNAKE(I) is not I, # the player is immediately moved to a previous square whose index # is SNAKE(I). Similarly, if LADDER(I) is not I, then player is # immediately taken to a later square whose index is LADDER(I). # import numpy as np ladder = list ( range ( 0, 101 ) ) ladder[1] = 38 ladder[4] = 14 ladder[9] = 31 ladder[21] = 42 ladder[28] = 84 ladder[36] = 44 ladder[51] = 67 ladder[71] = 91 ladder[80] = 100 snake = list ( range ( 0, 101 ) ) snake[16] = 6 snake[48] = 26 snake[49] = 11 snake[56] = 53 snake[62] = 19 snake[64] = 60 snake[87] = 24 snake[93] = 73 snake[95] = 75 snake[98] = 78 return snake, ladder def snakes_move ( i, snake, ladder ): #*****************************************************************************80 # ## snakes_move() takes one move in a game of Snakes and Ladders. # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 07 December 2022 # # Author: # # John Burkardt # # Input: # # integer I, the current location. # # integer SNAKE(101), LADDER(101), define the snakes and # ladders. If a player lands on square I, then if SNAKE(I) is not I, # the player is immediately moved to a previous square whose index # is SNAKE(I). Similarly, if LADDER(I) is not I, then player is # immediately taken to a later square whose index is LADDER(I). # # Output: # # integer I, the current location. # # integer D, the value of the die roll, between 1 and 6. # from numpy.random import default_rng rng = default_rng ( ) # # Roll the die. # d = rng.integers ( low = 1, high = 6, endpoint = True ) # # Move from I to I + D. # i = i + d # # Your position can't exceed 100. # i = min ( i, 100 ) # # If we landed on a snake, we slide down. # i = snake [ i ] # # If we landed on a ladder, we climb up. # i = ladder [ i ] return i, d def snakes_one_game ( ): #*****************************************************************************80 # ## snakes_one_game() plays Snakes and Ladders once. # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 07 December 2022 # # Author: # # John Burkardt # # Output: # # integer STEP: the number of steps required for a random simulated # one-player game of Snakes and Ladders. # # # Define the snakes and ladders. # snake, ladder = snakes_ladder_setup ( ) # # Begin the simulation. # step = 0 i = 0 while ( i < 100 ): step = step + 1 i, d = snakes_move ( i, snake, ladder ) return step def timestamp ( ): #*****************************************************************************80 # ## timestamp() prints the date as a timestamp. # # Licensing: # # This code is distributed under the MIT license. # # Modified: # # 21 August 2019 # # Author: # # John Burkardt # import time t = time.time ( ) print ( time.ctime ( t ) ) return if ( __name__ == '__main__' ): timestamp ( ) snakes_and_ladders_simulation_test ( ) timestamp ( )