Jun-04-2020, 01:41 PM
As always, I welcome feedback.
#! /usr/bin/env python3 # Do the imports import os import tkinter as tk from tkinter import messagebox from functools import partial import random as rnd # Used to close the register window without causing an error in console def close(event): os.sys.exit() # Define player class with some set values class Player: player_name = '' player_wins = 0 player_loss = 0 player_ties = 0 games_played = 0 # Define the game class class Game: def __init__(self, parent): # Set the parent window and ask for player name self.parent = parent self.register() # Function creates a form to get a player name def register(self): self.form = tk.Toplevel(None) self.form.geometry('+340+200') self.form.title('Player Name') self.form.configure(padx=10, pady=10) self.name_label = tk.Label(self.form, text='Enter Player Name', anchor='w', fg='blue', width=25) self.name_label.grid(column=0, row=0, sticky='nw', pady=5, columnspan=2) self.name_entry = tk.Entry(self.form, width=25) self.name_entry.grid(column=0, row=1, columnspan=2) self.name_entry.focus() self.quit_btn = tk.Button(self.form, text='Cancel', fg='red', command=os.sys.exit) self.quit_btn.grid(column=0, row=2, pady=5, sticky='w') self.btn = tk.Button(self.form, fg='green', text='Submit', command=partial(self.getname)) self.btn.grid(column=1, row=2, pady=5, sticky='e') # Some bind keys player can use the enter keys instead of clicking buttons self.form.bind('<Return>', self.getname) self.form.bind('<KP_Enter>', self.getname) self.form.bind('<Escape>', close) self.form.protocol('WM_DELETE_WINDOW', os.sys.exit) self.parent.withdraw() self.form.mainloop() # Handles the form processing def getname(self, event): # Convert the form entry to a simple variable name = self.name_entry.get() # Check to see if the name is empty. If empty throw an error. if not name: msg = messagebox.showwarning(title='No Name Entered', message='You must enter a name to play.') # See if the name is greater than 8 characters. If true throw an error. elif len(name) > 8: msg = messagebox.showwarning(title='Name is too long.', \ message='Names must be 1 - 8 charcters in length.') # This is just to clear the form self.form.destroy() self.register() # Every thing ok go to the game else: # Setup player instances self.player = Player() self.player.player_name = name.strip().title() self.computer = Player() self.computer.player_name = 'Computer' # Pull the root window back up, destroy the form window, and initiate the game board self.parent.deiconify() self.form.destroy() self.board() # This function get the percentages of wins. def get_percentage(self, num1, num2, num3): try: total = num1 / (num1 + num2 + num3) return format(total, '.0%') except ZeroDivisionError: return format(0, '.0%') # Defines the game play def play(self, player_choice): # Player choices options = ['rock', 'paper', 'scissors'] # declare empty variable for later use msg = '' # Get the computers choice computer_choice = rnd.choice(options) # Get the players choice player_choice = player_choice # Do the comparison and get the winner. Display messages and update the win/losses if player_choice == 'rock' and computer_choice == 'scissors': self.player.player_wins += 1 self.players_wins['text'] = f'{self.player.player_wins} / {self.get_percentage(self.player.player_wins, self.player.player_loss, self.player.player_ties)}' self.msgbox['text'] = f'Status: {self.player.player_name.title()} wins! Rock Crushes Scissors.' self.computer.player_loss += 1 self.computers_loss['text'] = f'{self.computer.player_loss} / {self.get_percentage(self.computer.player_loss, self.computer.player_wins, self.computer.player_ties)}' print('player wins') elif player_choice == 'paper' and computer_choice == 'rock': self.player.player_wins += 1 self.players_wins['text'] = f'{self.player.player_wins} / {self.get_percentage(self.player.player_wins, self.player.player_loss, self.player.player_ties)}' self.msgbox['text'] = f'Status: {self.player.player_name.title()} wins! Paper Covers Rock.' self.computer.player_loss += 1 self.computers_loss['text'] = f'{self.computer.player_loss} / {self.get_percentage(self.computer.player_loss, self.computer.player_wins, self.computer.player_ties)}' print('player wins') elif player_choice == 'scissors' and computer_choice == 'paper': self.player.player_wins += 1 self.players_wins['text'] = f'{self.player.player_wins} / {self.get_percentage(self.player.player_wins, self.player.player_loss, self.player.player_ties)}' self.msgbox['text'] = f'Status: {self.player.player_name.title()} wins! Scissors Cut Paper.' self.computer.player_loss += 1 self.computers_loss['text'] = f'{self.computer.player_loss} / {self.get_percentage(self.computer.player_loss, self.computer.player_wins, self.computer.player_ties)}' print('player wins') elif computer_choice == 'rock' and player_choice == 'scissors': self.msgbox['text'] = f'Status: Computer wins! Rock crushes Scissors' self.computer.player_wins += 1 self.computers_wins['text'] = f'{self.computer.player_wins} / {self.get_percentage(self.computer.player_wins, self.computer.player_loss, self.computer.player_ties)}' self.player.player_loss += 1 self.players_loss['text'] = f'{self.player.player_loss} / {self.get_percentage(self.player.player_loss, self.player.player_wins, self.player.player_ties)}' elif computer_choice == 'paper' and player_choice == 'rock': self.msgbox['text'] = f'Status: Computer wins! Paper Covers Rock' self.computer.player_wins += 1 self.computers_wins['text'] = f'{self.computer.player_wins} / {self.get_percentage(self.computer.player_wins, self.computer.player_loss, self.computer.player_ties)}' self.player.player_loss += 1 self.players_loss['text'] = f'{self.player.player_loss} / {self.get_percentage(self.player.player_loss, self.player.player_wins, self.player.player_ties)}' elif computer_choice == 'scissors' and player_choice == 'paper': self.msgbox['text'] = f'Status: Computer wins! Scissors Cuts Paper.' self.computer.player_wins += 1 self.computers_wins['text'] = f'{self.computer.player_wins} / {self.get_percentage(self.computer.player_wins, self.computer.player_loss, self.computer.player_ties)}' self.player.player_loss += 1 self.players_loss['text'] = f'{self.player.player_loss} / {self.get_percentage(self.player.player_loss, self.player.player_wins, self.player.player_ties)}' else: self.computer.player_ties += 1 self.player.player_ties += 1 self.msgbox['text'] = f'Status: {self.player.player_name.title()} and Computer have tied. No winner.' print('tie game') # Keep track of played games self.player.games_played += 1 self.played_games['text'] = f'Games Played: ( {self.player.games_played} )' # Define the game window # This sets up all the frames and widget for the game window def board(self): try: mainframe = tk.Frame(self.parent) mainframe.grid(column=0, row=0, sticky='new') headerframe = tk.Frame(mainframe) headerframe['padx'] = 8 headerframe['pady'] = 5 headerframe['relief'] = 'ridge' headerframe['borderwidth'] = 2 headerframe.grid(column=0, row=0) header = tk.Label(headerframe, anchor='n') header['text'] = 'Rock Paper Scissors' header['font'] = 'serif 18 bold' header['fg'] = 'indianred' header['relief'] = 'ridge' header['padx'] = 2 header['pady'] = 2 header['width'] = 21 header.grid(column=0, row=0, ipady=3, ipadx=8) dataframe = tk.Frame(mainframe) dataframe['padx'] = 2 dataframe['pady'] = 2 dataframe['relief'] = 'ridge' dataframe['borderwidth'] = 2 dataframe['width'] = 21 dataframe.grid(column=0, row=1, sticky='new') data_header_player = tk.Label(dataframe, anchor='w') data_header_player['text'] = 'Player Name' data_header_player['font'] = 'serif 10 bold' data_header_player['fg'] = 'navy' data_header_player['relief'] = 'ridge' data_header_player['padx'] = 7 data_header_player['pady'] = 0 data_header_player['borderwidth'] = 1 data_header_player['width'] = 11 data_header_player.grid(column=0, row=0, ipady=3, ipadx=8) data_header_wins = tk.Label(dataframe, anchor='w') data_header_wins['text'] = 'Wins / %' data_header_wins['font'] = 'serif 10 bold' data_header_wins['fg'] = 'navy' data_header_wins['relief'] = 'ridge' data_header_wins['padx'] = 7 data_header_wins['pady'] = 0 data_header_wins['borderwidth'] = 1 data_header_wins['width'] = 11 data_header_wins.grid(column=1, row=0, ipady=3, ipadx=8, sticky='nw') data_header_loss = tk.Label(dataframe, anchor='w') data_header_loss['text'] = 'Loose / %' data_header_loss['font'] = 'serif 10 bold' data_header_loss['fg'] = 'navy' data_header_loss['relief'] = 'ridge' data_header_loss['padx'] = 7 data_header_loss['pady'] = 0 data_header_loss['borderwidth'] = 1 data_header_loss['width'] = 11 data_header_loss.grid(column=2, row=0, ipady=3, ipadx=8, sticky='nw') computers = tk.Label(dataframe, anchor='w') computers['text'] = self.computer.player_name computers['font'] = 'serif 8 bold' computers['fg'] = 'purple' computers['relief'] = 'ridge' computers['padx'] = 7 computers['pady'] = 1 computers['borderwidth'] = 1 computers.grid(column=0, row=1, ipady=3, ipadx=8, sticky='new') self.computers_wins = tk.Label(dataframe, anchor='w') self.computers_wins['text'] = f'0 / 0%' self.computers_wins['font'] = 'sans 9 normal' self.computers_wins['fg'] = 'purple' self.computers_wins['relief'] = 'ridge' self.computers_wins['padx'] = 7 self.computers_wins['pady'] = 0 self.computers_wins['borderwidth'] = 1 self.computers_wins.grid(column=1, row=1, ipady=3, ipadx=8, sticky='new') self.computers_loss = tk.Label(dataframe, anchor='w') self.computers_loss['text'] = f'0 / 0%' self.computers_loss['font'] = 'sans 9 normal' self.computers_loss['fg'] = 'purple' self.computers_loss['relief'] = 'ridge' self.computers_loss['padx'] = 7 self.computers_loss['pady'] = 0 self.computers_loss['borderwidth'] = 1 self.computers_loss.grid(column=2, row=1, ipady=3, ipadx=8, sticky='new') players = tk.Label(dataframe, anchor='w') players['text'] = self.player.player_name players['font'] = 'serif 8 bold' players['fg'] = 'blue' players['relief'] = 'ridge' players['padx'] = 7 players['pady'] = 0 players['borderwidth'] = 1 players.grid(column=0, row=2, ipady=3, ipadx=8, sticky='news') self.players_wins = tk.Label(dataframe, anchor='w') self.players_wins['text'] = f'0 / 0%' self.players_wins['font'] = 'sans 9 normal' self.players_wins['fg'] = 'blue' self.players_wins['relief'] = 'ridge' self.players_wins['padx'] = 7 self.players_wins['pady'] = 0 self.players_wins['borderwidth'] = 1 self.players_wins.grid(column=1, row=2, ipady=3, ipadx=8, sticky='news') self.players_loss = tk.Label(dataframe, anchor='w') self.players_loss['text'] = f'0 / 0%' self.players_loss['font'] = 'sans 9 normal' self.players_loss['fg'] = 'blue' self.players_loss['relief'] = 'ridge' self.players_loss['padx'] = 7 self.players_loss['pady'] = 0 self.players_loss['borderwidth'] = 1 self.players_loss.grid(column=2, row=2, ipady=3, ipadx=8, sticky='news') messageframe = tk.Frame(mainframe, borderwidth=3, relief='ridge') messageframe.grid(column=0, row=2, sticky='new') messageframe.grid_columnconfigure(0, weight=3) self.msgbox = tk.Label(messageframe, fg='brown', font='sans 9 normal', anchor='w', borderwidth=2, relief='ridge') self.msgbox['text'] ='Status:' self.msgbox.grid(column=0, row=0, padx=2, sticky='ew') self.played_games = tk.Label(messageframe, fg='brown', font='sans 9 normal', anchor='w', borderwidth=2, relief='ridge') self.played_games['text'] = f'Games Played: 0' self.played_games.grid(column=0, row=1, padx=2, sticky='ew') buttonsframe = tk.Frame(mainframe, borderwidth=3, relief='ridge', bg='grey86') buttonsframe.grid(column=0, row=3, sticky='new') rock_btn = tk.Button(buttonsframe, text='Rock', width=7, command=partial(self.play, 'rock')) rock_btn.grid(column=0, row=0, padx=2) paper_btn = tk.Button(buttonsframe, text='Paper', width=7, command=partial(self.play, 'paper')) paper_btn.grid(column=1, row=0, padx=2) scissors_btn = tk.Button(buttonsframe, text='Scissors', width=7, command=partial(self.play, 'scissors')) scissors_btn.grid(column=2, row=0, padx=2) spacer = tk.Frame(buttonsframe, width=74) spacer.grid(column=3, row=0) quit_btn = tk.Button(buttonsframe, text='Quit', fg='red', command=os.sys.exit) quit_btn.grid(column=4, row=0) # os.sys.exit() except ValueError as error: print(f'Error!: {error}') os.sys.exit() def main(): root = tk.Tk() root.title('Rock, Paper, and Scissors') Game(root) root.mainloop() if __name__ == '__main__': main()