Help with classes - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Help with classes (/thread-15928.html) |
Help with classes - lucaswinnerton - Feb-06-2019 Hi everyone! I've created a noughts and crosses game in Python, and I can't figure out the best way to eliminate global variables. I'm not sure what variables to instantiate or methods to have in my class. Any help would be great! I am aware that my code doesn't follow PEP 8, I'm just trying to get rid of the global variables right now. import time import random def reset_values(): global BOARD, INPUTS, PLAYER_SYMBOLS, draw_count, computer_level, MAIN_TEXT BOARD = [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]] INPUTS = [{"row": 0, "column": 0}, {"row": 0, "column": 1}, {"row": 0, "column": 2}, {"row": 1, "column": 0}, {"row": 1, "column": 1}, {"row": 1, "column": 2}, {"row": 2, "column": 0}, {"row": 2, "column": 1}, {"row": 2, "column": 2}] PLAYER_SYMBOLS = {"O": "noughts", "X": "crosses"} draw_count = 0 computer_level = 0 MAIN_TEXT = """ ┌───────────────────────────────┐ │Welcome to noughts and crosses!│ │Press Q in any prompt to quit. │ └───────────────────────────────┘""" def computer_player(): """ Runs the player vs computer game. Calls other functions in a while True loop. """ while True: c_get_level() c_get_symbol() c_print_symbols() c_get_start() number_board() print_board() reset_board() while True: c_get_square() check_end() c_computer_move() check_end() def c_get_level(): global computer_level while True: wait() level_input = input("\nWhat level would you like the computer to play at? (1/2/3) ") wait() if level_input in ("1", "2", "3"): computer_level = int(level_input) break elif level_input in ("H", "h"): print("You need to enter either 1, 2 or 3 here. This will decide the level that the computer will") else: invalid_input() def c_get_symbol(): """ Gets player's input for their character """ global player_symbol, computer_symbol while True: wait() symbol_input = input("\nWould you like to be noughts or crosses? (O/X) ") wait() if symbol_input in ("O", "o", "0"): player_symbol = "O" computer_symbol = "X" number_board() break elif symbol_input in ("X", "x"): player_symbol = "X" computer_symbol = "O" number_board() break elif symbol_input in ("Q", "q"): quit_program() else: invalid_input() def c_print_symbols(): print("\n\ ┌───────────────────────┐\n\ │Player 1 is " + PLAYER_SYMBOLS[player_symbol] + " " + "(" + player_symbol + ")" + "│\n\ │Computer is " + PLAYER_SYMBOLS[computer_symbol] + " " + "(" + computer_symbol + ")" + "│\n\ └───────────────────────┘") def c_get_start(): """ Ask the user if they want to start the game. Either restarts or quits if they don't. """ while True: wait() start_input = input("\nWould you like to start the game? (Y/N) ") wait() if start_input in ("Y", "y"): break elif start_input in ("N", "n"): quit_program() elif start_input in ("H", "h"): print("You need to enter either Y or N here. Y will start the game and N will quit it.") else: invalid_input() def reset_board(): """ Initialise the board to empty spaces. ┌───┬───┬───┐ │ │ │ │ ├───┼───┼───┤ │ │ │ │ ├───┼───┼───┤ │ │ │ │ └───┴───┴───┘ """ global BOARD BOARD = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]] def number_board(): """ Initialise the board to numbers. ┌───┬───┬───┐ │ 1 │ 2 │ 3 │ ├───┼───┼───┤ │ 4 │ 5 │ 6 │ ├───┼───┼───┤ │ 7 │ 8 │ 9 │ └───┴───┴───┘ """ global BOARD BOARD = [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]] def print_board(): """ Draw the board with the characters in the BOARD list. """ global BOARD wait() row_count = 0 print("\n┌───┬───┬───┐") # print first line (row_count = 0) for line in BOARD: print("│ ", end = "") # print first vertical separator and space row_count += 1 # 1, 2, 3 for item in line: print(item, end = " │ ") # print symbol, a space, a vertical separator and a space if row_count in (1, 2): print("\n├───┼───┼───┤") # print middle lines (row_count = 1, 2) elif row_count == 3: print("\n└───┴───┴───┘\n") # print last line (row_count = 3) wait() def c_get_square(): """ Get player's square and check if it's legal. """ global BOARD while True: square_input = input("What square would you like to choose? (1-9) ") if square_input in ("1", "2", "3", "4", "5", "6", "7", "8", "9"): pass else: invalid_input() continue if BOARD[INPUTS[int(square_input) - 1]["row"]][INPUTS[int(square_input) - 1]["column"]] in ("X", "O"): print("\nSorry, you have put a symbol in the same place as another!\n") else: BOARD[INPUTS[int(square_input) - 1]["row"]][INPUTS[int(square_input) - 1]["column"]] = player_symbol break print_board() def c_computer_move(): if computer_level == 1: while True: computer_move = random.randint(1, 9) computer_row = INPUTS[computer_move - 1]["row"] computer_col = INPUTS[computer_move - 1]["column"] if BOARD[computer_row][computer_col] in ("X", "O"): continue else: BOARD[computer_row][computer_col] = computer_symbol break print_board() ## if computer_level == 2: ## ## while True: ## if def check_end(): global BOARD global draw_count while True: if BOARD[0][0] == BOARD[0][1] == BOARD[0][2] != " ": state_win() elif BOARD[1][0] == BOARD[1][1] == BOARD[1][2] != " ": state_win() elif BOARD[2][0] == BOARD[2][1] == BOARD[2][2] != " ": state_win() elif BOARD[0][0] == BOARD[1][0] == BOARD[2][0] != " ": state_win() elif BOARD[0][1] == BOARD[1][1] == BOARD[2][1] != " ": state_win() elif BOARD[0][2] == BOARD[1][2] == BOARD[2][2] != " ": state_win() elif BOARD[0][0] == BOARD[1][1] == BOARD[2][2] != " ": state_win() elif BOARD[0][2] == BOARD[1][1] == BOARD[2][0] != " ": state_win() else: break while True: for row in BOARD: for symbol in row: if symbol != " ": draw_count += 1 if draw_count == 9: state_draw() else: pass else: break break break break def state_win(): print("\n\ ┌────────┐\n\ │YOU WON!│\n\ └────────┘\n") while True: restart_input = input("Do you want to play again? (Y/N) ") if restart_input in ("Y", "y"): wait() print("Restarting the game...") wait() computer_player() elif restart_input in ("N", "n"): quit_program() else: wait() invalid_input() def state_draw(): print("\n\ ┌────────────┐\n\ │It's a draw!│\n\ └────────────┘\n") while True: restart_input = input("Do you want to play again? (Y/N) ") if restart_input in ("Y", "y"): restart_calculator() elif restart_input in ("N", "n"): quit_program() else: wait() invalid_input() def quit_program(): while True: quit_input = input("Do you want to quit the game (Y/N)? ") if quit_input in ("Y", "y"): wait() print("\nNow quitting the game", end="") print_dots() wait() raise SystemExit elif quit_input in ("N", "n"): wait() print("Restarting the game...") wait() computer_player() else: wait() invalid_input() def restart_calculator(): wait() print("\nRestarting the game", end="") print_dots() wait() computer_player() def print_dots(): wait() for _ in range(3): print(".", end="", flush=True) wait() def wait(): time.sleep(0.25) def invalid_input(): wait() print("\nYou have entered an invalid response. Enter H for help.\n") computer_player() RE: Help with classes - woooee - Feb-06-2019 Quote:I'm not sure what variables to instantiate or methods to have in my class.All of them. BTW you instantiate a class, not a variable. RE: Help with classes - Larz60+ - Feb-06-2019 Your code doesn't run as presented: So you will have to fix errors in class as well.** Note ** I have not attempted to make code any more efficient, but there is room for improvement. Again you will need to fix errors: import time import random class NoughtsAndCrosses: def __init__(self): self.Board = None self.draw_count = None self.INPUTS = None self.PLAYER_SYMBOLS = None self.computer_level = None self.MAIN_TEXT = None self.computer_symbol = None self.player_symbol = None self.reset_values() self.computer_player() def reset_values(self): self.BOARD = [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]] self.INPUTS = [{"row": 0, "column": 0}, {"row": 0, "column": 1}, {"row": 0, "column": 2}, {"row": 1, "column": 0}, {"row": 1, "column": 1}, {"row": 1, "column": 2}, {"row": 2, "column": 0}, {"row": 2, "column": 1}, {"row": 2, "column": 2}] self.PLAYER_SYMBOLS = {"O": "noughts", "X": "crosses"} self.draw_count = 0 self.computer_level = 0 self.MAIN_TEXT = """ ┌───────────────────────────────┐ │Welcome to noughts and crosses!│ │Press Q in any prompt to quit. │ └───────────────────────────────┘""" def computer_player(self): """ Runs the player vs computer game. Calls other functions in a while True loop. """ while True: self.c_get_level() self.c_get_symbol() self.c_print_symbols() self.c_get_start() self.number_board() self.print_board() self.reset_board() while True: self.c_get_square() self.check_end() self.c_computer_move() self.check_end() def c_get_level(self): while True: self.wait() level_input = input("\nWhat level would you like the computer to play at? (1/2/3) ") self.wait() if level_input in ("1", "2", "3"): self.computer_level = int(level_input) break elif level_input in ("H", "h"): print("You need to enter either 1, 2 or 3 here. This will decide the level that the computer will") else: self.invalid_input() def c_get_symbol(self): """ Gets player's input for their character """ while True: self.wait() symbol_input = input("\nWould you like to be noughts or crosses? (O/X) ") self.wait() if symbol_input in ("O", "o", "0"): self.player_symbol = "O" self.computer_symbol = "X" self.number_board() break elif symbol_input in ("X", "x"): player_symbol = "X" computer_symbol = "O" self.number_board() break elif symbol_input in ("Q", "q"): self.quit_program() else: self.invalid_input() def c_print_symbols(self): print("\n\ ┌───────────────────────┐\n\ │Player 1 is " + self.PLAYER_SYMBOLS[self.player_symbol] + " " + "(" + self.player_symbol + ")" + "│\n\ │Computer is " + self.PLAYER_SYMBOLS[self.computer_symbol] + " " + "(" + self.computer_symbol + ")" + "│\n\ └───────────────────────┘") def c_get_start(self): """ Ask the user if they want to start the game. Either restarts or quits if they don't. """ while True: self.wait() start_input = input("\nWould you like to start the game? (Y/N) ") self.wait() if start_input in ("Y", "y"): break elif start_input in ("N", "n"): self.quit_program() elif start_input in ("H", "h"): print("You need to enter either Y or N here. Y will start the game and N will quit it.") else: self.invalid_input() def reset_board(self): """ Initialise the board to empty spaces. ┌───┬───┬───┐ │ │ │ │ ├───┼───┼───┤ │ │ │ │ ├───┼───┼───┤ │ │ │ │ └───┴───┴───┘ """ self.BOARD = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]] def number_board(self): """ Initialise the board to numbers. ┌───┬───┬───┐ │ 1 │ 2 │ 3 │ ├───┼───┼───┤ │ 4 │ 5 │ 6 │ ├───┼───┼───┤ │ 7 │ 8 │ 9 │ └───┴───┴───┘ """ self.BOARD = [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]] def print_board(self): """ Draw the board with the characters in the BOARD list. """ self.wait() row_count = 0 print("\n┌───┬───┬───┐") # print first line (row_count = 0) for line in self.BOARD: print("│ ", end = "") # print first vertical separator and space row_count += 1 # 1, 2, 3 for item in line: print(item, end = " │ ") # print symbol, a space, a vertical separator and a space if row_count in (1, 2): print("\n├───┼───┼───┤") # print middle lines (row_count = 1, 2) elif row_count == 3: print("\n└───┴───┴───┘\n") # print last line (row_count = 3) self.wait() def c_get_square(self): """ Get player's square and check if it's legal. """ while True: square_input = input("What square would you like to choose? (1-9) ") if square_input in ("1", "2", "3", "4", "5", "6", "7", "8", "9"): pass else: self.invalid_input() continue if self.BOARD[self.INPUTS[int(square_input) - 1]["row"]][self.INPUTS[int(square_input) - 1]["column"]] in ("X", "O"): print("\nSorry, you have put a symbol in the same place as another!\n") else: self.BOARD[self.INPUTS[int(square_input) - 1]["row"]][self.INPUTS[int(square_input) - 1]["column"]] = self.player_symbol break self.print_board() def c_computer_move(self): if self.computer_level == 1: while True: computer_move = random.randint(1, 9) computer_row = self.INPUTS[computer_move - 1]["row"] computer_col = self.INPUTS[computer_move - 1]["column"] if self.BOARD[computer_row][computer_col] in ("X", "O"): continue else: self.BOARD[computer_row][computer_col] = self.computer_symbol break self.print_board() ## if computer_level == 2: ## ## while True: ## if def check_end(self): draw_count = self.draw_count while True: if self.BOARD[0][0] == self.BOARD[0][1] == self.BOARD[0][2] != " ": self.state_win() elif self.BOARD[1][0] == self.BOARD[1][1] == self.BOARD[1][2] != " ": self.state_win() elif self.BOARD[2][0] == self.BOARD[2][1] == self.BOARD[2][2] != " ": self.state_win() elif self.BOARD[0][0] == self.BOARD[1][0] == self.BOARD[2][0] != " ": self.state_win() elif self.BOARD[0][1] == self.BOARD[1][1] == self.BOARD[2][1] != " ": self.state_win() elif self.BOARD[0][2] == self.BOARD[1][2] == self.BOARD[2][2] != " ": self.state_win() elif self.BOARD[0][0] == self.BOARD[1][1] == self.BOARD[2][2] != " ": self.state_win() elif self.BOARD[0][2] == self.BOARD[1][1] == self.BOARD[2][0] != " ": self.state_win() else: break while True: for row in self.BOARD: for symbol in row: if symbol != " ": draw_count += 1 if draw_count == 9: self.state_draw() else: pass else: break break break break def state_win(self): print("\n\ ┌────────┐\n\ │YOU WON!│\n\ └────────┘\n") while True: restart_input = input("Do you want to play again? (Y/N) ") if restart_input in ("Y", "y"): self.wait() print("Restarting the game...") self.wait() self.computer_player() elif restart_input in ("N", "n"): self.quit_program() else: self.wait() self.invalid_input() def state_draw(self): print("\n\ ┌────────────┐\n\ │It's a draw!│\n\ └────────────┘\n") while True: restart_input = input("Do you want to play again? (Y/N) ") if restart_input in ("Y", "y"): self.restart_calculator() elif restart_input in ("N", "n"): self.quit_program() else: self.wait() self.invalid_input() def quit_program(self): while True: quit_input = input("Do you want to quit the game (Y/N)? ") if quit_input in ("Y", "y"): self.wait() print("\nNow quitting the game", end="") self.print_dots() self.wait() raise SystemExit elif quit_input in ("N", "n"): self.wait() print("Restarting the game...") self.wait() self.computer_player() else: self.wait() self.invalid_input() def restart_calculator(self): self.wait() print("\nRestarting the game", end="") self.print_dots() self.wait() self.computer_player() def print_dots(self): self.wait() for _ in range(3): print(".", end="", flush=True) self.wait() def wait(self): time.sleep(0.25) def invalid_input(self): self.wait() print("\nYou have entered an invalid response. Enter H for help.\n") if __name__ == '__main__': NoughtsAndCrosses() RE: Help with classes - lucaswinnerton - Feb-06-2019 Larz60+, Thanks for the help! Yeah, there are some errors that I need to fix. Is it worth eliminating all the global variables for the extra use of self? It seems like self is overused in all the functions. And if the class is only being used for global variables and calling functions, does it really count as a class? Thanks! RE: Help with classes - woooee - Feb-06-2019 You want to start using a class for all of your programs. It eliminates a lot of the stuff that is a pain, like keeping track of globals. RE: Help with classes - lucaswinnerton - Feb-06-2019 woooee, Thanks for the help! Does it really count as a class, however, seeing as it's only being used for the purpose of removing global variables? And I seem to be overusing "self" a lot when I use a class; is there any way to avoid this? RE: Help with classes - Larz60+ - Feb-07-2019 self doesn't cost anything removing global variables is worth it. As you write larger and larger code, sooner or later a global will burn you badly. consider the following where two programmers are working on the same code. both use the same global variable, but in different functions. Programmer A changes the global variable. Programmer B had changed the global variable at the start of his routine, prior to the change that programmer A made. Next, based on the value in the global, programmer B executes code that erases backup files. Not good |