Creating a dice game in Python (part 3)

In this post we continue developing a dice game in Python.

  • In Iteration 1 we coded a single round of the dice game for one player.
  • In Iteration 2 we added an additional loop so that multiple rounds were completed until the target score is reached.

Iteration 3

For this iteration we add a second player to the game. A high-level design for the revised game is shown below.

set target
set score1 to 0
set score2 to 0

while score1 < target and score2 < target
   player1 completes their turn
   update score1
   player2 completes their turn
   update score2
end while

output winner and scores

In the algorithm above, if player 1 reaches the target score, then player 2 will also get a turn before the loop terminates. However, the game should terminate as soon as one player reaches the target score. Another issue that we need to consider is ensuring that the amount of repeated code is minimised. A literal interpretation of the pseudocode above can lead to repeated code which we should avoid.

We improve the algorithm by adding a current player counter to keep track of who the current player is.

set target
set score1 to 0
set score2 to 0
set current_player to 1

while score1 < target and score2 < target
   current_player completes their turn
   if current_player = 1
   then
      update score1
      set current_player to 2
   else
      update score2
      set current_player to 1
   end if
end while

output winner and scores

After refining the algorithm to reduce the amount of repeated code we implement the algorithm in Python.
The first part of the code, as shown below, includes the necessary package imports together with variable initialisations. The variable current_player is used to track which player has the current turn. Initially this has a value of 1 (for player one) and will alternate between 1 and 2 until the game is complete.

import random
import time

target = 200
score1 = 0
score2 = 0
current_player = 1

The next block of code contains the main control loop and code for running the current player's round. The condition for the control loop (highlighted in the code listing) checks whether both scores are below the target score. The next line of code provides an indication of who the current player is.

while score1 < target and score2 < target:
    print("Player", current_player, "turn")
    round_score = 0
    valid = True
    while valid:
        roll1 = random.randint(1, 6)
        roll2 = random.randint(1, 6)
        total = roll1 + roll2
        if total == 7:
            valid = False
            print(total)
        else:
            round_score = round_score + total
            print(total, end=", ")
    print("You scored", round_score, "this round")

The block of code starting at line 23 is responsible for printing the total score of the current player and then updating the value of the current player before the while loop runs again. The code includes a conditional statement that checks who the current player is. Note that the code in the two branches of the condition block are very similar. This provides further opportunities for improving (refactoring) the code to reduce repetition. This is explore in the next part of the tutorial where we generalise to any number of players.

    if current_player == 1:
        score1 = score1 + round_score
        print("Total score for player 1 is", score1)
        current_player = 2
    else:
        score2 = score2 + round_score
        print("Total score for player 2 is", score2)
        current_player = 1
    time.sleep(1)

The final block of code outputs the winner of the game together with the final score. The winner is determined by comparing the scores of the two players within an if statement condition.

if score1 > score2:
    print("Player 1 wins", score1, "to", score2)
else:
    print("Player 2 wins", score2, "to", score1)

Example output that is generated when the code is run is shown below. Note that for brevity the output has been elided with only the first three and last round shown.

Player 1 turn
9, 10, 11, 6, 7
You scored 36 this round
Total score for player 1 is 36
Player 2 turn
2, 8, 10, 7
You scored 20 this round
Total score for player 2 is 20
Player 1 turn
6, 5, 9, 6, 9, 11, 10, 6, 9, 7
You scored 71 this round
...
Player 2 turn
11, 8, 11, 4, 6, 6, 5, 10, 5, 9, 7
You scored 75 this round
Total score for player 2 is 234
Player 2 wins 234 to 154

Creating a dice game in Python (part 2)

Iteration 2

In the second iteration of the development of Seven Out we add an outer loop so that the game will continue until the player’s total score equals or exceeds the target score – in this case 200. In the pseudocode shown below the outer loop is modelled as a while loop with a condition to check whether the target score has been met. The algorithm used inside of the outer loop is the same as that used in iteration 1 except a new variable is used to keep track of the score for the current round.


set target to 200
set score to 0
while score < target
   set round_score to 0
   loop
      set total to sum of two random integers between 1 and 6
      if total = 7
      then
         exit loop
      else
         add total to round_score
      end if
    end loop
    output round_score
end while
output score

The code written for this iteration is similar to that from iteration 1. New lines of code are highlighted in the listing below. Line 6 contains a while loop with a condition that checks that the score is less than the target. The while loop will continue while
this condition is true. In particular this while loop will always run at least once. Line 7 creates a new variable to represent the score for the current round - the value for this variable is reset to zero each time the outer loop is repeated. Line 17 updates the round score by adding the current dice total. Note that when a total of 7 is rolled this is not added to the round score.

import random

target = 200
score = 0

while score < target:
    round_score = 0
    valid = True
    while valid:
        roll1 = random.randint(1, 6)
        roll2 = random.randint(1, 6)
        total = roll1 + roll2
        if total == 7:
            valid = False
            print(total)
        else:
            round_score = round_score + total
            print(total, end=", ")
    score = score + round_score
    print("You scored", round_score, "this round")
    print("Total score is", score)

print("Well done. You got to", target)

Line 18 of the code uses an option within the print statement to alter its behaviour. The end option will by default print a newline character at the end of the output, meaning that subsequent output will appear on a new line. In this case we replace the default behaviour and instead end with a comma followed by a space. This means all of the totals for a round will be printed out on one line.

Output generated by running the game is shown below. For each round a list of comma-separated dice totals are shown, followed by the total for that round and then the total score. At the end of the game the player's total is shown.

8, 2, 3, 8, 2, 4, 9, 7
You scored 36 this round
Total score is 36
9, 5, 8, 10, 7
You scored 32 this round
Total score is 68
7
You scored 0 this round
Total score is 68
2, 9, 5, 11, 4, 4, 10, 6, 11, 11, 3, 4, 7
You scored 80 this round
Total score is 148
3, 6, 9, 7
You scored 18 this round
Total score is 166
6, 5, 5, 4, 7
You scored 20 this round
Total score is 186
8, 6, 4, 3, 6, 6, 7
You scored 33 this round
Total score is 219
Well done. You got to 200