2 years ago 2 years ago Python Share

Simplified Game of NIM in Python with Code and Details

This was an assignment I did for my Cyber Security course. It's a Python version of the ancient Chinese game of NIM.

This page still needs a lot of editing, and fixing up generally, especially for the images to be pasted in properly.

I'm trying to get the game to run in a web browser, which so far has not been fully successful. Though you can try out a live example of the game running online here (though it doesn't run very well due to the way the input() statements are badly handled by the JavaScript implementation of Python, and also run your own Python code in the browser, edit it, and save it.  You can also copy the code to another site which runs it much better (link is on the same page), or run it in any other version of Python which you may have access to.

Preliminary Notes

Note that I’ve made the margins of this document smaller than usual, to allow more of my pasted Python source code to not overlap to a new line after being pasted into this document. So, this way, the code is a bit easier to read and follow. I hope this is okay. 

Rather than textbooks, I used mostly Google searches, of which there would have been hundreds (and far too many to individually list in the Bibliography here). Probably the site I used the most was stackoverflow (as found from Google searches). Generally, I would Google-search a term and then open the most promising-looking about ~5 pages in new browser tabs, and then scan them for what I was looking for. This I found to be the quickest and easiest way to learn, based on having coded before in many languages, but not very much before in Python. So, I already knew what I wanted to do, and what it was called – and could therefore search for things like “string concatenation in python” and find the answer quickly and easily from the web, without needed to look much at textbooks. I was already familiar enough with the basics of Python, like how the indenting works, which would be hard to learn without textbooks and/or class video lectures, etc. 

Here are a few textbooks that I refer to occasionally (just so there are some references to cite): Reges, Stepp, and Obourn [1]; Guttag [2]; and Nagar [3].  

User Requirements

These are the user requirements, as per the stated specifications: 

Write a detailed algorithm and a program that plays the ancient Chinese game of NIM. Actually, this is a simplified version of the original game. In this game, the person who runs your program will be one of the two human players, your program will be a simple Artificial Intelligence (AI) that will serve as the other player, as well as provide the narrative for the game and keep score, invite a friend to be the third player. Your program must keep score impartially while participating in the game, but this is not a difficult task for the computer. 

Rules of the Game: 

·         Number of participating Players: 2 students and 1 computer

·         The player who goes first shall define the number of stones in the pile. The number must be between 30 to 50.

·         Each player then removes some number (between 1 to 3) of stones from the pile in turn until one player removes the final stone.

·         The player who goes first:

I. Provides the number of stones to be placed in the pile,

ii. Removes the first set of 1 to 3 stones

·         The other player removes a set of 1 to 3 stones

·         The players then take turns(iteration) until the final stone is removed.

·         The player who removes the final stone is the winner (student player 1/ student player 2 / the computer). 

    The program must perform the following:

·         Introduce and describe the game, the computer shall introduce itself as the AI player, and prompt the human players for his or her names along with MIT Ids.                

·         Program is to be interactive to receive and display the response.                                               

·         To display a greeting to the human player that incorporates the name provided in response to the prompt: Welcome <user’s name> to the game of Taking Stones.               

·         The user’s name must be output in proper name case (i.e., mixed case starting with upper case for the first letter) regardless of the case the user types in.                                 

·         The users shall input the number of stones to be picked either by using a standard random number generator function or may input according to their own strategy but the number should be less than or equal to three (3) and more than zero.                                                                      

·         The program must reject and display a valid message if the number of stones to be removed are either less than one (1) or more than three (3) and remind them the game constrains. In case of invalid entries program to prompt that player to re-enter an appropriate number. 

·         Your program should have the computer use the optimal playing strategy. The optimal strategy is as follows: Divide the remaining number of stones by three. If the remainder is zero, then two stones are removed, or else one stone is removed. For example, if the remaining number of stones is nine or fifteen, then two stones are removed; if the remaining number of stones is eight or ten, then one stone is removed.     

·         Both the human players shall have their own strategies to play.                                     

·         When one of the players has won a game, the program must output a congratulatory message naming the winner along with ID.                                                                                    

·         Your program should allow the users to play additional games of NIM as long as he/she enters a “y” or “yes” (lowercase or uppercase) in response to a “Do you want to play again?” prompt. 

In this assignment the students shall code the specified requirements on incremental development processes of designing, coding, testing and debugging. This assignment involves the following tasks:

1.       To Design and develop an algorithm or a detailed flow chart to play the game as defined by the rules.

2.       To convert the algorithm to a python program and test for various cases.

3.       A GUI (optional) may be designed to feed in the password and display the encrypted messages. 

Note: Generally, in a project you should write a program that contains an introductory docstring. This documentation should describe what the program will do (analysis) and how it will do it (design the program in the form of a pseudocode algorithm). Include suitable prompts for all inputs, and label all outputs appropriately. After you have coded a program, be sure to test it with a reasonable set of legitimate inputs. 

Note that an extra assumption was made for the AI of the computer and its “optimal” strategy, which is that if it can possibly win on any given turn (e.g. by removing the last 2 or 3 stones), it will do so, which the original specifications as above does not include. The original strategy from the specifications will still work when there is only one stone remaining – since that isn’t divisible by 3, and therefore the computer will remove the one last remaining stone and win. However, the originally specified “optimal” strategy would cause the computer to lose when there are 3 stones left (which is divisible by 3, so it would remove two of them), or 2 stones left (which isn’t divisible by three, so it would remove one of the two) – either of these choices would result in the computer losing, when it could win on that move according to the rules. So the specifications have been changed so that it will remove all of the stones if that number is from 1-3, and then win on that move. 

A further addition is the keeping of a running score count, and displaying a scoreboard.  

Another extra feature is the use of asterisks in an ASCII-art-style to construct a box to highlight the winning player’s details for each single game played. 

Analysis

Here is a Software Requirements Specification document for PyNIM: 

1. Purpose of Document

This is a Requirements Specification document for a new computer game. The game is a simplified implementation of the ancient Chinese game of NIM. This document describes the scope, objectives and goal of the new system. In addition to describing non-functional requirements, this document models the functional requirements with use cases, interaction diagrams, and class models. This document is intended to direct the design and implementation of the target system in the language Python. 

2. Background

This would be elaborated on in an actual commercial project. For this project, refer to the previous section for the specifications (since they also contain the background information). 

3. Project Scope

The game as currently deployed runs on a local machine with a Python 3 interpreter installed. It could be modified/extended, with addition of further code (including JavaScript / AJAX / etc.) to run online in a web browser, and sessions could be set up enabling the two human players to be online at different physical locations. This was not implemented in this version – therefore the two human players must have physical access to the same one machine the game is running on. 

4. Functional Requirements

The game must be able to run and be played as per the specifications above. This includes appropriate handling of basic wrong inputs such as non-numeric answers for numeric questions.  

5. Non-Functional Requirements

The game has some added “personality” features of the AI to make it more interesting.  

The players of the game must be able to read English, and also to make extremely basic mathematical conclusions, at the level of early primary school mathematics. 

6. Security Requirements

This version does not implement a large amount of security considerations, other than some basic input validation, and truncating of potentially extremely long input strings. A commercial version would further examine and sanitate all possible inputs, e.g. by stripping out special characters where they are not needed from all inputs to the program. This program does not have any filesystem nor network access within it, which greatly simplifies the potential security issues.  

Potential security risks would be limited to the system the program is running on being compromised, in which case there is a potential risk that names and ID numbers of students/players may be leaked to unwanted or malicious intrusion. 

7. Documentation Specifications

A short “heredoc” statement is included at the beginning of the program’s source code. The rest of the documentation is scattered throughout this entire document, plus in comments inline with the source code and the pseudocode. However, in a commercial application, further work would be required for documentation (including perhaps a “man” page for Unix and a Windows-style help interface for a Windows version, etc.). 

Design

Here is an algorithm (in pseudocode) to accomplish the task as specified above. This “pseudocode” is very wordy and English-like. It could be further reduced for brevity, though then it would quite closely resemble the actual Python code (but without all the Python syntax). The perhaps longer-than-usual version as given here was chosen since it more fully explains the functionality/design of the game. 

Start 

Import any required modules: Random number generator module. 

Define a function input_players_stones(name, max_removable) for the number of stones removed by one human in one turn. This function accepts two parameters: name (the player’s name) and max_removable which is the most stones that can be removed in this turn.  

Display prompt (including their name) and accept input into the variable num_removed 

      If num_removed is blank (i.e. nothing is entered):

            Set num_removed to a random number between 1 and the max_removable

            Display how many stones were removed by the randomly selected choice. 

      Return the value of num_removed. 

Define a function players_turn(players_name) which processes each human player’s turn. This function accepts one parameter, the players name. Its return value is the number of stones that were removed in this turn. 

      Display the number of stones remaining.   

      Set the value of max_removable to 3, or less than 3 when < 3 stones are left. 

      Call the function input_players_stones(players_name, max_removable_stones). 

      Set the value of num_removed to the return value of the function above.     

      Check that the value of num_removed is valid (is numeric a in the range

      from 1 to max_removable_stones). If it is invalid, display a message and

      keep asking the player repeatedly until the input is valid.   

      Convert the value of num_removed from string to integer. 

      Return this value.          

Initialise variables for the start of the entire run:

game_running = True

games_played = 1

player_1_score = 0

player_2_score = 0

pythons_score = 0 

Display the opening welcome message and a summary of the rules. 

Get the basic information (names and IDs) from the players. 

Blank inputs are rejected and the player is asked repeatedly until a non-blank answer. 

The names are converted to first-letter-capital and the rest lowercase.

The names are truncated to a maximum of 30 characters, any more are deleted.

The IDs are truncated to a maximum of 9 characters, and more are deleted. 

A further welcome message is displayed including both human players’ names

and the message “to the game of Taking Stones” as per the specifications. 

From this point the entire rest of the code loops over each single game,

until the player chooses to quit the gameplay. The variable game_running is used to determine if the player wishes to continue playing the game after the first game is played. 

while game_running: (everything in the code below here is part of this ‘while’ loop).     

      Prompt player one and ask them to input the initial number of stones.

      Reject out-of-range answers and non-numeric answers and blank answers, and re-ask the question until valid. 

      Display confirmation message when a valid number is entered.  

      Set current_num_stones = initial_num_stones 

Loop over each of the players turns (including the computer) while the gameplay gradually reduces the number of stones:

while current_num_stones > 0:      

            Process first player’s turn:

                  current_num_stones -= players_turn(player_1_name)

                  if current_num_stones == 0:

                        Set winners_name = player_1_name

                        Set winners_id = player_1_id

                        Increment player_1_score

                        break       

      Process second player’s turn:

current_num_stones -= players_turn(player_2_name)

            if current_num_stones == 0:

                  Set winners_name = player_2_name

                  Set winners_id = player_2_id

                  Increment player_2_score

                        break           

            Process computer’s turn:                 

                  First check for possible winning moves when 3 or 2 stones are left.

                  if current_num_stones == 3 then computer_removes = 3

                  else if current_num_stones == 2 then computer_removes = 2           

            Now follow the “optimal” strategy as given in the specifications

            for the non-final moves:           

            else if current_num_stones modulus 3 == 0 then computer_removes = 2           

            else computer_removes = 1 (this applies to either final or non-final moves) 

            Display the number of stones removed by the computer. 

current_num_stones -= computer_removes       

                  if current_num_stones == 0:

                        Set winners_name = "The Python"

                        Increment pythons_score

                        break       

At this point, a single game is over, as current_num_stones = 0, which ends the above inner ‘while’ loop.

Display winner’s details with a box of asterisks surrounding the message.

If the winner is human, include their ID and a message of congratulations.   

      Display the running score so far of the two human players, and the computer,

      next to their names. The computer’s name is “The Python”.   

If the computer has won the recently-played game, and is also winning the total scoreboard, display an insulting message characteristic of the “reptilian” personality of the AI as implemented in this version of NIM. 

Else if either human player has won this current game (and irrespective of the total ongoing scoreboard results), display a further congratulatory message, but in a sarcastic tone as befitting a “python”. 

Else if the computer wins the current game, but is not winning overall, then neither of the above two extra messages are displayed (this line is not needed in the actual code as nothing happens at all for this step, but is included here to clarify the logic).

   

      Prompt for “Would you like to play again?” and repeatedly ask until a non-blank answer is given. This is to prevent a player accidentally pressing enter and

      then ending the game (and the scoring count) if they didn’t mean to. 

      Then, as per the specs, if ‘y’ or ‘yes’ (after conversion to all-lowercase) is e      entered, the game continues. All other responses end the game. 

      If the game is continuing, then:

            Increment games_played.

            Display a message to get ready for round (value of games_played). 

      else:

            Set game_running = False (this will end the outer ‘while’ loop).

            Display “Goodbye, and thank you for playing PyNIM!!!”.           

At this point, game_running has been set to False and the program stops running. 

Stop

Implementation Phase

Here is my Python code pasted in (in character form and not from a screenshot, as requested). The font size was reduced so there would be significantly less line-wrap of the longer lines in this pasted version, which is not seen in my IDE editor, and which makes the indented structure of the Python language harder to view and follow visually. The colours from the IDE’s code colouring were left in as an aid to reading, and the black background was added to make the code colouring-colours more visible (since the IDE also has a dark theme) than they would be against a white background (like the rest of this document has).

Python Source Code

"""

This program plays the ancient Chinese game of NIM.

Actually, this is a simplified version of the original game.

In this game, the person who runs your program will be one of the two human players.

This program will be a simple Artificial Intelligence (AI) that will serve as the other player,

as well as provide the narrative for the game and keep score, invite a friend to be the third player.

 

'The Python' i.e. the computer/AI player in this version is "cheeky", to make it more interesting, and to

more fully emulate the "personality" that an actual snake/reptile might perhaps have.

 

If there was more time to do work on this, there would have been an option for "Do you want The Python

to be in friendly or reptilian mode?", and if in reptilian mode the AI would tell lies about

how many stones it's removed, and sometimes cheat on the rules (e.g. by removing 4 stones),

and make even more condescending  remarks, just to make the game more interesting.

However this feature was not implemented, due to the extra time required and many other assessments are also due.

 

Rules of the Game:

 

    *    Number of participating Players: 2 students and 1 computer

    *    The player who goes first shall define the number of stones in the pile. The number must be between 30 to 50.

    *    Each player then removes some number (between 1 to 3) of stones from the pile in turn until one player removes the final stone.

    *    The player who goes first:

            i. Provides the number of stones to be placed in the pile,

            ii. Removes the first set of 1 to 3 stones

    *    The other player removes a set of 1 to 3 stones

    *    The players then take turns(iteration) until the final stone is removed.

    *    The player who removes the final stone is the winner (student player 1/ student player 2 / the computer).

 

Most of the comments in the code occur above the line(s) they are relevant to, however occasionally

they are written underneath, in cases where writing them above would have broken up the visual appearance

of the code itself and made it look more complicated and harder to follow/read by people.

 

A few lines of debugging code (in the form of print() statements) have been commented out, but left in this program.

In a 'real' commercial program this may be removed, or not, depending on the style/conventions used by the

coding company involved. Leaving the degugging code in allows for future additions to the game,

and also for any debugging that may be needed to the existing version, and which

may be helped by being able to easily activate/turn on some of the debugging info.

 

Generally, variable and function names have been chosen to help make the code itself as "self-commenting" as possible.

"""

 

# importing the random module

import random

 

# Function to input the number of stones a player removes in any one turn

#

# I made this a separate function since the code gets called twice,

# and it seemed more elegant than writing it twice in the parent function

def input_players_stones(name, max_removable):

    """

    This function processes the input for a player's choice of how many stones to remove

    within each step of their turn.

    """

    num_removed = input("How many stones (from 1 to " + str(max_removable) + ") will you remove, " + name + "? (or press Enter for a mystery value): ")

    if num_removed == '':

        num_removed = str(random.randint(1, max_removable))

        print(name + ", you have removed " + num_removed + " stones.")

       

    return(num_removed)

  

 

# Function definition for each human player's turn

# I made this into a function since the whole thing gets called twice

# (once for each human player).

def players_turn(players_name):

    """

    This function processes the input for a player's turn

    """

    print("There are " + str(current_num_stones) + " stones remaining...")

   

    if current_num_stones < 3:

        max_removable_stones = current_num_stones

    else:

        max_removable_stones = 3

   

   

    num_removed = input_players_stones(players_name, max_removable_stones)

   

    while not num_removed.isnumeric() or int(num_removed) < 1 or int(num_removed) > max_removable_stones:

        print("You MUST enter a number from 1 to " + str(max_removable_stones) + "! Can you even count, " + players_name + "?")

        num_removed = input_players_stones(players_name, max_removable_stones)

        # print ('Debugging: Your corrected attempt is removing ' + num_removed + ' stones.')

 

       

    # print ('Debugging: You are removing ' + num_removed + ' stones.')

       

    num_removed = int(num_removed)

   

    return num_removed

 

# Init basic game counters and other variables

game_running = True

games_played = 1

player_1_score = 0

player_2_score = 0

pythons_score = 0

 

# Get basic info from players

 

# Display opening message and rules.

print('Welcome to PyNIM, the Ancient game of NIM played against a real live Python!')

print('... or, perhaps against a virtual Python...')

print('... or, maybe it\'s played against a computer language called Python.')

print('\nA formidable opponent... Can you (or your friend) beat the powerful AI of the Python?')

print('\nPyNIM has 3 players: Two humans, plus "The Python" which is this computer.')

print('The first player initially decides how many stones to start the game with, from 30 to 50.')

print('For each round of the game, each player gets to remove from 1 to 3 stones from the pile.')

print('The player who removes the last stone (i.e. reduces the pile to 0 stones) is the winner.\n')

 

# Input players' details. Completely blank inputs are rejected, and the question is repeated until answered.

player_1_name = ''

while player_1_name == '':

    player_1_name = str.capitalize(input("What is your name, Player One? "))[:30] # Limit to first 30 characters entered

   

player_1_id = ''

while player_1_id == '':   

    player_1_id   = input("What is your MIT Student ID, " + player_1_name + "? ")[:9] # Limit to first 9 characters entered

   

player_2_name = ''

while player_2_name == '':   

    player_2_name = str.capitalize(input("What is your name, Player Two? "))[:30]

 

player_2_id = ''

while player_2_id == '':

    player_2_id   = input("What is your MIT Student ID, " + player_2_name + "? ")[:9]

 

# Note that it would easily be possible to further validate the IDs above, e.g. by requiring them to begin with 'MIT',

# and to then consist of exactly 6 digits. However this was not officially in the specs and therefore

# was not implemented here to save development time. Especially since it was easier to test-play the game

# a large number of times without having to type in a valid MIT student ID string for each test run.

 

print("Welcome, " + player_1_name + " and " + player_2_name + " to the game of Taking Stones.")

 

# Loop over each single entire game until player chooses to quit

while game_running:

     

    initial_num_stones = 0

    while initial_num_stones < 30 or initial_num_stones > 50:

        initial_num_stones = input("How many stones (from 30 to 50) would you like to start the game with, " + player_1_name + "? ")[:3] # Limit to 3 chars

        # Note above that if the input above was limited to 2 characters (as may seem more appropriate for 30-50 stones), then a value like 345 would be

        # interpreted as 34, rather than generating an error message and asking to input the number again as is the intended behaviour.

        try:

            initial_num_stones = int(initial_num_stones)

        except ValueError:

            print("This is not even a number! Numbers consist of the digits from 0 to 9, in case you have forgotten!")

            initial_num_stones = 0

            # The computer is a "Python" so it has a cheeky/rude personality befitting a reptile

       

    print("You have selected " + str(initial_num_stones) + " stones, " + player_1_name + ". A fine choice!\n")

   

    current_num_stones = initial_num_stones

   

    while current_num_stones > 0:

        # print("There are " + str(current_num_stones) + " stones remaining...")

       

        current_num_stones -= players_turn(player_1_name)

        if current_num_stones == 0:

            winners_name = player_1_name

            winners_id = player_1_id

            player_1_score += 1

            break

       

        current_num_stones -= players_turn(player_2_name)

        if current_num_stones == 0:

            winners_name = player_2_name

            winners_id = player_2_id

            player_2_score += 1

            break

           

        # The 'Python's turn to play

        # The optimal strategy is as follows: Divide the remaining number of stones by three.

        # If the remainder is zero, then two stones are removed, or else one stone is removed

        # *** Note that this strategy was modified for the last move of the game, where the

        #     computer will remove as many stones as possible to win on that move, if it can.

        # Since the computer's turn is processed quite differently to the human players' turns,

        # there seemed no need to make it a function, since the code only needs to be written once.

       

        if current_num_stones == 3: # This is a winning move for the final move only

            computer_removes = 3

           

        elif current_num_stones == 2: # This is a winning move for the final move only

            computer_removes = 2

           

        elif current_num_stones % 3 == 0: # This is a non-winning move on the non-final moves

            computer_removes = 2

           

        else:

            computer_removes = 1 # This may be either on the final move, or not, it's the same action for either.

           

        print("The Python has removed " + str(computer_removes) + " stones...\n")

           

        current_num_stones -= computer_removes

       

        if current_num_stones == 0:

            winners_name = "The Python"

            pythons_score += 1

            break

       

       

    # The code below calculates offsets for lining up the final asterisk in the

    # "box" display of asterisks, and displays them.

    # Note to any future development -- this section may need to be modded if there is a

    # significant change to the character length limits on the Name and the Student ID fields

   

    print('\n' + '*' * (44 + len(winners_name)))

    #print("****************************************************")       

    print("*     And...THE WINNER IS......... " + winners_name + "!!!" + "     *")

   

    if winners_name != "The Python":

        print("*     Your MIT Student ID is: " + winners_id + ' ' * (44 + len(winners_name) - len(winners_id) - 31) +'*')

        #print("*     Congratulations, " + winners_name + "! Nice work!" + ' ' * (16 - len(winners_name)) +'*')

        print("*     Congratulations, " + winners_name + "! Nice work!        *")

       

    print('*' * (44 + len(winners_name)) + '\n')

    #print("****************************************************\n") 

   

    print("The score so far:")

    print(player_1_name + ": " + str(player_1_score))     

    print(player_2_name + ": " + str(player_2_score))     

    print("The Python: " + str(pythons_score))  

    print()  

   

    if pythons_score > player_1_score and pythons_score > player_2_score and winners_name == "The Python":

        print("Evidently, reptilian intelligence exceeds that of humans.")

        print("Perhaps you can be a better example of success for your species in the next game...?\n")

       

    elif winners_name == player_1_name or winners_name == player_2_name:

        print("The Python is hissing as it concedes to your superior playing skill. Ssssssssss...\n")

 

    play_again = ''

    while play_again == '':

        play_again = input("Would you like to play again? ")

   

    if play_again.lower() == 'y' or play_again.lower() == 'yes':

        games_played += 1

        print("\nGreat! Get ready for round " + str(games_played) + "...\n")

    else:

        game_running = False

        print("\nGoodbye, and thank you for playing PyNIM!!!")    

           

 

Welcome to PyNIM, the Ancient game of NIM played against a real live Python!

... or, perhaps against a virtual Python...

... or, maybe it's played against a computer language called Python.

 

A formidable opponent... Can you (or your friend) beat the powerful AI of the Python?

 

PyNIM has 3 players: Two humans, plus "The Python" which is this computer.

The first player initially decides how many stones to start the game with, from 30 to 50.

For each round of the game, each player gets to remove from 1 to 3 stones from the pile.

The player who removes the last stone (i.e. reduces the pile to 0 stones) is the winner.

 

What is your name, Player One? Tim

What is your MIT Student ID, Tim? MIT123456

What is your name, Player Two? Sally

What is your MIT Student ID, Sally? MIT555555

Welcome, Tim and Sally to the game of Taking Stones.

How many stones (from 30 to 50) would you like to start the game with, Tim? 33

You have selected 33 stones, Tim. A fine choice!

 

There are 33 stones remaining...

How many stones (from 1 to 3) will you remove, Tim? (or press Enter for a mystery value):

Tim, you have removed 1 stones.

There are 32 stones remaining...

How many stones (from 1 to 3) will you remove, Sally? (or press Enter for a mystery value):

Sally, you have removed 2 stones.

The Python has removed 2 stones...

 

There are 28 stones remaining...

How many stones (from 1 to 3) will you remove, Tim? (or press Enter for a mystery value): 3

There are 25 stones remaining...

How many stones (from 1 to 3) will you remove, Sally? (or press Enter for a mystery value): 2

The Python has removed 1 stones...

 

There are 22 stones remaining...

How many stones (from 1 to 3) will you remove, Tim? (or press Enter for a mystery value): 1

There are 21 stones remaining...

How many stones (from 1 to 3) will you remove, Sally? (or press Enter for a mystery value): 2

The Python has removed 1 stones...

 

There are 18 stones remaining...

How many stones (from 1 to 3) will you remove, Tim? (or press Enter for a mystery value): 3

There are 15 stones remaining...

How many stones (from 1 to 3) will you remove, Sally? (or press Enter for a mystery value):

Sally, you have removed 3 stones.

The Python has removed 2 stones...

 

There are 10 stones remaining...

How many stones (from 1 to 3) will you remove, Tim? (or press Enter for a mystery value): 4

You MUST enter a number from 1 to 3! Can you even count, Tim?

How many stones (from 1 to 3) will you remove, Tim? (or press Enter for a mystery value): 2

There are 8 stones remaining...

How many stones (from 1 to 3) will you remove, Sally? (or press Enter for a mystery value): 1

The Python has removed 1 stones...

 

There are 6 stones remaining...

How many stones (from 1 to 3) will you remove, Tim? (or press Enter for a mystery value): 3

There are 3 stones remaining...

How many stones (from 1 to 3) will you remove, Sally? (or press Enter for a mystery value): 3

 

*************************************************

*     And...THE WINNER IS......... Sally!!!     *

*     Your MIT Student ID is: MIT555555         *

*     Congratulations, Sally! Nice work!        *

*************************************************

 

The score so far:

Tim: 0

Sally: 1

The Python: 0

 

The Python is hissing as it concedes to your superior playing skill. Ssssssssss...

 

Would you like to play again?

 

Further examples of different inputs and test results are shown in the next section.

 


 

Testing

Compilations with Syntax Errors and Their Corrections

Note that in the screenshots, my MIT student ID is present in the directory name in the file list pane, and also in the window title bar at the top of the workspace application.

 

Here is an initial compilation attempt with an indentation error in the syntax:

 

 


 

Here is a corrected version, the affected line is highlighted in blue:

 


 

Here are some test cases with wrong inputs:

·         Blank answers to the initial questions result in the question being re-asked.

·         The Names are truncated to a maximum of 30 characters, which seems plenty long enough for anyone’s first name.

·         The Names are converted to first character uppercase and the rest all lowercase as per the specs.

·         (Although not re-displayed after entering), the student IDs are truncated to a maximum of 9 characters and otherwise not checked/validated.

·         The number of stones gives a response from “The Python” demonstrating its reptilian “attitude” if you enter anything that isn’t a number, including a blank response.

·         The number of stones just repeats the question if you enter a number out of range.

 


 

Next is the gameplay and some test cases of wrong inputs:

Blank answers for player’s turns generate a random number of stones from 1-3 (or from 1 to the number left if it’s less than 3). Above are some examples of this. The players are told how many stones they removed when they chose a random value. The number of stones removed by “The Python” is also shown.

 

Here is some more of the gameplay:

·         When the human players choose a number of stones, it isn’t re-displayed (since they already know what the number is), unlike when a random number is chosen.

·         Answers out of range give an error (in the personality of “The Python”).

·         Very long answers are handled without problems (giving the same error message during the game).

·         At the end the winner is displayed in a box with asterisks all around to highlight it.

·         Then the score is displayed.

·         If the Python/computer wins the current game, and also is leading in the overall scoreboard, it gives a bragging/insulting message.

 

Here is the new game starting:

Blank answers to “Would you like to play again?” generate another repeat of the same question.

As per the specs, only a “y” or a “yes” after converting the string to all lowercase will play again, any other response ends the game. I didn’t test multiple options of “no” for the screenshots since each one requires playing an entire new game, and there would end up being dozens of pages of screenshots. 

The game keeps count of how many rounds (i.e. games) have been played, and displays it as shown above. 

 Above is an example of a human player winning. the box with asterisks centres the first line of text, and then the other lines are left-aligned to that one. The asterisks at the end are lined up based on calculations of the character lengths of the Name and ID strings, and the other characters. They are designed to work for any currently-possible combinations of Name and ID string length within the existing constraints. This may need to be modified if the allowed lengths were to change in future versions and there is a comment to that effect in the code. For example, the Name has to be at least one character long, and the longest the MIT IT can be is nine characters. This means that (the way things are now) the first second line of text will never be longer than the first line, even for the boundary condition of a one-character name and a 9-character ID. The other boundary conditions (e.g. a really long name and short ID, and other combinations) were also tested, yet screenshots are not included for all these due to space/length considerations of this report. 

I can remember ASCII-character-based “graphical” display devices such as this were common in the days before GUIs were easily available, so (with the box of asterisks) I was trying to re-create somewhat of a genuine retro/vintage look-and-feel, which I think well suits this kind of text-based game. Additional calculations could be performed (and functions written) to centre all three lines of text (rather than left-align them), however due to time constraints this was not done. 

 Above is shown the ending of the game, when “n” is selected. 

Link to Video of Game Play with Test Cases

https://drive.google.com/file/d/15S8p_Yz7tY6C7Q7nRqXf74t-o3hEC5b1/view?usp=sharing

References

[1]          S. Reges, M. Stepp, and A. Obourn, Building Python programs, First edition. ed. New York, NY: Pearson, 2019, p. pages cm.

[2]          J. Guttag, Introduction to computation and programming using Python : with application to computational modeling and understanding data, Third edition. ed. Cambridge, Massachusetts: The MIT Press, 2021, pp. xviii, 637 pages.

[3]          S. Nagar, Introduction to Python for Engineers and Scientists : Open Source Solutions for Numerical Computation, 1st ed. Berkeley, CA: Apress : Imprint: Apress,, 2018, pp. 1 online resource (XVII, 254 pages 30 illustrations in color.

 

Cover image by Shutterstock

Byte.Yoga Homepage - Australian Cyber Security Web Magazine

Share This Page

If you liked this page, please share it with others! You can use the links to share on Facebook, Twitter, LinkedIn, Pinterest, and Email. Ther is also an RSS feed to get updates for the website.