The user's inputs are specified by entering a number: 1 for rock, 2 for paper, 3 for scissors. If the user enters a 4, the program should print some useful statistics about the series of game results, print a goodbye message, and exit. The program should reject any other inputs with an error message; it should not crash.
On exit, the program computes and prints some final statistics about the play:
Note that you'll need to use several of the constructs you've learned in class including a loop and if statements. You also must define at least two functions (in addition to your main() routine). For example, my version defined the following three functions, though you don't have to use these same ones. (ROCK is a symbolic constant; see the discussion in the Programming Tips section below.)
def playName( play ): """For each possible move, return the name to print. For example, ROCK prints as 'rock'.""" ... def defeats( play1, play2 ): """Boolean valued function that returns True iff play1 defeats play2.""" ... def printStats( plays, wins, losses, draws ): """Print the statistics for the sequence of games played.""" ...Implementing the Machine Play: The user specifies a play by entering a number. The machine must also make a play. Below is the code to implement the machine play. Be sure to copy this code exactly. (This doesn't count as one of your two required functions.) When you need in your code for the machine to return a play, just call machinePlay().
import random import sys # If no 'oracle' is supplied on the command line, choose machine plays # randomly. Otherwise use the supplied oracle. HAS_ORACLE = ( len(sys.argv) > 1 ) if HAS_ORACLE: MACHINE_ORACLE = sys.argv[1] # This is a global variable that indexes into the 'oracle' to select # the next machine play. machinePlayCounter = 0 def machinePlay (): """The machine chooses one of the three moves randomly, unless there's an oracle passed on the command line. Then we choose machine plays from that.""" global machinePlayCounter if HAS_ORACLE and machinePlayCounter < len(MACHINE_ORACLE): play = MACHINE_ORACLE[ machinePlayCounter ] machinePlayCounter += 1 else: play = random.choice(["1", "2", "3"]) return playYou don't really need to understand the code above. But if you'd like to, here's what it does: If the program is run without an argument on the command line as, for example:
> python3 Project1.pythen each play by the machine is selected at random from the three possible legal responses. If, on the other hand, there is an argument given on the command line, e.g.,
> python3 Project1.py 12313223122131then plays by the machine are chosen in order from the supplied string; arguments on the command line are always interpreted by Python as strings. In computing, an input like this that drives the computation is sometimes called an oracle. The oracle should contains only characters "1", "2", and "3". If it runs out, subsequent machine plays are chosen randomly.
None of your other code needs to take notice of the possibility of running the program in these two different ways. But being able to do this is useful; the TAs can supply an oracle to force your code to behave deterministically. This makes it much easier to write a grading script that doesn't have to account for random behavior.
> python Project1.py Welcome to a game of Rock, Paper, Scissors! Choose your play: Enter 1 for rock; Enter 2 for paper; Enter 3 for scissors; Enter 4 to exit: exit Illegal play entered. Try again! Choose your play: Enter 1 for rock; Enter 2 for paper; Enter 3 for scissors; Enter 4 to exit: 18 Illegal play entered. Try again! Choose your play: Enter 1 for rock; Enter 2 for paper; Enter 3 for scissors; Enter 4 to exit: 4 No games were completed. Thanks for playing. Goodbye! > python Project1.py Welcome to a game of Rock, Paper, Scissors! Choose your play: Enter 1 for rock; Enter 2 for paper; Enter 3 for scissors; Enter 4 to exit: 1 You played rock; your opponent played rock There's no winner. Try again! Choose your play: Enter 1 for rock; Enter 2 for paper; Enter 3 for scissors; Enter 4 to exit: 1 You played rock; your opponent played scissors Congratulations, you won! Choose your play: Enter 1 for rock; Enter 2 for paper; Enter 3 for scissors; Enter 4 to exit: 1 You played rock; your opponent played paper Sorry, you lost! Choose your play: Enter 1 for rock; Enter 2 for paper; Enter 3 for scissors; Enter 4 to exit: 4 Game statistics: Games played: 8 You won: 1 (12.5%) You lost: 1 (12.5%) No winner: 6 (75.0%) Thanks for playing. Goodbye! >BTW: the stats shown aren't correct because I omitted some games that were redundant.
Your file must compile and run before submission. It must also contain a header with the following format:
# File: Project1.py # Student: # UT EID: # Course Name: CS303E # # Date: # Description of Program:
This is a common feature of programming: you need to choose the appropriate type for a value. Think about how it's going to be used. Don't make unnecessary conversions.
Using literal constants: If you are using the same literal data multiple times, it's a good idea to define it as a constant. For example, this program uses '1' to represent rock, '2' for paper, and '3' for scissors. It would be easy to forget this, or to type 1 when you mean '1'. A way to reduce such errors and make your code easier to read is to use symbolic constants. For example:
ROCK = '1' PAPER = '2' ...Then, we know for example that play1 defeats play2 if:
play1 == PAPER and play2 == ROCKamong other possibilities. By convention, you should put your symbolic constants near the top of your program and use uppercase names. (From Python's perspective, they're just variables and you could re-assign them; the uppercase convention reminds you not to do that.)
Another place to use symbolic constants is for messages output by your program. If you define them once near the start of your program, you won't risk mistyping them later (as often happens):
GOODBYE_MESSAGE = "Thanks for playing. Goodbye!"Then, instead of
print( "Thanks for playing. Goodbye!" )you'd type
print( GOODBYE_MESSAGE )That way, if you decide later to change the message (because you noticed that you put two spaces after the period instead of one) you just have to fix it in one place. Strictly speaking, there's no need to do this for a message you're only printing once, but it's probably still a pretty good idea. That way, you have all of the messages collected in one place and it's easy to change one or more without searching through the code. This may not seem so useful for a small program; it's absolutely crucial on large projects.