attached
hgp/.DS_Store hgp/coordinates.py import math class Coordinate: def __init__(self, frac: (float, float), absolute: (int, int), absolute_size: (int, int)): if frac == None: abs_x, abs_y = absolute abs_size_x, abs_size_y = absolute_size self.frac_x = abs_x / abs_size_x self.frac_y = abs_y / abs_size_y else: frac_x, frac_y = frac self.frac_x = frac_x self.frac_y = frac_y def frac(self) -> (float, float): return (self.frac_x, self.frac_y) def absolute(self, absolute_size: (int, int)) -> (int, int): abs_size_x, abs_size_y = absolute_size return (int(self.frac_x * abs_size_x), int(self.frac_y * abs_size_y)) def frac_distance_from(self, c: 'coord') -> float: return math.sqrt( (self.frac_x - c.frac_x) * (self.frac_x - c.frac_x) + (self.frac_y - c.frac_y) * (self.frac_y - c.frac_y)) def from_frac(frac: (float, float)) -> Coordinate: return Coordinate(frac, None, None) def from_absolute(absolute: (int, int), absolute_size: (int, int)) -> Coordinate: return Coordinate(None, absolute, absolute_size) hgp/hgp.docx hgp/Reversi.py import tkinter import coordinates import ReversiLogic from tkinter import ttk import tkinter.messagebox from collections import namedtuple Params = namedtuple('Params', 'rows cols first top_left win') # Options Menu that allows the user to specify the behaviour of the Reversi Game #TODO: Modify this function to add widgets that will set the parameters of the game #TODO: Assign the chosen parameters to variables #TODO: Set a title for this window #TODO: Add a button to set chosen parameters and close the window class OptionsMenu: def __init__(self): self._root_window = tkinter.Tk() self._params = None self._ComboBoxList = [] self._root_window.wm_title('Reversi Options') Labels = ['Rows', 'Columns', 'First Move', 'Top Left Piece', 'Win'] Values = [['4', '6', '8', '10', '12', '14', '16'], ['4', '6', '8', '10', '12', '14', '16'], ['Black', 'White'], ['Black', 'White'], ['Most Discs', 'Fewest Discs']] self._Header_label = ttk.Label(master=self._root_window, text='Reversi Options') self._Header_label.grid(row=0, column=0, pady=10, sticky=tkinter.N + tkinter.S) for i in range(0, 5): self._label = ttk.Label(master=self._root_window, text=Labels[i]) self._label.grid(row=i + 1, column=0, padx=(5, 10), pady=5, sticky=tkinter.W + tkinter.E) self._DropDown = ttk.Combobox(master=self._root_window, values=Values[i], state='readonly') self._DropDown.set(Values[i][0]) self._DropDown.grid(row=i + 1, column=0, padx=(100, 5), pady=5, sticky=tkinter.E + tkinter.W) self._ComboBoxList.append(self._DropDown) self._root_window.rowconfigure(i, weight=1) self._root_window.columnconfigure(0, weight=1) self._Button1 = ttk.Button(master=self._root_window, text='Enter', cursor='pirate', command=self._combine) self._Button1.grid(row=6, column=0, pady=10, sticky=tkinter.N + tkinter.S) #start function, COMPLETE, DO NOT MODIFY def start(self) -> None: self._root_window.mainloop() #function called if the button has been clicked in the Options Menu using the (command _combine), # and sets the parameters for the game #TODO: Complete this function to fetch and save parameters to a variable def _on_enter_clicked(self) -> None: #TODO: destroy root window def _close(self) -> None: #Returns parameters, COMPLETE, DO NOT MODIFY def get_params(self) -> None: return self._params #TODO: call the two previous functions (_on_enter_clicked and _close) def _combine(self) -> None: # Draws the Game Board based around the Game Logic class GameBoard: class Square: # Square objects keep track of where they were drawn #COMPLETE, No Modification required def __init__(self, top_left: tuple, bottom_right: tuple, width: float, height: float, i: int, j: int): self._top_left = top_left self._bottom_right = bottom_right self._width = width self._height = height self._i = i self._j = j self._min_x, self._min_y = self._top_left.frac() self._max_x, self._max_y = self._bottom_right.frac() #TODO: Complete this function to detect a click in the square def click_in_square(self, x: float, y: float) -> None: return False #always returns false, change this to return true if click is within square #Return Indexes I and J, COMPLETE def return_index(self) -> list: return [self._j, self._i] #Initialise GameBoard #TODO: complete tasks as per specification def __init__(self, rows: int, cols: int, params: list): self._root_window = tkinter.Tk() self._params = params self._rows = int(rows) self._cols = int(cols) self._root_window.wm_title('Reversi Game') self._canvas = tkinter.Canvas(master=self._root_window, width=500, height=400) self._Game = ReversiLogic.ReversiGame() self._Game.set_turn(self._params.first) self._Game.rows_cols(self._cols, self._rows) self._Game.game_board(self._params.top_left) self._canvas.grid(row=1, column=0, padx=10, pady=10, sticky=tkinter.N + tkinter.S + tkinter.W + tkinter.E) self._show_game_info().grid(row=0, column=0, padx=5, pady=5, sticky=tkinter.N + tkinter.S) self._canvas.configure(highlightbackground='black', highlightthickness=1) self._canvas.bind('
', self._on_window_resized) self._canvas.bind('', self._on_mouse_click) self._root_window.rowconfigure(0, weight=0) self._root_window.rowconfigure(1, weight=1) self._root_window.columnconfigure(0, weight=1) #TODO: When window is resized, redraw board def _on_window_resized(self, event: tkinter.Event) -> None: self._draw_board() #TODO: When mouse click is detected, check which square was clicked #TODO: Move if valid def _on_mouse_click(self, event: tkinter.Event) -> None: x = event.x y = event.y for square in self._squares: if square.click_in_square(x, y) == True: move = square.return_index() if self._Game.determine_valid_moves('black') == False and self._Game.determine_valid_moves( 'white') == False: self._winner.set('Winner: ' + self._Game.determine_winner(self._params.win)) elif self._Game.determine_valid_moves(self._Game.current_turn()) == False: tkinter.messagebox.showinfo(title='Pass', message=self._Game.current_turn() + ' Passes!') self._Game.switch_turn() self._draw_board() elif self._Game.flip_check(move[0], move[1], self._Game.current_turn()) != []: self._Game.move(move[0], move[1])