Answered step by step
Verified Expert Solution
Question
1 Approved Answer
The Slide Game is a two player game played on a two-dimensional game board. The game board has a number of rows and columns specified
The Slide Game is a two player game played on a two-dimensional game board. The game board has a number of rows and columns specified at the beginning of the game and starts off filled with black squares.
Please fill out the code where it specifies to do so. Thank you !
Source code:
from typing import Any, Dict, Tuple import logging import os import sys import unittest import slide_functions as sf FILENAME = 'slide_functions.py" PYTA_CONFIG = pyta/ai_pyta.txt' CONSTANTS = { 'N_COLUMNS': 5, "N_ROWS": 4, 'BLACK_SQUARE': '#' "RED_SQUARE': 'R', "YELLOW_SQUARE': 'Y', "ACROSS': 'across', "DOWN': 'down', "DOWN_RIGHT': 'dright', "DOWN_LEFT': 'dleft" } EMPTY_TEST_BOARD def _run_pyta(filename: str, configfile: str) -> None: Run python-ta with configuration config_file on the file named filename. if not os.path.isdir('pyta"): | logging.error('The pyta directory is missing. Cannot test for style.') elif not os.path.isfile(config_file): logging.error('The pyta configuration file is missing. Cannot test 'for style.') else: sys.path.insert(e, 'pyta') import python_ta python_ta.check_all(filename, config=config_file) def _check(func: callable, args: list, expected: type) -> Tuple[bool, object]: ***Check if a call to func(args) returns a result with type expected. Return (True, result-of-call) if the check succeeds. Return (False, error-or-failure-message) if anything goes wrong. try: returned = func(*args) except Exception as exn: return false, _error_message(func, args, exn) if isinstance(returned, expected): return True, returned def _type_error_message(func: callable, expected: type, got: object) -> str: ***"Return an error message for function func returning got, where the correct return type is expected. }, but return f'{func._name_} should return a {expected._name_ f'instead it returned {got}.' def _error_message(func: callable, args: list, error: Exception) -> str: "Return an error message: func(args) raised an error." args = str.join(',', map(str, args)) return f'The call {func._name_}({args}) caused an error error: {error}' class SanityTest(unittest. Testcase): Sanity checker for the assignment functions. def test_create_empty_board(self) -> None: "Check the type contract of function create_empty_board." self._check('create_empty_board', [], str) def test_full_board(self) -> None: Check the type contract of function full_board.' self._check( 'is_board_full', [EMPTY_TEST_BOARD], bool) def test_between(self) -> None: ***Check the type contract of function between." self._check('between', ['1', 1, 2], bool) def test_calculate_str_index(self) -> None: *** Check the type contract of function calculate_str_index.*** self._check('calculate_str_index', [1, 1], int) def test_calculate_increment(self) -> None: Check the type contract of function calculate_increment. self._check('calculate_increment', [sf.ACROSS], int) def test_get_row(self) -> None: Check the type contract of function get_row.*** self._check( 'get_row', [1, EMPTY_TEST_BOARD), str) def test_get_column(self) -> None: Check the type contract of function get_column. self._check('get_column', (1, EMPTY_TEST_BOARD], str) def test_slide_right(self) -> None: Check the type contract of function slide_right." self._check('slide_right', (sf.RED_SQUARE, 1, EMPTY_TEST_BOARD], str) def test_slide_left(self) -> None: "Check the type contract of function slide_left." self._check('slide_left', (sf. RED_SQUARE, 1, EMPTY_TEST_BOARD], str) def test_check_constants(self) -> None: Test that the values of constants have not been changed." main.py * 112 113 def test_check_constants(self) -> None: Test that the values of constants have not been changed." logging.info('Checking that constants refer to the original values") self._check_constants(CONSTANTS, sf) def _check(self, function_name: str, args: list, ret_type: type) -> None: ***** Check that func called with arguments args returns a value of type ret_type. Display the progress and the result of the check. BE 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 logging.info(f'checking the function {function_name}...') self.assertTrue (hasattr(sf, function_name), f'The function {function_name} was not implemented.') func = getattr(sf, function_name) self.assertTrue (callable(func), f'Expected (function_name} to be a function, but f'instead it was a {type(func)}.') result, message = _check(func, args, ret_type) self.assertTrue (result, message) logging.info(f'Done checking the function {function_name}...') def _check_constants(self, name2value: Dict[str, object], mod: Any) -> None: ***Check that, for each (name, value) pair in name2value, the value of a variable named name in module mod is value. 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 for name, expected in name2value.items(): actual = getattr(mod, name) msg = 'The value of constant {} should be {} but is {}.'.format( name, expected, actual) self.assertEqual(expected, actual, msg) logging.basicconfig stream=sys.stdout, level=logging.DEBUG, format=' %(levelname)s: %message)s' ) logging.info('Checking coding style.') _run_pyta(FILENAME, PYTA_CONFIG) logging.info('Done checking coding style.') 156 157 158 159 160 161 162 logging.info('Checking type contracts.') unittest.main(exit=False) logging.info('Done checking type contracts.') logging.info('SCROLL UP to see all the results.') 24 slide_functions.py 22 # The next several lines contain constants for you to use in your code. 23 # You must use these constants instead of the values they refer to. # For example, use BLACK_SQUARE instead of '#'. 25 # You may not need to use all of the constants provided. 26 # Do not change the values these constants refer to. 27 28 N_COLUMNS = 5 # Number of columns in the game board 29 N_ROWS = 4 # Number of rows in the game board 30 31 BLACK_SQUARE = # The character that represents a black square 32 RED_SQUARE = 'R' # The character that represents a red square 33 YELLOW_SQUARE = 'Y" # The character that represents a blue square 34 35 ACROSS = 'across' # The horizontal direction 36 DOWN="down' # The vertical direction 37 DOWN_RIGHT = 'dright' # The diagonal direction: downward and rightward 38 DOWN_LEFT = "dleft' # The diagonal direction: downward and leftward 39 40 41 # This function is completed for you as an example and you must not change it. 42 def create_empty_board() -> str: 43 *"Return a string representation of a game board of all empty symbols with 44 N_ROWS rows and N_COLUMNS columns. 45 46 return BLACK_SQUARE * N_ROWS * N_COLUMNS 47 48 49 def is_board_full(game_board: str) -> bool: 50 "Return True if and only if the game_board is full. 51 52 A game_board is full when it does not contain any BLACK_SQUARE characters. 53 54 55 56 57 58 >>> is_board_full('R########YR####Y####') False >>> is_board_full('RYYRYYRYYRYYRYYRYYRY") True # Write your code for the is_board_full function here if is_board_full ("RYYRYYRYYRYYRYYRYYRY'): return True 59 60 61 62 63 64 65 66 67 68 69 70 71 def between(value: str, min_value: int, max_value: int) -> bool: **"Return True if and only if value is between min_value and max_value, inclusive. Preconditions: value can be converted to an integer without error min_value >>> between('2', 0, 2) True >>> between('e', 2, 3) False # This function is completed for you as an example and you must not change it. def create_empty_board() -> str: ***"Return a string representation of a game board of all empty symbols with N_ROWS rows and N_COLUMNS columns. return BLACK_SQUARE * N_ROWS * N_COLUMNS def is_board_full(game_board: str) -> bool: Return True if and only if the game_board is full. A game_board is full when it does not contain any BLACK_SQUARE characters. >>>> is_board_full('R########YR####Y####') False >>> is_board_full('RYYRYYRYYRYYRYYRYYRY") True # Write your code for the is_board_full function here if is_board_full ("RYYRYYRYYRYYRYYRYYRY"): return True def between(value: str, min_value: int, max_value: int) -> bool: ***"Return True if and only if value is between min_value and max_value, inclusive. Preconditions: value can be converted to an integer without error min_value >> between('2', @, 2) True >>> between('e', 2, 3) False # Write your code for the between function here. # Write the rest of your functions here. import slide_functions as sf # All the possible squares in the game SQUARES = sf.RED_SQUARE + sf.YELLOW_SQUARE PLAYER1_ID = @ PLAYER2_ID = 1 NUM_MATCH = 3 # Number of spaces to be connected by a player # The two moves that can be done in a game of slide, represented as integers SLIDE_RIGHT = 1 SLIDE_LEFT = 2 def is_valid_response(response: str, min_value: int, max_value: int) -> bool: "Return True if and only if response contains the representation of an integer without a +/- sign that is between min_value and max_value, inclusive. >>> is_valid_response('4', 1, 9) True >>> is_valid_response('abc', 1, 3) False return response. isdigit() and sf.between(response, min_value, max_value) def get_valid_response (prompt_message: str, error_message: str, LIITwin_value: int, max_value: int) -> int: ***"Return the user's response to prompt_message. Repeatedly prompt the user for input with prompt_message until the user enters a valid response. Display error_message for each invalid response entered by the user. A response is valid if it is a str representation of an integer, without a +/- sign, between min_value and max_value, inclusive. (NO docstring example given since function depends on user input.) response = input(prompt_message) while not is_valid_response (response, min_value, max_value): print(error_message) response = input(prompt_message) return int(response) def get_valid_move() -> int: "Return the valid move entered by the user. The int i represents slide right and the int 2 represents slide left. Display an error message for each invalid response entered by the user. The user's input is valid if it is a string representation of an integer, without a +/- sign that is between 1 and 2. slide_game.py 71 "Return the valid move entered by the user. The int i represents slide 72 right and the int 2 represents slide left. Display an error message for 73 each invalid response entered by the user. The user's input is valid if 74 it is a string representation of an integer, without a +/- sign that is 75 between 1 and 2. 76 77 (No docstring example given since the function depends on user input.) 78 79 80 print('which move, slide right or slide left, would you like to do?') 81 move = get_valid_response( 'Enter 1 for slide right and 2 for slide left: 82 LITT'That is not a valid move. Try again!', 1, 2) 83 84 return move 85 86 87 def get_valid_row_number(max_row_number: int) -> int: 88 *Return a valid row number that is less than or equal to max_row_number. (NO docstring example given since the function depends on user input.) 89 90 91 92 93 print("Enter a row number between 1 and ' + str(max_row_number) + error_message = 'Your suggested row number is not valid. Try again!' row = get_valid_response( 'Enter row number: ', error_message, 1, max_row_number) return row def calculate_last_diagonal_index(row: int, col: int, Line_direction: str, max_row_number: int, max_col_number: int) \ -> int: "Return the index of the last character from a line that starts at row row and column col and goes in direction line_direction on a game board with max_row_number rows and max_col_number columns. 94 95 96 97 98 99 100 101 102 103 104 185 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 Preconditions: - row and col are valid row numbers and column numbers, respectively. line_direction is one of sf.DOWN_RIGHT, sf.DOWN_LEFT >>> calculate_last_diagonal_index(1, 2, sf.DOWN_LEFT, 4, 5) 5 >>> calculate_last_diagonal_index(2, 5, sf.DOWN_LEFT, 4, 5) 17 >>> calculate_last_diagonal_index(1, 2, sf.DOWN_RIGHT, 4, 5) 19 >>> calculate_last_diagonal_index(2, 1, sf.DOWN_RIGHT, 4, 5) 17 last_row = row last_col = col if line_direction == sf.DOWN_LEFT: ide_game.py if line_direction == sf.DOWN_LEFT: while last_row 1: 3 last_row = last_row + 1 2 last_col = last_col - 1 2 else: while last_row bool: ***Return True if and only if the game_board with max_row_number rows and max_col_number columns contains a winner. 3 The game has been won when a square appears consecutively NUM_MATCH times in the horizontal, vertical, or diagonal directions. >>> check_win("RYRYRYRYRYYRYRYRYRYR', 4, 5) False >>> check_win('YRRRYRYRYRYYRYYRYRYR', 4, 5) True winning_p1 = SQUARES(PLAYER1_ID] * NUM_MATCH winning_p2 = SQUARES(PLAYER2_ID] * NUM_MATCH # Horizontal wins for row in range(1, max_row_number + 1): squares = sf.get_row(row, game_board) if winning_p1 in squares or winning_p2 in squares: return True 2 3 # Vertical wins for col in range(1, max_col_number + 1): squares = sf.get_column(col, game_board) if winning_p1 in squares or winning_p2 in squares: return True # Diagonal wins: downward rightward increment = sf.calculate_increment(sf.DOWN_RIGHT) for col in range(1, max_col_number + 1): first_index = sf.calculate_str_index(1, col) last_index = calculate_last_diagonal_index(1, col, sf.DOWN_RIGHT, max_row_number, max_col_number) squares = game_board[first_index: last_index + 1:increment] + if winning_pi in squares or winning_p2 in squares: return True # Diagonal wins: downward leftward increment = sf.calculate_increment(sf.DOWN_LEFT) for col in range(1, max_col_number + 1): 179 slide_game.py # Diagonal wins: downward leftward 180 increment = sf.calculate_increment(sf.DOWN_LEFT) 181 for col in range(1, max_col_number + 1): 182 first_index = sf.calculate_str_index(1, col) last_index calculate_last_diagonal_index(1, col, sf.DOWN_LEFT, max_row_number, 185 max_col_number) squares = game_board[first_index:last_index + 1: increment] 183 184 186 187 188 if winning p1 in squares or winning_p2 in squares: return True return false 189 190 191 192 193 194 195 196 197 198 # Interested in why this docstring starts with an r? # See section 2.4.1: https://docs.python.org/3.9/reference/lexical_analysis.html def format_game_board(game_board: str, max_row_number: int, max_col_number: int) -> str: p"#"Return a string representation of game_board with max_row_number rows and max_col_number columns. 199 200 201 202 283 204 >>> format_game_board("Y', 1, 1) 1 1 Y ' >>> expected = ! 1 2 3 4 5 1 RTY RTY| R ' + ... '2Y|R|Y| R | Y 3 Y|R|Y| R | Y 4 RTY|R|Y| R ' >>> expected == format_game_board("RYRYRYRYRYYRYRYRYRYR', 4, 5) True 285 206 287 208 209 210 211 212 213 # Add in the column numbers. formatted_board - for col in range(1, max_col_number + 1): formatted_board += '' + str(col) + formatted_board += ' ' 214 215 216 217 218 # Add in the row numbers, board contents, and grid markers. for row in range(1, max_row_number + 1): # Row numbers formatted_board += str(row) + ' for col in range(1, max_col_number): index = sf.calculate_str_index(row, col) # Board contents and grid markers formatted_board + game_board[index] += 'I 219 220 221 222 223 224 225 226 227 228 229 230 231 index = sf.calculate_str_index(row, max_col_number) formatted_board += + game_board[index] + ' ' return formatted_board 232 def play_slide (max_row_number: int, max_col_number: int) -> str: "Play a single game of slide with two human users with a game board that has max_row_number rows and max_col_number columns. 233 234 179 slide_game.py # Diagonal wins: downward leftward 180 increment = sf.calculate_increment(sf.DOWN_LEFT) 181 for col in range(1, max_col_number + 1): 182 first_index = sf.calculate_str_index(1, col) last_index calculate_last_diagonal_index(1, col, sf.DOWN_LEFT, max_row_number, 185 max_col_number) squares = game_board[first_index:last_index + 1: increment] 183 184 186 187 188 if winning p1 in squares or winning_p2 in squares: return True return false 189 190 191 192 193 194 195 196 197 198 # Interested in why this docstring starts with an r? # See section 2.4.1: https://docs.python.org/3.9/reference/lexical_analysis.html def format_game_board(game_board: str, max_row_number: int, max_col_number: int) -> str: p"#"Return a string representation of game_board with max_row_number rows and max_col_number columns. 199 200 201 202 283 204 >>> format_game_board("Y', 1, 1) 1 1 Y ' >>> expected = ! 1 2 3 4 5 1 RTY RTY| R ' + ... '2Y|R|Y| R | Y 3 Y|R|Y| R | Y 4 RTY|R|Y| R ' >>> expected == format_game_board("RYRYRYRYRYYRYRYRYRYR', 4, 5) True 285 206 287 208 209 210 211 212 213 # Add in the column numbers. formatted_board - for col in range(1, max_col_number + 1): formatted_board += '' + str(col) + formatted_board += ' ' 214 215 216 217 218 # Add in the row numbers, board contents, and grid markers. for row in range(1, max_row_number + 1): # Row numbers formatted_board += str(row) + ' for col in range(1, max_col_number): index = sf.calculate_str_index(row, col) # Board contents and grid markers formatted_board + game_board[index] += 'I 219 220 221 222 223 224 225 226 227 228 229 230 231 index = sf.calculate_str_index(row, max_col_number) formatted_board += + game_board[index] + ' ' return formatted_board 232 def play_slide (max_row_number: int, max_col_number: int) -> str: "Play a single game of slide with two human users with a game board that has max_row_number rows and max_col_number columns. 233 234 229 230 231 232 233 234 235 236 237 def play_slide(max_row_number: int, max_COL_number: int) -> str: - ""Play a single game of slide with two human users with a game board that has max_row_number rows and max_col_number columns. (No docstring example given since the function indirectly depends on user input) 238 game_board = sf.create_empty_board() is_game_over = False is_playeri_turn = True 239 240 241 242 243 244 245 246 247 248 249 250 251 252 print('Player 1 is using square + SQUARES (PLAYER1_ID] + and Player 2' + " is using square ' + SQUARES (PLAYER2_ID] + '.') print('The first player to match + str(NUM_MATCH) + squares wins!") while not is_game_over: print('The Game Board: " + format_game_board (game_board, max_row_number, max_col_number)) 253 254 255 256 257 258 if is_playeri_turn: player = 'Player 1 square - SQUARES (PLAYER1_ID] else: player = 'Player 2 square = SQUARES [PLAYER2_ID] 259 print(player + "'s turn.") move = get_valid_move() row = get_valid_row_number(max_row_number) if move == SLIDE_LEFT: game_board = sf.slide_left(square, row, game_board) elif move == SLIDE_RIGHT: game_board = sf.slide_right(square, row, game_board) print(" " + player + ' slid ' + square + ' onto row ' + str(row) + 260 261 262 263 264 265 266 267 268 269 278 271 272 273 274 275 276 277 278 279 280 281 282 have_winner = check_winc gane_board, max_row_number, max_col_number) if have_winner: if is_playeri_turn: winner = 'Player 1 wins! ' else: winner = 'Player 2 wins! ' return winner + format_game_board (game_board, max_row_number, max_col_number) if sf.is_board_full(game_board) return 'It is a draw! ' + format_game_board(game_board, max_row_number, max_col_number) else: is_playeri_turn = not is_playeri_turn 283 284 285 286 287 288 if name main__': import doctest doctest.testmod() 289 298 291 292 293 result = play_slide(sf.N_ROWS, sf.N_COLUMNS) print(result) from typing import Any, Dict, Tuple import logging import os import sys import unittest import slide_functions as sf FILENAME = 'slide_functions.py" PYTA_CONFIG = pyta/ai_pyta.txt' CONSTANTS = { 'N_COLUMNS': 5, "N_ROWS": 4, 'BLACK_SQUARE': '#' "RED_SQUARE': 'R', "YELLOW_SQUARE': 'Y', "ACROSS': 'across', "DOWN': 'down', "DOWN_RIGHT': 'dright', "DOWN_LEFT': 'dleft" } EMPTY_TEST_BOARD def _run_pyta(filename: str, configfile: str) -> None: Run python-ta with configuration config_file on the file named filename. if not os.path.isdir('pyta"): | logging.error('The pyta directory is missing. Cannot test for style.') elif not os.path.isfile(config_file): logging.error('The pyta configuration file is missing. Cannot test 'for style.') else: sys.path.insert(e, 'pyta') import python_ta python_ta.check_all(filename, config=config_file) def _check(func: callable, args: list, expected: type) -> Tuple[bool, object]: ***Check if a call to func(args) returns a result with type expected. Return (True, result-of-call) if the check succeeds. Return (False, error-or-failure-message) if anything goes wrong. try: returned = func(*args) except Exception as exn: return false, _error_message(func, args, exn) if isinstance(returned, expected): return True, returned def _type_error_message(func: callable, expected: type, got: object) -> str: ***"Return an error message for function func returning got, where the correct return type is expected. }, but return f'{func._name_} should return a {expected._name_ f'instead it returned {got}.' def _error_message(func: callable, args: list, error: Exception) -> str: "Return an error message: func(args) raised an error." args = str.join(',', map(str, args)) return f'The call {func._name_}({args}) caused an error error: {error}' class SanityTest(unittest. Testcase): Sanity checker for the assignment functions. def test_create_empty_board(self) -> None: "Check the type contract of function create_empty_board." self._check('create_empty_board', [], str) def test_full_board(self) -> None: Check the type contract of function full_board.' self._check( 'is_board_full', [EMPTY_TEST_BOARD], bool) def test_between(self) -> None: ***Check the type contract of function between." self._check('between', ['1', 1, 2], bool) def test_calculate_str_index(self) -> None: *** Check the type contract of function calculate_str_index.*** self._check('calculate_str_index', [1, 1], int) def test_calculate_increment(self) -> None: Check the type contract of function calculate_increment. self._check('calculate_increment', [sf.ACROSS], int) def test_get_row(self) -> None: Check the type contract of function get_row.*** self._check( 'get_row', [1, EMPTY_TEST_BOARD), str) def test_get_column(self) -> None: Check the type contract of function get_column. self._check('get_column', (1, EMPTY_TEST_BOARD], str) def test_slide_right(self) -> None: Check the type contract of function slide_right." self._check('slide_right', (sf.RED_SQUARE, 1, EMPTY_TEST_BOARD], str) def test_slide_left(self) -> None: "Check the type contract of function slide_left." self._check('slide_left', (sf. RED_SQUARE, 1, EMPTY_TEST_BOARD], str) def test_check_constants(self) -> None: Test that the values of constants have not been changed." main.py * 112 113 def test_check_constants(self) -> None: Test that the values of constants have not been changed." logging.info('Checking that constants refer to the original values") self._check_constants(CONSTANTS, sf) def _check(self, function_name: str, args: list, ret_type: type) -> None: ***** Check that func called with arguments args returns a value of type ret_type. Display the progress and the result of the check. BE 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 logging.info(f'checking the function {function_name}...') self.assertTrue (hasattr(sf, function_name), f'The function {function_name} was not implemented.') func = getattr(sf, function_name) self.assertTrue (callable(func), f'Expected (function_name} to be a function, but f'instead it was a {type(func)}.') result, message = _check(func, args, ret_type) self.assertTrue (result, message) logging.info(f'Done checking the function {function_name}...') def _check_constants(self, name2value: Dict[str, object], mod: Any) -> None: ***Check that, for each (name, value) pair in name2value, the value of a variable named name in module mod is value. 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 for name, expected in name2value.items(): actual = getattr(mod, name) msg = 'The value of constant {} should be {} but is {}.'.format( name, expected, actual) self.assertEqual(expected, actual, msg) logging.basicconfig stream=sys.stdout, level=logging.DEBUG, format=' %(levelname)s: %message)s' ) logging.info('Checking coding style.') _run_pyta(FILENAME, PYTA_CONFIG) logging.info('Done checking coding style.') 156 157 158 159 160 161 162 logging.info('Checking type contracts.') unittest.main(exit=False) logging.info('Done checking type contracts.') logging.info('SCROLL UP to see all the results.') 24 slide_functions.py 22 # The next several lines contain constants for you to use in your code. 23 # You must use these constants instead of the values they refer to. # For example, use BLACK_SQUARE instead of '#'. 25 # You may not need to use all of the constants provided. 26 # Do not change the values these constants refer to. 27 28 N_COLUMNS = 5 # Number of columns in the game board 29 N_ROWS = 4 # Number of rows in the game board 30 31 BLACK_SQUARE = # The character that represents a black square 32 RED_SQUARE = 'R' # The character that represents a red square 33 YELLOW_SQUARE = 'Y" # The character that represents a blue square 34 35 ACROSS = 'across' # The horizontal direction 36 DOWN="down' # The vertical direction 37 DOWN_RIGHT = 'dright' # The diagonal direction: downward and rightward 38 DOWN_LEFT = "dleft' # The diagonal direction: downward and leftward 39 40 41 # This function is completed for you as an example and you must not change it. 42 def create_empty_board() -> str: 43 *"Return a string representation of a game board of all empty symbols with 44 N_ROWS rows and N_COLUMNS columns. 45 46 return BLACK_SQUARE * N_ROWS * N_COLUMNS 47 48 49 def is_board_full(game_board: str) -> bool: 50 "Return True if and only if the game_board is full. 51 52 A game_board is full when it does not contain any BLACK_SQUARE characters. 53 54 55 56 57 58 >>> is_board_full('R########YR####Y####') False >>> is_board_full('RYYRYYRYYRYYRYYRYYRY") True # Write your code for the is_board_full function here if is_board_full ("RYYRYYRYYRYYRYYRYYRY'): return True 59 60 61 62 63 64 65 66 67 68 69 70 71 def between(value: str, min_value: int, max_value: int) -> bool: **"Return True if and only if value is between min_value and max_value, inclusive. Preconditions: value can be converted to an integer without error min_value >>> between('2', 0, 2) True >>> between('e', 2, 3) False # This function is completed for you as an example and you must not change it. def create_empty_board() -> str: ***"Return a string representation of a game board of all empty symbols with N_ROWS rows and N_COLUMNS columns. return BLACK_SQUARE * N_ROWS * N_COLUMNS def is_board_full(game_board: str) -> bool: Return True if and only if the game_board is full. A game_board is full when it does not contain any BLACK_SQUARE characters. >>>> is_board_full('R########YR####Y####') False >>> is_board_full('RYYRYYRYYRYYRYYRYYRY") True # Write your code for the is_board_full function here if is_board_full ("RYYRYYRYYRYYRYYRYYRY"): return True def between(value: str, min_value: int, max_value: int) -> bool: ***"Return True if and only if value is between min_value and max_value, inclusive. Preconditions: value can be converted to an integer without error min_value >> between('2', @, 2) True >>> between('e', 2, 3) False # Write your code for the between function here. # Write the rest of your functions here. import slide_functions as sf # All the possible squares in the game SQUARES = sf.RED_SQUARE + sf.YELLOW_SQUARE PLAYER1_ID = @ PLAYER2_ID = 1 NUM_MATCH = 3 # Number of spaces to be connected by a player # The two moves that can be done in a game of slide, represented as integers SLIDE_RIGHT = 1 SLIDE_LEFT = 2 def is_valid_response(response: str, min_value: int, max_value: int) -> bool: "Return True if and only if response contains the representation of an integer without a +/- sign that is between min_value and max_value, inclusive. >>> is_valid_response('4', 1, 9) True >>> is_valid_response('abc', 1, 3) False return response. isdigit() and sf.between(response, min_value, max_value) def get_valid_response (prompt_message: str, error_message: str, LIITwin_value: int, max_value: int) -> int: ***"Return the user's response to prompt_message. Repeatedly prompt the user for input with prompt_message until the user enters a valid response. Display error_message for each invalid response entered by the user. A response is valid if it is a str representation of an integer, without a +/- sign, between min_value and max_value, inclusive. (NO docstring example given since function depends on user input.) response = input(prompt_message) while not is_valid_response (response, min_value, max_value): print(error_message) response = input(prompt_message) return int(response) def get_valid_move() -> int: "Return the valid move entered by the user. The int i represents slide right and the int 2 represents slide left. Display an error message for each invalid response entered by the user. The user's input is valid if it is a string representation of an integer, without a +/- sign that is between 1 and 2. slide_game.py 71 "Return the valid move entered by the user. The int i represents slide 72 right and the int 2 represents slide left. Display an error message for 73 each invalid response entered by the user. The user's input is valid if 74 it is a string representation of an integer, without a +/- sign that is 75 between 1 and 2. 76 77 (No docstring example given since the function depends on user input.) 78 79 80 print('which move, slide right or slide left, would you like to do?') 81 move = get_valid_response( 'Enter 1 for slide right and 2 for slide left: 82 LITT'That is not a valid move. Try again!', 1, 2) 83 84 return move 85 86 87 def get_valid_row_number(max_row_number: int) -> int: 88 *Return a valid row number that is less than or equal to max_row_number. (NO docstring example given since the function depends on user input.) 89 90 91 92 93 print("Enter a row number between 1 and ' + str(max_row_number) + error_message = 'Your suggested row number is not valid. Try again!' row = get_valid_response( 'Enter row number: ', error_message, 1, max_row_number) return row def calculate_last_diagonal_index(row: int, col: int, Line_direction: str, max_row_number: int, max_col_number: int) \ -> int: "Return the index of the last character from a line that starts at row row and column col and goes in direction line_direction on a game board with max_row_number rows and max_col_number columns. 94 95 96 97 98 99 100 101 102 103 104 185 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 Preconditions: - row and col are valid row numbers and column numbers, respectively. line_direction is one of sf.DOWN_RIGHT, sf.DOWN_LEFT >>> calculate_last_diagonal_index(1, 2, sf.DOWN_LEFT, 4, 5) 5 >>> calculate_last_diagonal_index(2, 5, sf.DOWN_LEFT, 4, 5) 17 >>> calculate_last_diagonal_index(1, 2, sf.DOWN_RIGHT, 4, 5) 19 >>> calculate_last_diagonal_index(2, 1, sf.DOWN_RIGHT, 4, 5) 17 last_row = row last_col = col if line_direction == sf.DOWN_LEFT: ide_game.py if line_direction == sf.DOWN_LEFT: while last_row 1: 3 last_row = last_row + 1 2 last_col = last_col - 1 2 else: while last_row bool: ***Return True if and only if the game_board with max_row_number rows and max_col_number columns contains a winner. 3 The game has been won when a square appears consecutively NUM_MATCH times in the horizontal, vertical, or diagonal directions. >>> check_win("RYRYRYRYRYYRYRYRYRYR', 4, 5) False >>> check_win('YRRRYRYRYRYYRYYRYRYR', 4, 5) True winning_p1 = SQUARES(PLAYER1_ID] * NUM_MATCH winning_p2 = SQUARES(PLAYER2_ID] * NUM_MATCH # Horizontal wins for row in range(1, max_row_number + 1): squares = sf.get_row(row, game_board) if winning_p1 in squares or winning_p2 in squares: return True 2 3 # Vertical wins for col in range(1, max_col_number + 1): squares = sf.get_column(col, game_board) if winning_p1 in squares or winning_p2 in squares: return True # Diagonal wins: downward rightward increment = sf.calculate_increment(sf.DOWN_RIGHT) for col in range(1, max_col_number + 1): first_index = sf.calculate_str_index(1, col) last_index = calculate_last_diagonal_index(1, col, sf.DOWN_RIGHT, max_row_number, max_col_number) squares = game_board[first_index: last_index + 1:increment] + if winning_pi in squares or winning_p2 in squares: return True # Diagonal wins: downward leftward increment = sf.calculate_increment(sf.DOWN_LEFT) for col in range(1, max_col_number + 1): 179 slide_game.py # Diagonal wins: downward leftward 180 increment = sf.calculate_increment(sf.DOWN_LEFT) 181 for col in range(1, max_col_number + 1): 182 first_index = sf.calculate_str_index(1, col) last_index calculate_last_diagonal_index(1, col, sf.DOWN_LEFT, max_row_number, 185 max_col_number) squares = game_board[first_index:last_index + 1: increment] 183 184 186 187 188 if winning p1 in squares or winning_p2 in squares: return True return false 189 190 191 192 193 194 195 196 197 198 # Interested in why this docstring starts with an r? # See section 2.4.1: https://docs.python.org/3.9/reference/lexical_analysis.html def format_game_board(game_board: str, max_row_number: int, max_col_number: int) -> str: p"#"Return a string representation of game_board with max_row_number rows and max_col_number columns. 199 200 201 202 283 204 >>> format_game_board("Y', 1, 1) 1 1 Y ' >>> expected = ! 1 2 3 4 5 1 RTY RTY| R ' + ... '2Y|R|Y| R | Y 3 Y|R|Y| R | Y 4 RTY|R|Y| R ' >>> expected == format_game_board("RYRYRYRYRYYRYRYRYRYR', 4, 5) True 285 206 287 208 209 210 211 212 213 # Add in the column numbers. formatted_board - for col in range(1, max_col_number + 1): formatted_board += '' + str(col) + formatted_board += ' ' 214 215 216 217 218 # Add in the row numbers, board contents, and grid markers. for row in range(1, max_row_number + 1): # Row numbers formatted_board += str(row) + ' for col in range(1, max_col_number): index = sf.calculate_str_index(row, col) # Board contents and grid markers formatted_board + game_board[index] += 'I 219 220 221 222 223 224 225 226 227 228 229 230 231 index = sf.calculate_str_index(row, max_col_number) formatted_board += + game_board[index] + ' ' return formatted_board 232 def play_slide (max_row_number: int, max_col_number: int) -> str: "Play a single game of slide with two human users with a game board that has max_row_number rows and max_col_number columns. 233 234 179 slide_game.py # Diagonal wins: downward leftward 180 increment = sf.calculate_increment(sf.DOWN_LEFT) 181 for col in range(1, max_col_number + 1): 182 first_index = sf.calculate_str_index(1, col) last_index calculate_last_diagonal_index(1, col, sf.DOWN_LEFT, max_row_number, 185 max_col_number) squares = game_board[first_index:last_index + 1: increment] 183 184 186 187 188 if winning p1 in squares or winning_p2 in squares: return True return false 189 190 191 192 193 194 195 196 197 198 # Interested in why this docstring starts with an r? # See section 2.4.1: https://docs.python.org/3.9/reference/lexical_analysis.html def format_game_board(game_board: str, max_row_number: int, max_col_number: int) -> str: p"#"Return a string representation of game_board with max_row_number rows and max_col_number columns. 199 200 201 202 283 204 >>> format_game_board("Y', 1, 1) 1 1 Y ' >>> expected = ! 1 2 3 4 5 1 RTY RTY| R ' + ... '2Y|R|Y| R | Y 3 Y|R|Y| R | Y 4 RTY|R|Y| R ' >>> expected == format_game_board("RYRYRYRYRYYRYRYRYRYR', 4, 5) True 285 206 287 208 209 210 211 212 213 # Add in the column numbers. formatted_board - for col in range(1, max_col_number + 1): formatted_board += '' + str(col) + formatted_board += ' ' 214 215 216 217 218 # Add in the row numbers, board contents, and grid markers. for row in range(1, max_row_number + 1): # Row numbers formatted_board += str(row) + ' for col in range(1, max_col_number): index = sf.calculate_str_index(row, col) # Board contents and grid markers formatted_board + game_board[index] += 'I 219 220 221 222 223 224 225 226 227 228 229 230 231 index = sf.calculate_str_index(row, max_col_number) formatted_board += + game_board[index] + ' ' return formatted_board 232 def play_slide (max_row_number: int, max_col_number: int) -> str: "Play a single game of slide with two human users with a game board that has max_row_number rows and max_col_number columns. 233 234 229 230 231 232 233 234 235 236 237 def play_slide(max_row_number: int, max_COL_number: int) -> str: - ""Play a single game of slide with two human users with a game board that has max_row_number rows and max_col_number columns. (No docstring example given since the function indirectly depends on user input) 238 game_board = sf.create_empty_board() is_game_over = False is_playeri_turn = True 239 240 241 242 243 244 245 246 247 248 249 250 251 252 print('Player 1 is using square + SQUARES (PLAYER1_ID] + and Player 2' + " is using square ' + SQUARES (PLAYER2_ID] + '.') print('The first player to match + str(NUM_MATCH) + squares wins!") while not is_game_over: print('The Game Board: " + format_game_board (game_board, max_row_number, max_col_number)) 253 254 255 256 257 258 if is_playeri_turn: player = 'Player 1 square - SQUARES (PLAYER1_ID] else: player = 'Player 2 square = SQUARES [PLAYER2_ID] 259 print(player + "'s turn.") move = get_valid_move() row = get_valid_row_number(max_row_number) if move == SLIDE_LEFT: game_board = sf.slide_left(square, row, game_board) elif move == SLIDE_RIGHT: game_board = sf.slide_right(square, row, game_board) print(" " + player + ' slid ' + square + ' onto row ' + str(row) + 260 261 262 263 264 265 266 267 268 269 278 271 272 273 274 275 276 277 278 279 280 281 282 have_winner = check_winc gane_board, max_row_number, max_col_number) if have_winner: if is_playeri_turn: winner = 'Player 1 wins! ' else: winner = 'Player 2 wins! ' return winner + format_game_board (game_board, max_row_number, max_col_number) if sf.is_board_full(game_board) return 'It is a draw! ' + format_game_board(game_board, max_row_number, max_col_number) else: is_playeri_turn = not is_playeri_turn 283 284 285 286 287 288 if name main__': import doctest doctest.testmod() 289 298 291 292 293 result = play_slide(sf.N_ROWS, sf.N_COLUMNS) print(result)Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started