Introduction

This document describes the second assignment for Problem Solving and Programming.

The assignment is intended to provide you with the opportunity to put into practice what you have learnt in the course by applying your knowledge and skills to implement a game of Blackjack and then extending the program to keep a record of the players who achieve high scores while playing.

This assignment is an individual task that will require an individual submission. You will be required to present your work to your practical supervisor during your practical session held in Week 12 of the study period. Important: You must attend the practical session that you have been attending all study period in order to have your assignment marked.

This document is a kind of specification of the required end product that will be generated by implementing the assignment. Like many specifications, it is written in English and hence will contain some imperfectly specified parts. Please make sure you seek clarification if you are not clear on any aspect of this assignment.

Assignment Overview

There are two parts to this assignment:

Part I: Implement a game of Blackjack

You are required to write a Python program that allows a player to play a game of Blackjack against the computer. The program will allow a player to play as many games of Blackjack as they wish.

Part II: High scores player information

You are required to extend your Python program (from part I) that will keep a record of the players who achieve high scores while playing. The program will allow players to play blackjack against the computer and will maintain information on high scoring players (using Lists). Player information will be stored in a text file that will be read in when the program commences. Once the initial high scores data has been read in from the file, the program should allow the user to interactively query and manipulate the high scores information as well as play blackjack against the computer. Please ensure that you read sections titled 'Part II specification below for further details.

Blackjack Rules

Blackjack is a popular card game where the goal is to beat the dealer by having the higher hand which does not exceed 21 https://en.wikipedia.org/wiki/Blackjack.

Although there are many variations of the rules and game play, we will be adhering to the following rules and game play for the assignment.

Blackjack hands are scored by their point total, calculated by adding together the face values of each card dealt. The hand with the highest total wins, as long as it doesn't exceed 21. A hand with a higher total than 21 is said to bust. Being dealt an Ace (of any suit) counts as eleven (11) points unless this would cause the player to bust, in which case it is worth one (1) point. Picture cards (King, Queen and Jack) are all worth 10 points. All other cards are worth their numerical value shown on the card.

Game play:

  • To begin, the player and the dealer are dealt an initial hand of two cards each (this part is handled by the GUI).
  • If the dealer has Blackjack (the first two cards dealt total 21 points) and the player does not, the dealer auto- matically wins.
  • If the player has Blackjack (the first two cards dealt total 21 points) and the dealer does not, the player automat- ically wins.
  • If both the player and the dealer have Blackjack (the first two cards dealt total 21 points) then it is a push (draw).
  • If neither have Blackjack, then the player plays out his/her hand. Note that the term Blackjack can only be achieved as a result of the first two cards dealt.
  • When the player has finished playing out his/her hand, the dealer (in this case the computer) plays out the dealer's hand.
  • During the player's turn, the player is faced with two options either:
    • Hit (take a card): After the initial deal of two cards, a player may choose to receive additional cards as many times as he/she wishes, adding the point value of each card to his/her hand total.
    • Stand (end their turn): Do not receive any more cards. The player's turn is over.
  • The player repeatedly takes a card until, the player chooses to stand, or the player busts (that is, exceeds a total of 21). The player's turn is over after deciding to stand or if he/she busts.
  • Once the player has finished, the dealer plays out his/her hand (in this case the computer), revealing the hidden second card amount. Note: the dealer always plays his/her hand regardless of what happens with the player's hand. The dealer must hit until he or she has a point value of 17 or greater.

Rules

  • If the player busts, he/she loses even if the dealer also busts.
  • If the player and the dealer have the same point value, it is called a 'push' and neither win the hand (draw).
  • An initial two-card deal of 21 (an 11 plus a 10) is called Blackjack (i.e. an 11 plus a 10 is dealt as the very first hand) and wins the round automatically.
  • An Ace counts as eleven (11) points unless this would cause the player/dealer to bust, in which case it is worth one (1) point.
  • House rules:
    • The dealer must hit until he or she has a point value of 17 or greater.
    • The player can not stand on a point value less than 15
  • The player with the higher hand that does not exceed 21 wins the game!

You do not have to write the code that deals one card at a time, a module containing the function that does that for you has been provided. The playing_cards.py file is a module that contains a function called deal_one_card() that deals one card at a time for you. The function returns a string (containing two characters) that represents a card; the first letter represents the face value of the card and the second letter represents the suit. For example: it may return the two character string 'AH', where A represents Ace and H represents Hearts; TC, where T represents Ten and C represents Clubs, 7S, where 7 represents the card value of 7 and S represents Spades, etc. You are required to use this as part of this assignment, however, please do not modify the playing_cards.py file. There are other functions within the module that create the playing deck, and shuffle it, but you do not have to worry about those functions, you only have to make use of the deal_one_card() function in your solution, the other functions will take care of the rest for you!

Part 1 Specification: Blackjack

You are required to write a program that plays the game of Blackjack. This file is provided for you (on the course website) however, you will need to modify this file by writing code that implements the functions listed below. Please read the slides on functions available on the course website if you would like more information on functions.

Your are required to implement a Python program that contains the following functions:

display_details()

This function takes no parameters and does not return any values. The function displays your details to the screen. Remember that defining the function does not execute the function - you will need to call the function from the appropriate place in the program. Your function should produce the following output (with your details) to the screen:

File: wayby001.py
Author: Batman
Stud ID: 0123456X
Email ID : wayby001
This is my own work as defined by the University’s Academic Misconduct Policy.

get_hand_total(hand)

This function accepts as a parameter a list of strings (containing the cards dealt) and calculates the point value of the hand. The function returns the total point value of the hand. For example:

If the player_hand list is as follows:

player_hand = ['4D', 'TS', 'KD']

. . . calling the get_hand_total() function like so:

card_total = get_hand_total(player_hand)

. . . will return the integer value 24 and assign it to the variable card_total.

If the dealer_hand list is as follows:

dealer_hand = ['KS', '9C']

. . . calling the get_hand_total() function like so:

card_total = get_hand_total(dealer_hand)

. . . will return the integer value 19 and assign it to the variable card_total.

get_card_suit(card)

This function accepts as a parameter a string (representing the value and suit of a single card). The function returns the suit of the card

For example, calling get_card_suit() as follows:

card_suit = get_card_suit('4D)

. . . will return the string value Diamonds and assign it to the variable card_suit

diplay_hand(hand_text, hand)

This function takes a string (hand text) to display to the screen and a list of strings (hand) containing the cards dealt. The function does not return any values and displays the hand (list) to the screen in the following format, for example:

If the player_hand list is as follows:

player_hand = ['4D', 'TS', 'KD']

. . . calling the display_hand() function like so:

display_hand('\nPlayer\'s hand is', player_hand)

. . . will produce the following output to the screen:

Player's hand is 24: 4 of Diamonds | 10 of Spades | K of Diamonds

If the dealer_hand list is as follows:

dealer_hand = ['KS', '9C']

. . . calling the display_hand() function like so:

display_hand('\nDealer\'s hand is', dealer_hand)

. . . will produce the following output to the screen:

Dealer's hand is 19: K of Spades | 9 of Clubs

This function must call function get_hand_total(hand).

play_player_hand(player_hand)

This function accepts a list of strings (containing the cards dealt) and returns the total point value of the player's hand. The function plays out the players hand until the player either busts or chooses to stand. Do not let the player stand on a value less than 15.

play_dealer_hand(dealer_hand)

This function takes a list of strings (containing the cards dealt) and returns the total point value of thedealer's hand. The function plays out the dealers hand until the dealer has a point value of 17 or greater. Dis- play the dealer busts message if the dealer exceeds 21. The function must call the following functions: get_hand_total(), display_hand() and deal_one_card().

You must test your functions to ensure that they are working correctly. So you do not have to write your own test file, one has been provided for you. The assign2_partI_test_file.py file is a test file that contains code that calls the functions contained in the your_saibt_id_blackjack.py file. Please do not modify the test file.

Part 1 - Practical Requirements: Blackjack

A graphical user interface (GUI) has been provided for you. You do not have to write any code that generates the GUI-it should just help you visualise your logic and make the game a little more fun! The GUI is provided as a Python class BlackjackGUI in a module called blackjack_gui.py. You will import the module and use the provided methods1 in your program to control the GUI. Please do not modify blackjack_gui.py.

You will make use of the following provided methods and instance variables:

Methods

  • deal_one_card()
  • get_player_hand()
  • get_dealer_hand()
  • set_player_hand_total(player_card_total)
  • set_dealer_hand_total(dealer_point_total)
  • reject_player_stand_request()
  • player_blackjack()
  • dealer_blackjack()
  • player_busted()
  • dealer_busted()
  • player_stand()
  • dealer_stand()
  • has_player_busted()
  • has_dealer_busted()
  • display_dealer_card(card)
  • draw()
  • increment_wins()
  • increment_losses()
  • is_dealer_standing()

Instance variable: player_turn

It is recommended that you develop this assignment in the suggested stages.

It is expected that your solution WILL include the use of the following:

  • Your solution in a file called your_saibt_id_blackjack.py.
  • The supplied playing_cards.py module (containing the deal_one_card() function). This is provided for you - please DO NOT modify this file.
  • The deal_one_card() function (provided in the supplied playing_cards.py module).
  • Appropriate and well constructed while and/or for loops (as necessary).
  • Appropriate if, if-else, if-elif-else statements (as necessary).
  • List of strings to represent the player's hand, i.e. player_hand = []
  • List of strings to represent the dealer's hand, i.e. dealer_hand = []
  • Functions (display_details, get_card_suit, get_play_choice, display_hand, get_hand_total, play_player_hand, play_dealer_hand) implemented adhering to the assignment specifications.
  • Output that strictly adheres to the assignment specifications. If you are not sure about these details, you should check with the 'Sample Output' provided at the end of this document.
  • Good programming practice:
    • Consistent commenting, layout and indentation. You are to provide comments to describe: your details, program description, all variable definitions, and every significant section of code.
    • Meaningful variable names.

Your solutions MUST NOT use:

  • break, or continue statements in your solution. Do not use the quit() or exit() functions or the break or return statements (or any other techniques) as a way to break out of loops. Doing so will result in a significant mark deduction.

PLEASE NOTE: You are reminded that you should ensure that all input and output conform to the specifica- tions listed here; if you are not sure about these details you should check with the sample output provided at the end of this document or post a message to the discussion forum in order to seek clarification.

Please ensure that you use Python 3.6.0 or a later version (i.e. the latest version) in order to complete your assign- ments. Your programs MUST run using Python 3.6.0 (or latest version).

Part 1 - Stages

The following stages of development are recommended:

Stage 1 - Setting Up

First download the zip file "Assignment2.zip" from the course website and extract its contents. You should see a folder called 201902 PSP Assignment 2 with the following directory structure:

201902 PSP Assignment 2
|
|_images
|
|_blackjack_gui.py
|
|_your_saibt_id_blackjack.py

Step 1: Open the your_saibt_id_blackjack.py file and you should see the following provided code:

Listing 1: supplied code see image.

The game variable references an object of the BlackjackGUI class. Through it, using the dot notation, you can access the methods discussed in Part 1 Practical Requirements: Blackjack on page 5. This is the minimum required code to get the GUI up and running.

Note that the provided while loop is deliberately made to be infinitely True.

Step 2: Run the your_saibt_id_blackjack.py file. If this is working correctly, you should now see the following window appear:

Figure 1: Blackjack GUI see image.

Note that the cards displayed when you run your program are likely to be different! To reset the game board, simply re-run the your_saibt_id_blackjack.py file in IDLE.

At this stage there is not much that the GUI will do. If you continue to press the Hit button, the player will draw another card until they have drawn a maximum of 12 cards. This is because it is up to you to take control of the GUI! This includes:

  • Keeping track of and updating the player (and dealer's) hand total
  • Keeping track of and updating the current wins and losses
  • Handling events such as:
    • When the user tries to stand but does not have a hand total of 15 or more
    • When the player stands/busts
    • When the dealer stands/busts
    • Drawing cards for the dealer
    • Determining whether either player has blackjack

Step 3: The methods of the BlackjackGUI class provide a means for you to interact with it. Enter the following two lines of code into function main(). For now position the code after line 3 and before the while loop on line 8 as per Listing 2 below:

player_hand = game.get_player_hand()
print(player_hand)

Listing 2: Using dot notation to call method get_player_hand see image.

This will result in the following output in the IDLE shell:

['9D', '9H']
['9D', '9H']
['9D', '9H']
['9D', '9H']
['9D', '9H']
['9D', '9H']
...
...
...
['9D', '9H']
['9D', '9H']
['9D', '9H']
...and so on

Note your output will be different since the deck gets shuffled by the GUI.

For now we will set aside the GUI and instead focus on writing the code for the functions we need to develop the logic of our game.

Stage 2 - Implement Function display_details()

Implement your display_details() function. When called this function should output your details similar to the sample output shown below:

File: 123456789_blackjack.py
Author: Andy Jordan
Student ID: 123456789
Email ID: andreas.jordan
This is my own work as defined by the University's
Academic Misconduct Policy

Think about where the function should be declared in your file in accordance with the Python style guidelines. Also, if you only want it to print once and at the beginning of your program's execution, think about where you should call the function.

Do not define functions inside other functions!

Stage 3 - Implement Function get_hand_total()

Now it's time to write a function to calculate the hand total for a player. The function must accept only a single pa- rameter, i.e. hand, that is a list containing the cards in the players hand (note that this could be the player or dealer).

Implement the function called get_hand_total() - see description in Part 1 Practical Requirements: Blackjack on page 5.

Hint: Function get_hand_total(hand) should use a loop. Display the dealer's hand and the players hand to the screen as seen below. For example:

If the player_hand list is as follows,

player_hand = ['KH', '5C']

calling the get_hand_total(hand) function like so

player_total = get_hand_total(player_hand)

will assign the value of 15 to variable player_total.

If the dealer_hand list is as follows,

dealer_hand = ['TC', '7H']

calling the get_hand_total(hand)function like so

dealer_total = get_hand_total(dealer_hand)

will assign the value of 17 to variable dealer_total.

You can then use a simple print statement to display the player and dealer hand totals along with the lists to the screen as follows:

Sample output 1:

Player hand is: 15 ['KH', '5C']
Dealer hand is: 17 ['TC', '7H']

Sample output 2:

Player's hand is 15: K of Hearts | 5 of Clubs
Dealer's hand is 17: 10 of Clubs | 7 of Hearts

You may be wondering why you are going to write code that displays content in the IDLE Shell when you have a GUI?!? The answer is that the output that get's displayed in the IDLE Shell is putting into practice your thinking skills. You will have to use print, loops, if/elif/else and proper sequencing to correctly display both players hand (its also a useful debugging tool).

Stage 4 - Implement Function get_card_suit()

Before we tackle the display_cards() function we will write another function that will make things easier later on. If you take a look at the output that the display_hand() function produces (in the next stage), the letter represent- ing the suit of the card, i.e. 'D, C, S and H, displays as Diamonds, Clubs, Spades and Hearts respectively. The function get_card_suit() will handle this for us!

The function get_card_suit() accepts a single parameter, i.e., card, that is a string comprising a single card. The function must return a string.

For example:

If card = 'AH' calling the get_current_suit(card) function like so:

suit = get_current_suit(card)

will return the string 'Hearts and assign it to the variable suit

At this stage, it may be useful to take a closer look at how the list of cards in the deck are represented. In the BlackjackGUI class, there is a private variable called self.__deck and looks like this:

# Deck of cards - first letter represents the face value and
# second letter represents the suit
self.__deck = ['AH','2H','3H','4H','5H','6H','7H','8H','9H','TH','JH','QH','KH',
'AD','2D','3D','4D','5D','6D','7D','8D','9D','TD','JD','QD','KD',
'AS','2S','3S','4S','5S','6S','7S','8S','9S','TS','JS','QS','KS',
'AC','2C','3C','4C','5C','6C','7C','8C','9C','TC','JC','QC','KC']

As you can see, each card is composed of a 2-character string where the first character is the value of the card and the second character is the suit.

Step 1: Start by defining the function ensuring you do not forget the parameter, i.e. card. Also do not define this function inside any other function.

Step 2: Write code that accesses the second character of the string (this represents the suit of the card)

Step 3: Write code that checks if the second character is a 'D, C, S or H and returns the appropriate string, i.e., Diamonds, Clubs, Spades and Hearts.

Make sure the program runs correctly. Once you have that working, back up your program. Note: When developing software, you should always have fixed points in your development where you know your software is bug free and runs correctly.

Stage 5 - Implement function display_hand()

This function takes a string (hand text) to display to the screen and a list of strings (hand) containing the cards dealt. The function does not return any values and displays the hand (list) to the screen in the following format, for example:

If the player_hand list is as follows:

player_hand = ['4D', 'TS', 'KD']

. . . calling the display_hand() function like so:

display_hand('Player\'s hand is', player_hand)

. . . will produce the following output to the screen:

Player's hand is 24: 4 of Diamonds | 10 of Spades | K of Diamonds

If the dealer_hand list is as follows:

dealer_hand = ['KS', '9C']

. . . calling the display_hand() function like so:

display_hand('Dealer\'s hand is', dealer_hand)

. . . will produce the following output to the screen:

Dealer's hand is 19: K of Spades | 9 of Clubs

This function must call function get_hand_total(hand) and get_card_suit().

Step 1: Start by defining the function ensuring you do not forget the parameters, i.e. hand_text and hand. Also do not define this function inside any other function.

Step 2: To display the player's total card value, now is a good time to call get_hand_total()

Step 3: Set up a loop to iterate through the list of cards

Step 4: For each card, use slicing to access the card value and call get_card_suit() to return the suit of each card.

Hint: Function display_hand(hand_text, hand) should use a loop and call the get_hand_total() and get_card_suit() function. Display the dealer's hand and the players hand to the screen as seen above.

Stage 6 - Implement function play_player_hand()

Okay, now let's write the function to play out the players hand. This function accepts a game object and returns the total point value of the players hand. The function plays out the players hand until the player either busts or chooses to stand. Do not let the player stand on a value less than 15.

At this stage, we need to talk about the GUI. The player uses the GUI to indicate whether they wish to Hit or Stand. When a player presses the Hit button, a card is automatically drawn, displayed in the GUI and more importantly added to a list stored inside the class. You can access the list at any time using the method get_player_hand(). For example:

player_hand = game.get_player_hand()

In this stage you will need to take into consideration the following possible game states:

  • If the player has Blackjack, i.e. a hand total of 21 on the player's first two cards. When this occurs you should call the method player_blackjack()
  • If the player has busted, i.e. a hand total greater than 21. When this occurs you should call the method player_busted()
  • If the player has pressed the Stand button. When this occurs you will need to check if the player's hand total is less than 15 and if so you should call the method reject_player_stand_request()

Step 1: Begin by defining the function ensuring you do not forget the parameter, i.e. game.

Step 2: To play out the player's hand, it is important to keep track of the following:

  • The current cards the player has (you will need to call the appropriate method and remember to assign it to a suitably named variable).
  • The current card total of the player (so again call the appropriate method and remember to assign that to a suitably named variable also).

Step 3: Since we are playing out the player's hand, you should call (not define) the function display_hand() and the appropriate method to update the players hand total in the GUI.

Remember that you will need to update the GUI for each of the different possible out- comes. . . by calling the appropriate method! You must use the dot notation as shown in section Description Of blackjackGUI.py Module on Page 29.

The while loop in the function main will continuously call the play_player_hand() function, so do not be surprised when your print statement(s) continuously display to the IDLE shell.

Sample output:

Player's hand is 17 : Q of Diamonds | 7 of Clubs
Player's hand is 17 : Q of Diamonds | 7 of Clubs
Player's hand is 17 : Q of Diamonds | 7 of Clubs
Player's hand is 17 : Q of Diamonds | 7 of Clubs
Player's hand is 17 : Q of Diamonds | 7 of Clubs
Player's hand is 19 : Q of Diamonds | 7 of Clubs | 2 of Clubs
Player's hand is 19 : Q of Diamonds | 7 of Clubs | 2 of Clubs
Player's hand is 19 : Q of Diamonds | 7 of Clubs | 2 of Clubs
Player's hand is 19 : Q of Diamonds | 7 of Clubs | 2 of Clubs
Player's hand is 19 : Q of Diamonds | 7 of Clubs | 2 of Clubs
Player's hand is 19 : Q of Diamonds | 7 of Clubs | 2 of Clubs

Stage 7 - Implement function play_dealers_hand()

Okay, now let's write the function to play out the dealers hand. This stage is a little different to the implementation for the players hand. You are responsible for drawing cards for the dealer. This function accepts a game object and returns the total point value of the dealers hand. The function plays out the dealers hand until the dealer has a point value of 17 or greater. The function must call the following functions: get_hand_total(), display_hand() and deal_one_card().

Once again you will need to take into consideration the following possible game states:

  • If the dealer has Blackjack, i.e. a hand total of 21 on the dealer's first two cards. When this occurs you should call the method dealer_blackjack()
  • If the dealer has busted, i.e. a hand total greater than 21. When this occurs you should call the method dealer_busted()

Step 1: Start by defining the function ensuring you do not forget the parameter, i.e. game. Also do not define this function inside any other function.

Step 2: Now let's add a loop which simulates the computers turn. That is, plays out the dealers (computers) hand. Think about the condition the while loop should have. Hint - you must keep drawing cards until the dealer has at least 17 or busts.

To play out the dealer's hand, it is important to keep track of the following:

  • The current cards the dealer has (you will need to call the appropriate method and remember to assign it to a suitably named variable).
  • The current card total of the player (so again call the appropriate method and remember to assign that to a suitably named variable also).
  • If the dealer has a hand total greater than or equal to 17 the dealer must stand.

Step 3: Since we are playing out the dealer's hand, you should call (not define) the function display_hand() here also.

Remember that after you draw a card for the dealer you will need to call the appropriate method to display the dealer card in the GUI.

Stage 8 - Implement function main()

Now it is time to complete function main(). The main function is where you will handle the following:

  • Prompting the user if they wish to play Blackjack
  • Prompting the user to enter their name (provided they enter 'y' to play!)
  • Calling function play_player_hand()
  • Calling function play_dealer_hand()
  • Checking the status of the game which involves:
    • Checking if either player has Blackjack
    • Checking if either player has busted
    • Checking which player has the highest hand (i.e. card value of hand closest to 21)

Before we begin completing the function main(), let's discuss what has been supplied to you and what is still required to be done to provide the full functionality of the game. The code provided creates an instance of the BlackjackGUI class (see line 6 below). For each iteration of the loop, the try statement attempts to update the GUI (see lines 13-16). The print() statement on Line 10 will need to be removed with your code. The last two lines simply call the function main() when you run your program.

The following code has been provided:

Listing 3: Supplied code in file your_saibt_id_blackjack.py see image.

You will need to place your own code inside the existing if statement. So as stated above, when you know what you have to write, replace the existing print statement with your own code (which will include print() statements. . . ).

Speaking of print() statements, apart from displaying each player's cards in the console, you are also required to determine the winner and display the results to the screen (as well as to the GUI!).

You will need to check all conditions. As this can get rather confusing, you have been supplied an algorithm (see Listing 1) that if followed correctly will allow you to check all needed conditions.

The possible outcomes of each game are listed in Table 1 below:

Table 1: Possible outcomes fo each game see image.

Determine Winner

The output below is what you are expected to print to the IDLE Shell. You will still need to call the appropriate methods in the BlackjackGUI class to keep the game state in the GUI up-to-date.

Sample output 1:

Dealer's hand is 10: K of Hearts
Player's hand is 20: A of Clubs | 9 of Diamonds
Please enter h or s (h = Hit, s = Stand): s
Dealer's hand is 20: K of Hearts | 10 of Hearts
---> Dealer: 20 Player: 20 -> Push - no winners! <---

Sample output 2:

Dealer's hand is 10: K of Spades
Player's hand is 16: Q of Diamonds | 6 of Clubs
Please enter h or s (h = Hit, s = Stand): s
Dealer's hand is 20: K of Spades | Q of Hearts
---> Dealer: 20 Player: 16 -> Dealer Wins! <---

Sample output 3:

Dealer's hand is 11: A of Spades
Player's hand is 11: 6 of Diamonds | 5 of Diamonds
Please enter h or s (h = Hit, s = Stand): h
Player's hand is 19: 6 of Diamonds | 5 of Diamonds | 8 of Diamonds
Please enter h or s (h = Hit, s = Stand): s
Dealer's hand is 14: A of Spades | 3 of Diamonds
Dealer's hand is 17: A of Spades | 3 of Diamonds | 3 of Hearts
---> Dealer: 17 Player: 19 -> Player Wins! <---

Stage 9 - Match Sample Output

Finally, check the sample output (see section titled 'Sample Output' towards the end of this document) and if neces- sary, modify your code so that:

  • The output produced by your program EXACTLY adheres to the sample output provided.
  • Your program behaves as described in these specs and as the sample output provided.

It should go without saying that you will need to call the appropriate methods in the Blackjack- GUI class in order to update the Wins/Losses/Draws in the GUI.

Part 2 Specification - High Scores Information

Write a menu driven program called yourSAIBTId_highscores.py that will allow the user to enter commands and process these commands until the quit command is entered. The program will keep a record of the players who achieve high scores while playing rock, paper, scissors. The program will allow players to play rock, paper, scissors against the computer and will maintain information on high scoring players (using Lists). Player information will be stored in a text file that will be read in when the program commences. Once the initial high scores data has been read in from the file, the program should allow the user to interactively query and manipulate the high scores information as well as play rock, paper, scissors against the computer.

Input

When your program begins, it will read in player information from a file called high_scores.txt. This is a text file that stores high score information relating to players. An example input file called high_scores.txt can be found on the course website (under the Assessment tab). You may assume that all data is in the correct format. The name of the player and his/her high score is stored on one line and are separated by the space character as seen in Figure 1 below.

After the program has stored the data (using two Lists, one List to store the player names and the other List to store the high scores), it will enter interactive mode as described in the following section.

Figure 1: Player information file format (high_scores.txt).

Tony Stark 10
Fox Mulder 8
Dale Cooper 6
Buster Bluth 1

Interactive Mode

Your program should enter an interactive mode after the player high score information has been read from the file. The program will allow the user to enter commands and process these commands until the quit command is entered. The following commands should be allowed:

1. Scores: Outputs the contents of the high scores Lists as seen below (as seen below in the section titled Screen Format).

2. Search: Prompts for and reads the player's name and searches for the player in the player names (high scores) list. If the player is found in the player names (high scores) list, the players name, and high score, are displayed to the screen as seen below (in the section titled Screen Format). If the player is not found in the high scores list, an error message stating the player has not been found is displayed.

3. Play: Allows a player to play rock, paper, scissors (RPS) against the computer until he/she does not wish to continue playing (enters 'n' when prompted to Play again [y|n]?). After every game, the players total (cumulative) score is updated. 3 points are awarded if the player wins, 0 points are awarded if the player loses and 1 point is awarded if the player draws with the dealer.

Once the player enters 'n' (i.e. does not wish to continue playing), it is determined whether the player has qualified to be stored in the high scores list.

If the player is to be added to the high scores list, the player's name is prompted for and read. The players information is then added to the high scores lists (player names and high scores lists). Player information must be added to the high scores lists maintaining the sorted order of the lists (descending order of total score). Where two players have the same total score, the new player should appear first. (Hint: to add a record, shift all elements one position down the list). A message should be displayed to the screen indicating they have been added to the high scores lists (player names and high scores).

If the player does not qualify for the high scores lists, a message should be displayed to the screen.

4. Quit: Causes the program to quit, outputting the contents of the high scores lists (player names and player scores) to a file (see section 'Final Output' below).

Note:

The program should display an appropriate message if a player is not found matching a search criteria. Appropriate messages should also be displayed to indicate whether a command has been successfully completed.

Please refer to the sample output (at the end of this handout) to ensure that your program is behaving correctly and that you have the correct output messages.

Each time your program prompts for a command, it should display the list of available commands. See the sample output (at the end of this handout) to ensure that you have the output format correct.

For example:

Please enter command [scores, search, play, quit]:

Menu input should be validated with an appropriate message being displayed if incorrect input is entered.

Screen Format

The scores command (display_high_scores() function) should display the player information in the following format: see image.

The search command should display individual player information in the following format:

Dale Cooper has a high score of 6

Final Output

When your program finishes (because you entered the quit command) your program should output the contents of the high scores lists to a file called new_scores.txt. The format of this file should exactly match that of the input file.

Part 2 Practical Requirements - Highscores

It is recommended that you develop this part of the assignment in the suggested stages.

It is expected that your solution WILL include the use of:

  • Your solution in a file called yourSAIBTId_highscores.py.
  • The supplied rps.py module (that plays one game of rock, paper, scissors against the computer). This is provided for you - do NOT modify this file.
  • Appropriate and well constructed while and/or for loops. (Marks will be lost if you use break statements or the like in order to exit from loops).
  • You must use a loop in each function.
  • Appropriate if, if-else, if-elif-else statements (as necessary).
  • The following functions:
    • read_file(filename, player_names, player_scores) This function takes a file name and reads the contents of that file into the player_name and player_scores lists passed as a parameter into the function. The function returns the number of players read in from the file. You should make sure that you do not exceed the size of the lists (i.e. size of 5). The player_names and player_scores lists should not exceed 5 elements. You must use a loop in your solution. You may use String and/or List methods in this function only.
    • write_to_file(filename, player_names, player_scores, num_players) This function will output the contents of the player_names and player_scores lists to a file in the same format as the input file. The file will need to be opened for writing in this function (and of course closed once all writing has been done). The function accepts the filename of the file to write to, the player_names and player_scores lists and the number of players stored in the lists. You must use a loop in your solution.
    • display_high_scores(player_names, player_scores) This function will take the player_names list and the player_scores list as parameters and will output the contents of the lists to the screen. This function displays the information to the screen in the format specified in the assignment specifications under the section - 'Screen Format. You must use a loop in your solution.
    • find_player(player_names, name, num_players) This function will take the player's name as input along with the player_names list and the number of players stored in the list and will return the position (index) of the player found in the player_names list. If more than one player exists with the same name, return the position of the player who has the highest score (i.e. first match found). If the player is not found, the function returns -1. You must use a loop in your solution. You must not use list methods in your solution.
    • is_high_score(player_scores, new_score) This function takes a player's score, and the player_scores list as input and determines whether the player is to be added to the high scores lists (player_names and player_scores). If the player is to be added, the insertion position is returned from this function. If the player does not qualify to have their name recorded in the high scores lists, the function returns -1. You must use a loop in your solution.
    • add_player(player_names, player_scores, new_name, new_score, insert_position, num_players) This function takes the high scores lists (player_names and player_scores), the player's name and score, the number of high scores (stored in the lists) and the position to insert the player into the lists. The player is added to the high scores lists at the insert position. The high scores lists (player_names and player_scores) must be maintained in descending order of total score. Where two players have the same total score, the new player being added should appear first. (Hint: when inserting a player, simply shift all elements one position down the lists. You must make sure you are not exceeding list bounds and that your lists do not contain more than five elements). The function returns the number of high scores stored in the lists. You must use a loop in your solution. You must not use list methods in your solution.
    • play_rps() The play_rps() function allows a player to play RPS against the computer until he/she does not wish to continue playing (enters 'n' when prompted to Play again [y|n]?). After every game, the players total game score is updated. 3 points are awarded if the player wins, 0 points are awarded if the player loses and 1 point is awarded if the player draws. This function keeps a cumulative total of the score returned from function play_one_game() (function provided for you in the rps module). Function play_rps() returns the total score resulting from all games played and does not accept any parameters. This function calls function play_one_game()(i.e. the function provided for you in the rps module; see note below). You must use a loop in your solution.
    • So you do not have to write your own game of rock, paper, scissors, one has been provided for you. The rps.py file contains the function called play_one_game() that allows you to play one game of rock, paper, scissors against the computer. Please do not modify this module.
  • Good programming practice:
    • Consistent commenting, layout and indentation. You are to provide comments to describe: your details, program description, all variable definitions, all function definitions and every significant section of code.
    • Meaningful variable names.

Your solutions MAY make use of the following:

  • Built-in functions int(), input(), print(), range(), open(), len(), format() and str().
  • Concatenation (+) operator to create/build new strings.
  • Access the individual elements in a string with an index (one element only). i.e. string_name[index].
  • Access the individual elements in a list with an index (one element only). i.e. list_name[index].
  • The list_function.py module (that you wrote in part I of this assignment). You may like to make use of some of the functions defined in the list_function.py module for this part of the assignment (as appropriate).

Your solutions MUST NOT use:

  • Built-in functions (other than the int(), input(), print(), range(), open(), len(), format() and str() functions).
  • Slice expressions to select a range of elements from a string or list. i.e. name[start:end].
  • String or list methods (i.e. list_name.append(item), etc).
  • Global variables as described in week 9 lecture.
  • Do not use break, return or continue statements (or any other technique to break out of loops) in your solution - doing so will result in a significant mark deduction.

PLEASE NOTE: You are reminded that you should ensure that all input and output conform to the assignment specifications. If you are not sure about these details you should check with the sample output provided at the end of this document or post a message to the discussion forum in order to seek clarification.

Please ensure that you use Python 3.6.5 (or most current version) in order to complete your assignments. Your programs MUST run using Python 3.6.5 (or most current version).

Part 2 - Stages

It is recommended that you develop this part of the assignment in the suggested stages. Many problems in later stages are due to errors in early stages. Make sure you have finished and thoroughly tested each stage before continuing.

The following stages of development are recommended:

Stage 1

To begin, download the provided file (available on the course website called highscores.py) and name it yourSAIBTId_highscores.py. Define two lists (with five elements each) in order to store high score information, that is, player names and their cor- responding scores.

For example:

player_names = ["","","","",""]
player_scores = [0,0,0,0,0]

Stage 2

Call function play_one_game() (provided for you in the rps.py module).

Note: you may simply download it from the course website under the Assessment tab. The file rps.py should be placed in the same directory as yourSAIBTId_highscores.py file. Please do NOT modify the rps.py module.

Import the rps module and call function play_one_game() as seen below. You may wish to read the material on modules posted on the course website (under the assessment tab).

import rps
score = rps.play_one_game()
print('Score is:', score)

Make sure the program runs correctly. Once you have that working, back up your program. Note: When developing software, you should always have fixed points in your development where you know your software is bug free and runs correctly.

Once you are sure that your program is working correctly, you can comment out the above two statements - we just wanted to make sure it was working correctly! You can bring it back later (appropriately positioned).

Stage 3

Write the code for function read_file() and display_high_scores() as specified in Part 2 Practical Require- ments Highscores on page 22 . Add code to call these two functions to ensure they are working correctly.

Hint on reading files. . . : Week 9 contains the slides that discuss and demonstrate reading in a file. You may want to refresh your memory by (re-)reading the relevant slides.

Hint on Testing. . . : After reading in the contents of the file, use a print statement to print out the lists player_names and player_scores. They should appear as follows:

['Zhang Ziyi', 'Phteven Tuna', 'Drew Barrymore', 'Aaron Eckhart', '']
['5', '4', '3', '1', 0]

Hint on formatting output. . . : The format command helps you to place text either left, right or center aligned within a number of spaces that you can specify. See the format command in IDLE Help.

Output for function display_high_scores() see image.

Let's look at how you can use the format command to display one of the lines above. . . The following line is made up of 2 asterisks with a whole bunch of dashes:

*---------------------------------------------------*

Instead of manually counting the number of dashes you can use the len() function to tell you how many there are.

Step 1: Copy and paste the dashes into a Python Shell :)

>>>len('---------------------------------------------------')

Step 2: Then use the repetition operator to display that many. For example:

print('-'*20)

. . . will produce the following output:

>>>--------------------

Step 3: To add the asterisks (i.e. '*') in the same print statement is just a matter of including them like so:

print('*', '-'*numberOfDashes,'*')

Don't forget that when you have multiple items in a print statement, the default separator is a space character. So either factor this in or simply change the default value to an empty string ;)

Stage 4

Now that you know the information is being correctly stored in your high scores lists (player_names and player_scores lists), write the code for function write_to_file(). Add code to call this function to ensure it is working correctly.

Just remember that while testing, where you call this function does not really matter. However you will need to move the call to write_to_file() after developing your program.

Stage 5

Implement the interactive mode, i.e. to prompt for and read menu commands. Set up a loop to obtain and process commands. Test to ensure that this is working correctly before moving onto the next stage. You do not need to call any functions at this point, you may simply display an appropriate message to the screen, for example:

Sample output:

Please enter command [scores, search, play, quit]: roger
Not a valid command - please try again.
Please enter command [scores, search, play, quit]: scores
In scores command
Please enter command [scores, search, play, quit]: search
In search command
Please enter command [scores, search, play, quit]: play
In play command
Please enter command [scores, search, play, quit]: quit

Menu input should be validated with an appropriate message being displayed if incorrect input is entered by the user.

Stage 6

Implement one command at a time. Test to ensure the command is working correctly before starting the next com- mand. Start with the quit and scores commands as they do not need you to add anything further to the file other than ensuring that the function calls are in the correct place.

You should be able to see that for most commands there is a corresponding function(s).

For the remaining commands, the following implementation order is suggested:

  • search command (find_player() function).
  • play command (play_rps(), is_high_score() and add_player() functions).

Stage 7

Ensure that you have validated all user input with an appropriate message being displayed for incorrect input entered by the user. Add code to validate all user input. Hint: use a while loop to validate input.

Stage 8

Finally, check the sample output (see section titled 'Sample Output - Part II' towards the end of this document) and if necessary, modify your code so that:

  • The output produced by your program EXACTLY adheres to the sample output provided.
  • Your program behaves as described in these specs and the sample output provided.
Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.