CS21 Lab 4: while loops and functions

Due Saturday, October 6, before midnight


Make sure all programs are saved to your cs21/labs/04 directory. Files outside this directory will not be graded.

$ update21
$ cd ~/cs21/labs/04/

Programming Tips

Topics for this assignment


1. Guess my Number

Write a program, guess.py, that allows the user to guess a secret number. First use the random module to pick a random (secret) number between 1 and 20 (inclusive). If their guess is below the secret number, print Too low!, and if their guess is above the secret number, print Too high!.

$ python3 guess.py
Enter your guess: 15
Too low!
Enter your guess: 18
Too high!
Enter your guess: 17
Too high!
Enter your guess: 16
You guessed it in 4 guesses!

$ python3 guess.py
Enter your guess: 20
Too high!
Enter your guess: 1
Too low!
Enter your guess: 4
Too low!
Enter your guess: 8
Too low!
Enter your guess: 12
Too high!
Enter your guess: 2
Too low!
Enter your guess: 10
Too low!
Enter your guess: 15
Too high!
Enter your guess: 12
Too high!
Enter your guess: 11
You guessed it in 10 guesses

Hint: define a boolean variable that keeps track of whether or not the secret number has been "guessed". In your while statement, you can use this variable to check whether you should break out of the loop!

Hint: use randrange() from the random module to generate your number. Make sure that randrange returns the full range from 1 to 20 inclusive!

For this question, implement your solution in a main() function.


Blackjack

For the remainder of this assignment, you will be implementing functions for a game similar to Blackjack. Please read through the whole writeup before starting.

In this game, two players compete to get as close to 21 as possible, without going over. Both players start with a total of zero. Each turn, the players must decide whether to "Hit" or "Stand". If a player chooses to "Hit", the computer will pick a random value to add to their total. This random value should be chosen from the following sequence of numbers:

cards = [1,2,3,4,5,6,7,8,9,10,10,10,10,11]

[Hint: You can use random.choice(cards) to choose a value from cards]

If a player chooses to "Stand", nothing happens and their total stays the same. If a player goes over 21, they BUST and lose the game. If they get exactly 21, they win. If they both have values under 21, the player with the higher total wins.

In this assignment, you will implement a computer player, called the dealer, and (optionally) a human player, called the user. The user can choose to "Hit" or "Stand" however they like. However, the dealer must play according to strict rules.

The next questions will ask you to implement the following:

The first two questions ask you to write a single function outside of the context where they would be used. To test them, we will call them from main() using test values. Testing functions with known inputs and outputs is called unit testing. If a unit test doesn't produce the correct output, we know there is a bug in our function!

2. To "Hit" or to "Stand"? This is the question

Complete the program, choice.py, that asks a user to choose whether to "Hit" or "Stand". If the user specifies something other than "Hit" or "Stand", the program should print an error and ask the user again.

Implement a function getChoice to ask the user for their decision.

getChoice

To test, we call getChoice() from main() and print the returned string.

 $ python3 choice.py
 What would you like to do? Hit or Stand? dance
 Sorry, unrecognized command: dance
 What would you like to do? Hit or Stand? Dance!
 Sorry, unrecognized command: Dance!
 What would you like to do? Hit or Stand? DANCE!
 Sorry, unrecognized command: DANCE!
 What would you like to do? Hit or Stand? ok, hit?
 Sorry, unrecognized command: ok, hit?
 What would you like to do? Hit or Stand? Stand
 The player selected:  Stand

3. Dealer Decision

Complete the program, decision.py, which simulates a dealer's turn. Recall that the dealer starts with a total of 0 and must play by strict rules:

If the dealer choses to "Hit", they get a random number from the following sequence of cards.

cards = [1,2,3,4,5,6,7,8,9,10,10,10,10,11]

[Hint: You can use random.choice(cards) to choose a value from cards]

If the dealer stands, nothing happens and the total stays the same.

Implement a function, doDealerTurn, which decides whether to hit or stand based on the dealer's current total.

doDealerTurn

To test, we call doDealerTurn from main() with the values 1, 17, 19, and 21.

Using a random seed

Testing with random values is very difficult because we get slightly different output each time we run. However, if we set a random seed, the random module will generate the same numbers every time. The code below shows how we can set a random seed in main() before we run our unit tests.

   def main():
      random.seed(0) # Set the seed to 0

The following output was generated with random.seed(0)

$ python3 decision.py
--- First Test ---
The dealer has total 1
The dealer HITS and draws 11
Value returned by doDealerTurn: 11

--- Second Test ---
The dealer has total 17
The dealer HITS and draws 7
Value returned by doDealerTurn: 7

--- Third Test ---
The dealer has total 19
The dealer STANDS
Value returned by doDealerTurn: 0

--- Fourth Test ---
The dealer has total 21
The dealer STANDS
Value returned by doDealerTurn: 0

4. Blackjack Dealer - Solo Edition

Write a program dealer.py that simulates a dealer playing our Blackjack game. In the previous question, you implemented doDealerTurn. Copy your function to dealer.py. In this question, you will implement a new function, called checkGameOver which determines whether the dealer stands, wins, or goes BUST.

checkGameOver

Write a main() which implements a game loop. In main(), you should also keep track of the dealer's total score and the number of turns. The game loop should quit when checkGameOver() returns True. Each turn, you should update the dealer's score by calling doDealerTurn().

To test your program, set different seeds and make sure you can replicate the output below.

The following output was generated with random.seed(0).

 $ python3 dealer.py
 -------------
 Turn 1
 -------------
 The dealer has total 0
 The dealer HITS and draws 11
 
 -------------
 Turn 2
 -------------
 The dealer has total 11
 The dealer HITS and draws 7
 The dealer can only STAND (18).

The following output was generated with random.seed(1)

 $ python3 dealer.py
 -------------
 Turn 1
 -------------
 The dealer has total 0
 The dealer HITS and draws 3
 
 -------------
 Turn 2
 -------------
 The dealer has total 3
 The dealer HITS and draws 10
 
 -------------
 Turn 3
 -------------
 The dealer has total 13
 The dealer HITS and draws 11
 The dealer went BUST (24).

The following output was generated with random.seed(4)

 $ python3 dealer.py
 -------------
 Turn 1
 -------------
 The dealer has total 0
 The dealer HITS and draws 4
 
 -------------
 Turn 2
 -------------
 The dealer has total 4
 The dealer HITS and draws 5
 
 -------------
 Turn 3
 -------------
 The dealer has total 9
 The dealer HITS and draws 2
 
 -------------
 Turn 4
 -------------
 The dealer has total 11
 The dealer HITS and draws 10
 The dealer wins (21).

(Extra challenge) Blackjack: Dealer vs. Human

Write a program, blackjack.py, that allows a person to play against a dealer. Begin by copying dealer.py to blackjack.py.

This challenge builds on the features you implemented in the previous three questions. In this version, both a player and the dealer makes a decision to "Hit" or "Stand" each turn. Your program should ask the player what they want to do using the function getChoice(). Your program should use doDealerTurn to implement the dealer's turn.

Implement a function doUserTurn to perform the user's turn.

doUserTurn

Additionally, modify checkGameOver to handle new win conditions

checkGameOver

The game can end in the following ways:

In main(), you should keep track of the user total, the dealer total, and the number of turns. As before, you should implement a game loop which exits when checkGameOver is True. Each turn, you should call doDealerTurn and doUserTurn to update the totals for each.

The following was generated with random.seed(0)

 $ python3 blackjack.py
 -------------
 Turn 1
 -------------
 The dealer has total 0
 The dealer HITS and draws 11
 You have total 0
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 7
 
 -------------
 Turn 2
 -------------
 The dealer has total 11
 The dealer HITS and draws 10
 The dealer wins (21).
 

The following was generated with random.seed(1)

 $ python3 blackjack.py
 -------------
 Turn 1
 -------------
 The dealer has total 0
 The dealer HITS and draws 3
 You have total 0
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 10
 
 -------------
 Turn 2
 -------------
 The dealer has total 3
 The dealer HITS and draws 11
 You have total 10
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 10
 
 -------------
 Turn 3
 -------------
 The dealer has total 14
 The dealer HITS and draws 10
 The dealer went BUST (24). You win (20)!

The following was generated with random.seed(2)

 $ python3 blackjack.py
 -------------
 Turn 1
 -------------
 The dealer has total 0
 The dealer HITS and draws 11
 You have total 0
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 11
 
 -------------
 Turn 2
 -------------
 The dealer has total 11
 The dealer HITS and draws 1
 You have total 11
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 2
 
 -------------
 Turn 3
 -------------
 The dealer has total 12
 The dealer HITS and draws 2
 You have total 13
 What would you like to do? Hit or Stand? Stand
 You STAND
 
 -------------
 Turn 4
 -------------
 The dealer has total 14
 The dealer HITS and draws 6
 You have total 13
 What would you like to do? Hit or Stand? Stand
 You STAND
 
 -------------
 Turn 5
 -------------
 The dealer has total 20
 The dealer STANDS
 You have total 13
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 11
 You went BUST (24)! The dealer wins (20).

The following was generated with random.seed(5)

 $ python3 blackjack.py
 -------------
 Turn 1
 -------------
 The dealer has total 0
 The dealer HITS and draws 10
 You have total 0
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 5
 
 -------------
 Turn 2
 -------------
 The dealer has total 10
 The dealer HITS and draws 10
 You have total 5
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 6
 
 -------------
 Turn 3
 -------------
 The dealer has total 20
 The dealer STANDS
 You have total 11
 What would you like to do? Hit or Stand? Hit
 You HIT and draw 10
 You win! (21)

5. Answer the Questionnaire

Each lab has a short questionnaire at the end. Please edit the QUESTIONS-04.txt file in your cs21/labs/04 directory and answer the questions in that file.


Turning in Your Labs

Don't forget to run handin21 to turn in your lab files! You may run handin21 as many times as you want. Each time it will turn in any new work. We recommend running handin21 after you complete each program or after you complete significant work on any one program.