We give you the main function, and basic board setup. You have to write the brains inside the box! As always, attempt to program the functions in the order we give them. Do not attempt to program the second funtion until the first one is passing, or the third until the second is passing, etc.Dots and boxes is a classic mathy game. To see how to play, read this diagram left to right, row by row:
Usage: ksquares.py """ from typing import List, TextIO, Tuple, Callable import docopt # type: ignore class Box: """This class exists primarily to override the [] operator""" def __init__ XXXXXXXXXXself, XXXXXXXXXXl: bool = False, XXXXXXXXXXr: bool = False, XXXXXXXXXXu: bool = False, XXXXXXXXXXd: bool = False, XXXXXXXXXXowner: str = " ", ) -> None: """ XXXXXXXXXXPurpose: Initializes a box XXXXXXXXXXFalse - unmarked, True - marked XXXXXXXXXXParameters: Each side as a bool, player-owner XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: None XXXXXXXXXXModifies: Creates a box instance, with members: XXXXXXXXXXleft, right, up, down, owner XXXXXXXXXXCalls: basic python XXXXXXXXXXTests: 01_class_box.py XXXXXXXXXXUsage: >>> a_box = Box(True, True, True, False, "C") >>> a_box.left XXXXXXXXXXTrue >>> a_box.down XXXXXXXXXXFalse >>> a_box.owner 'C' """ XXXXXXXXXXpass def __getitem__(self, key: str) -> bool: """ XXXXXXXXXXPurpose: Overloads get bracket operator [] for Box XXXXXXXXXXParameters: key (direction) as L, R, U, or D XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: bool (the relevant side of the box XXXXXXXXXXModifies: Nothing XXXXXXXXXXCalls: Basic python XXXXXXXXXXTests: 01_class_box.py XXXXXXXXXXUsage: >>> a_box = Box(True, True, True, False, "C") >>> a_box["R"] XXXXXXXXXXTrue """ XXXXXXXXXXpass def __setitem__(self, key: str, value: bool) -> None: """ XXXXXXXXXXPurpose: Overloads set bracket operator [] for Box XXXXXXXXXXParameters: key (direction) as L, R, U, or D, XXXXXXXXXXbool to set side as XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: None XXXXXXXXXXModifies: Instance of a Box XXXXXXXXXXCalls: Basic python XXXXXXXXXXTests: 01_class_box.py XXXXXXXXXXUsage: >>> a_box = Box(True, True, True, False, "C") >>> a_box["R"] XXXXXXXXXXTrue >>> a_box["R"] = False >>> a_box["R"] XXXXXXXXXXFalse """ XXXXXXXXXXpass class Player: def __init__(self, name: str, human: bool = True, score: int = 0) -> None: """ XXXXXXXXXXPurpose: Initializes an instance of a player XXXXXXXXXXParameters: name as string, XXXXXXXXXXbool for human or computer, XXXXXXXXXXint to keep track of score XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: None XXXXXXXXXXModifies: Creates an instance of a player, with members: XXXXXXXXXXname, human, score XXXXXXXXXXCalls: Basic python XXXXXXXXXXTests: 02_class_player.py XXXXXXXXXXUsage: >>> your_player = Player('h', human=True) >>> your_player.name 'h' >>> your_player.human XXXXXXXXXXTrue """ XXXXXXXXXXpass Board = List[List[Box]] def build_board(config: List[str]) -> Board: """ Purpose: Build the initial board state as a List of List of Boxes Parameters: config string, List of strings, one line per element Input: None Prints: None Returns: a Board, a matrix describing the game state, a List[List[Box]] Modifies: None Calls: None Tests: We give you this one. Usage: >>> board: Board = build_board(['1 1', '1 1 1 1']) """ board: Board = [] rows, cols = map(int, config[0].split XXXXXXXXXXincnt = 1 for irow in range(rows): XXXXXXXXXXrowList: List[Box] = [] XXXXXXXXXXfor icol in range(cols): XXXXXXXXXXbox: List[int] = list(map(int, config[incnt].split XXXXXXXXXXincnt += XXXXXXXXXXl, r, u, d = map(bool, box XXXXXXXXXXrowList.append(Box(l, r, u, d XXXXXXXXXXboard.append(rowList) return board class Game: def __init__(self, board: Board, player1: Player, player2: Player) -> None: """ XXXXXXXXXXPurpose: Initializes an instance of a Game XXXXXXXXXXParameters: the pre-build board, XXXXXXXXXXtwo Player instances XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: None XXXXXXXXXXModifies: Creates a Game instance, with some class members: XXXXXXXXXXboard XXXXXXXXXXplayer XXXXXXXXXXplayer XXXXXXXXXXturn starting at XXXXXXXXXXrows XXXXXXXXXXcols XXXXXXXXXXCalls: Basic python XXXXXXXXXXTests: 03_class_game.py XXXXXXXXXXUsage: >>> test_board = [[Box(True, False, True, True), Box(False, False, False, True)], [Box(False, False, True, True), Box(False, True, True, True)]] >>> a_game = Game(test_board, Player("S"), Player("T")) >>> a_game.board == test_board XXXXXXXXXXTrue >>> a_game.player1.name == "S" XXXXXXXXXXTrue >>> a_game.turn == XXXXXXXXXXTrue >>> a_game.rows == 2 and a_game.cols == XXXXXXXXXXTrue """ XXXXXXXXXXpass def __str__(self) -> str: """ XXXXXXXXXXPurpose: Displays the current game-state XXXXXXXXXXParameters: self, which can access the Board in the Game instance XXXXXXXXXXInput: None XXXXXXXXXXPrints: None (this function is for printing though XXXXXXXXXXReturns: The board with lines representing the moves made thusfar (see usage XXXXXXXXXXcompleted squares should indicate which player completed them XXXXXXXXXXModifies: None XXXXXXXXXXCalls: None XXXXXXXXXXTests: 04_print_game.py XXXXXXXXXXUsage: >>> test_board = [[Box(True, False, True, True, "S"), Box(False, False, False, True)], [Box(False, False, True, True), Box(False, True, True, True, "T")]] >>> a_game = Game(test_board, Player("S"), Player("T")) >>> a_game.__str__() '\\n o---o o\\n | S XXXXXXXXXXn o---o---o\\n T |\\n o---o---o' """ XXXXXXXXXXpass def box_complete(self, row: int, col: int) -> bool: """ XXXXXXXXXXPurpose: Checks if a given square is completed, XXXXXXXXXXleft, right, up, down are all marked True XXXXXXXXXXParameters: the board, XXXXXXXXXXa row, and XXXXXXXXXXa column. XXXXXXXXXXThe row/col indicating position of the square XXXXXXXXXXInput: None XXXXXXXXXXPrints: None XXXXXXXXXXReturns: True if the square is complete, else False XXXXXXXXXXModifies: None XXXXXXXXXXCalls: None XXXXXXXXXXTests: 06_box_complete.py XXXXXXXXXXUsage: >>> test_board = [[Box(True, True, True, True), Box(False, False, False, True)], [Box(False, False, True, True), Box(False, True, True, True)]] >>> a_game = Game(test_board, Player("S"), Player("T")) >>> a_game.box_complete(0, XXXXXXXXXXTrue >>> a_game.box_complete(1, XXXXXXXXXXFalse """ XXXXXXXXXXpass def player_move(self, player: Player, row: int, col: int, direction: str) -> bool: """ XXXXXXXXXXPurpose: Modifies game when player makes a move XXXXXXXXXXParameters: The board, XXXXXXXXXXthe player making the move, XXXXXXXXXXthe move as row/col/dir XXXXXXXXXXInput: None XXXXXXXXXXPrints: None XXXXXXXXXXReturns: True if player completes a square, XXXXXXXXXXotherwise False, and XXXXXXXXXXFalse when the game is over XXXXXXXXXXModifies: board (updated according to move), player score XXXXXXXXXXCalls: basic python, is_game_on, box_complete XXXXXXXXXXTests: 08_player_move.py XXXXXXXXXXUsage: >>> test_board = [[Box(True, True, True, True), Box(True, False, False, True)], [Box(False, False, True, True), Box(False, True, True, True)]] >>> a_game = Game(test_board, Player("S"), Player("T")) >>> a_game.player_move(a_game.player1, 0, 1, "R" XXXXXXXXXXFalse >>> a_game.player1.score == XXXXXXXXXXTrue >>> a_game.player_move(a_game.player1, 0, 1, "U" XXXXXXXXXXTrue >>> a_game.player1.score == XXXXXXXXXXTrue """ XXXXXXXXXXpass def is_game_on(self) -> bool: """ XXXXXXXXXXPurpose: Determines if the current game-state is still ongoing XXXXXXXXXXParameters: self, which can access the Board XXXXXXXXXXInput: None XXXXXXXXXXPrints: None XXXXXXXXXXReturns: True if the game is over (no more moves can be played XXXXXXXXXXelse False XXXXXXXXXXModifies: None XXXXXXXXXXCalls: None XXXXXXXXXXTests: 07_is_game_on.py XXXXXXXXXXUsage: >>> test_board1 = [[Box(False, True, True, True), Box(True, False, False, False)], [Box(False, False, True, False), Box(False, False, False, False)]] >>> testG1 = Game(test_board1, Player(name="S", score=0), Player(name="T", score=0)) >>> testG1.is_game_on XXXXXXXXXXTrue >>> test_board2 = [[Box(True, True, True, True, owner="S"), Box(True, True, True, True, owner="S")], [Box(True, True, True, True, owner="S"), Box(True, True, True, True, owner="T")]] >>> testG2 = Game(test_board2, Player(name="S", score=3), Player(name="T", score=1)) >>> testG2.is_game_on XXXXXXXXXXFalse """ XXXXXXXXXXpass def evaluate_move(self, row: int, col: int, direction: str) -> int: """ XXXXXXXXXXPurpose: XXXXXXXXXXevaluates square of move, and potentially impacted neighbor XXXXXXXXXXhigher return value = worse move XXXXXXXXXXParameters: row, col, dir for move XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: XXXXXXXXXX -> a square is now complete XXXXXXXXXX -> leaves 1 walls completed XXXXXXXXXX -> leaves 2 wall completed XXXXXXXXXX -> leaves 3 walls completed XXXXXXXXXX -> the move is illegal XXXXXXXXXXModifies: Nothing XXXXXXXXXXCalls: Basic python XXXXXXXXXXTests: 09_evaluate_move.py XXXXXXXXXXUsage: >>> test_board = [[Box(False, True, True, True), Box(True, False, False, False)], [Box(False, False, True, True), Box(False, False, False, False)]] >>> testG = Game(test_board, Player(name="S"), Player(name="T")) >>> testG.evaluate_move(0, 0, "L" XXXXXXXXXX >>> testG.evaluate_move(0, 1, "R" XXXXXXXXXX >>> testG.evaluate_move(1, 1, "R" XXXXXXXXXX >>> testG.evaluate_move(1, 1, "L" XXXXXXXXXX >>> testG.evaluate_move(0, 0, "U" XXXXXXXXXX """ XXXXXXXXXXpass def get_computer_move(self) -> Tuple[int, int, str]: """ XXXXXXXXXXPurpose: Computer AI, evaluate all moves to pick "best", with XXXXXXXXXXties broken by lowest row -> lowest col -> LRUD order XXXXXXXXXXParameters: self, which has access to Game and its internals XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: Move to complete a square, or XXXXXXXXXXthe 'worst case' from either affected square if it can't complete a square XXXXXXXXXXModifies: Nothing XXXXXXXXXXCalls: evaluate_move, basic python XXXXXXXXXXTests: 10_get_computer_move.py XXXXXXXXXXUsage: >>> test_board = [[Box(True, False, True, True), Box(False, False, False, True)], [Box(False, False, True, True), Box(False, True, True, True)]] >>> testG = Game(test_board, Player(name="S"), Player(name="T")) >>> row, col, direction = testG.get_computer_move() >>> row XXXXXXXXXX >>> col XXXXXXXXXX >>> direction 'R' """ XXXXXXXXXXpass def validate_move(self, row: int, col: int, direction: str) -> bool: """ XXXXXXXXXXPurpose: Checks move is on the board, and not taken already XXXXXXXXXXParameters: move as row, col, dir, self has access to Game XXXXXXXXXXInput: None XXXXXXXXXXPrints: Nothing XXXXXXXXXXReturns: a bool, True if valid, False if not XXXXXXXXXXModifies: Nothing XXXXXXXXXXCalls: basic Python XXXXXXXXXXTests: 05_validate_move.py XXXXXXXXXXUsage: >>> test_board = [[Box(False, False, True, True), Box(False, True, True, True)], [Box(True, True, True, True), Box(True, False, True, False)]] >>> testG = Game(test_board, Player("S"), Player("T")) >>> testG.validate_move(0, 0, "L" XXXXXXXXXXTrue >>> testG.validate_move(0, 0, "D" XXXXXXXXXXFalse """ XXXXXXXXXXpass def main() -> None: """ Purpose: Main driver Parameters: None Input: Yes, file-based and stdio based Prints: Yes Returns: None Modifies: All kinds of stuff! Calls: All your functions, basic python Tests: We give this one to you """ args = docopt.docopt(__doc__) with open(args[""]) as fhand: XXXXXXXXXXconfig: List[str] = fhand.readlines() board: Board = build_board(config) num_human_players: int = XXXXXXXXXXplayer1_name: str = "" player2_name: str = "" while num_human_players 1 or num_human_players > 2: XXXXXXXXXXnum_human_players = int(input("How many humans are playing? 1 or 2: ")) while len(player1_name) != 1: XXXXXXXXXXplayer1_name = input("Enter initial of player 1 (one-character): ") player_one: Player = Player(player1_name) while len(player2_name) != 1 or player2_name == player1_name: XXXXXXXXXXplayer2_name = input("Enter a initial of the computer (one-character): ") if num_human_players == 1: XXXXXXXXXXplayer_two: Player = Player(player2_name, human=False) else: XXXXXXXXXXplayer_two = Player(player2_name, human=True) my_game: Game = Game(board, player_one, player_two) print("Starting board state is:") print(my_game) players: List[Player] = [player_one, player_two] get_player_move: Callable[[Player], Tuple[int, int, str]] = lambda player: XXXXXXXXXXint(input(f"Player {player.name}, enter a row: ")), XXXXXXXXXXint(input(f"Player {player.name}, enter a column: ")), XXXXXXXXXXinput(f"Player {player.name}, enter a direction (L,R,U,D): ").upper(), XXXXXXXXXXwhile my_game.is_game_on(): XXXXXXXXXXcurr_player: Player = players[my_game.turn % 2] XXXXXXXXXXextra_turn: bool = True XXXXXXXXXXwhile extra_turn: XXXXXXXXXXprint(f"\n======== Turn number: {my_game.turn} ========" XXXXXXXXXXif curr_player.human: XXXXXXXXXXentity_move = get_player_move(curr_player XXXXXXXXXXwhile not my_game.validate_move(*entity_move): XXXXXXXXXXprint("\nINVALID MOVE.\n") XXXXXXXXXXentity_move = get_player_move(curr_player XXXXXXXXXXelse: XXXXXXXXXXprint("Computer thinking..." XXXXXXXXXXentity_move = my_game.get_computer_move XXXXXXXXXXprint XXXXXXXXXXf"Player {curr_player.name}'s move was ({entity_move[0]}, {entity_move[1]}, {entity_move[2]}):" XXXXXXXXXXextra_turn = my_game.player_move(curr_player, *entity_move XXXXXXXXXXprint(my_game XXXXXXXXXXmy_game.turn += 1 print("\n======== GAME OVER ========") print(f"Player {player1_name} had {player_one.score} points") print(f"Player {player2_name} had {player_two.score} points") if player_one.score > player_two.score: XXXXXXXXXXprint("Player " + player1_name + " wins!") elif player_one.score player_two.score: XXXXXXXXXXprint("Player " + player2_name + " wins!") else: XXXXXXXXXXprint("It's a tie!") if __name__ == '__main__': main()