|
46 | 46 | START_GAME: bool = False
|
47 | 47 | CHECK_FOR_WINNER: bool = False
|
48 | 48 | MAIN_DIAGONAL_IS_WINNER: bool = False
|
49 |
| -CURENT_BOARD_WON: bool = False |
50 | 49 | CONTINUE_WITH_NEXT_GAME: str = ''
|
51 | 50 | STEP_COUNTER: int = 0
|
52 | 51 | PLAYER_SWITCH = True
|
|
56 | 55 | PLAYER2_NAME: str = ''
|
57 | 56 | PLAYER2_MARKER: str = ''
|
58 | 57 |
|
59 |
| -ROWS, COLS = (3, 3) |
| 58 | +ROWS, COLS = (3, 3) |
60 | 59 | GAME_PROGRESS_ARRAY = [['' for i in range(COLS)] for j in range(ROWS)]
|
61 | 60 | GAME_PROGRESS_ARRAY = np.array(GAME_PROGRESS_ARRAY, dtype=str)
|
62 | 61 | # WINNING_PATTERNS: list = [['00', '10', '20'], ['01', '11', '21'], ['02', '12', '22'], # rows
|
@@ -69,28 +68,46 @@ def split(word):
|
69 | 68 |
|
70 | 69 | def progress_game(key: str, player_marker: str):
|
71 | 70 | '''populated the 'GAME_PROGRESS_ARRAY' and
|
72 |
| -checks for is winning condition.''' |
| 71 | +checks for is winning condition. |
| 72 | +
|
| 73 | +PARAMS: |
| 74 | +1. key - the button element in the grid that was clicked. |
| 75 | +
|
| 76 | +2. player_marker - the marker of the current player. |
| 77 | +
|
| 78 | +RETURNS: |
| 79 | +continue_with_next_game - 'Yes' / 'No' indicator from the user action |
| 80 | +whether to continue with the same players. |
| 81 | +''' |
73 | 82 |
|
74 | 83 | global GAME_PROGRESS_ARRAY
|
75 |
| -global CURENT_BOARD_WON |
76 | 84 |
|
77 | 85 | continue_with_next_game: str = ''
|
78 | 86 |
|
79 | 87 | row, column = split(key)
|
80 | 88 | GAME_PROGRESS_ARRAY[row][column] = player_marker
|
81 | 89 |
|
| 90 | +# check if we have a winner in the current state of the board. |
82 | 91 | if CHECK_FOR_WINNER:
|
83 | 92 | game_won, winning_marker = is_winning()
|
84 | 93 | if game_won:
|
85 |
| -CURENT_BOARD_WON = True |
86 | 94 | continue_with_next_game = display_winner_and_continue(winning_marker=winning_marker)
|
87 | 95 |
|
88 | 96 | return continue_with_next_game
|
89 | 97 |
|
90 | 98 | def is_row_column_diagonal_complete(row_col_num: int = -1, is_row: bool = True,
|
91 | 99 | is_diagonal: bool = False):
|
92 | 100 | '''checks if the given row or column is complete
|
93 |
| -to proceed with a winner.''' |
| 101 | +to proceed with a winner. |
| 102 | +
|
| 103 | +PARAMS: |
| 104 | +1. row_col_num - the row/column index to check if the row/columns is complete. |
| 105 | +2. is_row: True if a ROW needs to be checked for completion else FALSE for a column. |
| 106 | +3. is_diagonal: True is any of the diagonal needs to be checked for completion. |
| 107 | +
|
| 108 | +RETURNS: |
| 109 | +is_complete: BOOLEAN FLAG to indicate of the row/column/diagonal is complete. |
| 110 | +''' |
94 | 111 | is_complete: bool = False
|
95 | 112 |
|
96 | 113 | if is_diagonal is False and row_col_num != -1:
|
@@ -117,10 +134,22 @@ def is_row_column_diagonal_complete(row_col_num: int = -1, is_row: bool = True,
|
117 | 134 |
|
118 | 135 | return is_complete
|
119 | 136 |
|
120 |
| - |
121 |
| -def mark_the_winner(row_is_winner: bool, row_column_index: int = -1, diagonal_is_winner: bool = False): |
| 137 | +def mark_the_winner(row_is_winner: bool, row_column_index: int = -1, |
| 138 | + diagonal_is_winner: bool = False): |
122 | 139 | '''marks the winner row/column by updating
|
123 |
| -the button row/column.''' |
| 140 | +the button row/column. The button image background |
| 141 | +changes to red to mark the winning sequence. |
| 142 | +
|
| 143 | +PARAMS: |
| 144 | +1. row_is_winner - Is the winner found in a ROW wise sequence. |
| 145 | +TRUE for a row & FALSE incase the winner is a column. |
| 146 | +
|
| 147 | +2. row_column_index - The winning row/column index. |
| 148 | +This default value is -1 to indicate the winner being found |
| 149 | +in one of the diagonals. |
| 150 | +
|
| 151 | +3. diagonal_is_winner - Is the winner found in one of the diagonals. |
| 152 | +''' |
124 | 153 |
|
125 | 154 | if not diagonal_is_winner and row_column_index != -1:
|
126 | 155 | if row_is_winner:
|
@@ -203,7 +232,11 @@ def is_winning():
|
203 | 232 | return False, ''
|
204 | 233 |
|
205 | 234 | def display_winner_and_continue(winning_marker: str):
|
206 |
| -'''display the winner of the current board.''' |
| 235 | +'''display the winner of the current board. |
| 236 | +
|
| 237 | +PARAMS: |
| 238 | +1. winning_marker - the marker that won the current board. |
| 239 | +''' |
207 | 240 |
|
208 | 241 | if winning_marker == PLAYER1_MARKER:
|
209 | 242 | popup_result = sg.PopupYesNo('The Winner is ' + PLAYER1_NAME + '.\nDo you want to play another game with the current players?',
|
@@ -218,6 +251,7 @@ def display_winner_and_continue(winning_marker: str):
|
218 | 251 |
|
219 | 252 | def init_game_window():
|
220 | 253 | '''Initializes and creates the game options window.'''
|
| 254 | + |
221 | 255 | init_game_layout = [[sg.Text('Player 1 Name: ', size=(12, 1)),
|
222 | 256 | sg.InputText('', key='-P1_NAME-')],
|
223 | 257 | [sg.Text('Player 2 Name: ', size=(12, 1)),
|
@@ -239,18 +273,36 @@ def reset_game_board():
|
239 | 273 | global STEP_COUNTER
|
240 | 274 | global CONTINUE_WITH_NEXT_GAME
|
241 | 275 | global CHECK_FOR_WINNER
|
242 |
| -global CURENT_BOARD_WON |
243 | 276 | global GAME_BOARD
|
244 | 277 | global PLAYER_SWITCH
|
| 278 | +global MAIN_DIAGONAL_IS_WINNER |
245 | 279 |
|
246 | 280 | GAME_BOARD = initialize_game_board()
|
247 | 281 | GAME_PROGRESS_ARRAY = [['' for i in range(COLS)] for j in range(ROWS)]
|
248 | 282 | GAME_PROGRESS_ARRAY = np.array(GAME_PROGRESS_ARRAY, dtype=str)
|
249 | 283 | STEP_COUNTER = 0
|
250 | 284 | CHECK_FOR_WINNER = False
|
251 | 285 | CONTINUE_WITH_NEXT_GAME = ''
|
252 |
| -CURENT_BOARD_WON = False |
253 | 286 | PLAYER_SWITCH = True
|
| 287 | +MAIN_DIAGONAL_IS_WINNER = False |
| 288 | + |
| 289 | +def start_next_session(user_choice: str): |
| 290 | + |
| 291 | +'''starts the next session as per the user choice. |
| 292 | +YES - retain the players and reset the board state. |
| 293 | +NO - return to the game init dialog to start over with new set of players.''' |
| 294 | + |
| 295 | +global INIT_WINDOW |
| 296 | +global GAME_BOARD |
| 297 | + |
| 298 | +if user_choice == 'Yes': |
| 299 | +# retain the players and reset the board state. |
| 300 | +GAME_BOARD.Close() |
| 301 | +reset_game_board() |
| 302 | +elif user_choice == 'No': |
| 303 | +# return to the game init dialog to start over with new set of players. |
| 304 | +GAME_BOARD.Close() |
| 305 | +INIT_WINDOW = init_game_window() |
254 | 306 |
|
255 | 307 | def initialize_game_board():
|
256 | 308 | '''initialize the game board.'''
|
@@ -291,6 +343,7 @@ def initialize_game_board():
|
291 | 343 |
|
292 | 344 | if EVENT == '-START-' and not GAME_BOARD:
|
293 | 345 |
|
| 346 | +# player name validation. Valid names required. |
294 | 347 | if VALUES['-P1_NAME-'] == '' and VALUES['-P2_NAME-'] == '':
|
295 | 348 | sg.popup_ok("Error initializing players name. Enter both the players name before proceeding.",
|
296 | 349 | title='Tic Tac Toe', icon=GAME_ICON)
|
@@ -313,14 +366,16 @@ def initialize_game_board():
|
313 | 366 | INIT_WINDOW.close()
|
314 | 367 | GAME_BOARD = initialize_game_board()
|
315 | 368 |
|
316 |
| -if WINDOW == GAME_BOARD and (EVENT in ('WIN_CLOSE', 'Exit')): |
| 369 | +if WINDOW == GAME_BOARD and (EVENT in ('WIN_CLOSE', '-EXIT-')): |
317 | 370 | GAME_BOARD.close()
|
318 | 371 | GAME_BOARD = None
|
319 | 372 | INIT_WINDOW = init_game_window()
|
320 | 373 |
|
321 |
| -if START_GAME: |
| 374 | +# We do not want to execute the progress logic in case |
| 375 | +# of the reset event. |
| 376 | +if START_GAME and EVENT != '-RESET-': |
322 | 377 |
|
323 |
| -if EVENT not in ('-START-', 'WIN_CLOSE'): |
| 378 | +if EVENT not in ('-START-', 'WIN_CLOSE', '-EXIT-'): |
324 | 379 | CURRENT_MARKER = GAME_BOARD.Element(EVENT).get_text()
|
325 | 380 | GAME_BOARD.Element(EVENT).update(PLAYER1_MARKER if CURRENT_MARKER == ' ' and\
|
326 | 381 | PLAYER_SWITCH is True else PLAYER2_MARKER if CURRENT_MARKER == ' ' and\
|
@@ -341,6 +396,7 @@ def initialize_game_board():
|
341 | 396 | GAME_BOARD.Element('-P1-').update(text_color='white')
|
342 | 397 | GAME_BOARD.Element('-P2-').update(text_color='darkblue')
|
343 | 398 |
|
| 399 | +# update the button images as per the current players marker. |
344 | 400 | if PLAYER1_MARKER == 'X':
|
345 | 401 | GAME_BOARD.Element(EVENT).update(image_filename=X_IMAGE)
|
346 | 402 | else:
|
@@ -349,12 +405,10 @@ def initialize_game_board():
|
349 | 405 | GAME_BOARD.Element(EVENT).update(disabled=True)
|
350 | 406 |
|
351 | 407 | CONTINUE_WITH_NEXT_GAME = progress_game(EVENT, PLAYER1_MARKER)
|
352 |
| -if CONTINUE_WITH_NEXT_GAME == 'Yes': |
353 |
| -GAME_BOARD.Close() |
354 |
| -reset_game_board() |
355 |
| -elif CONTINUE_WITH_NEXT_GAME == 'No': |
356 |
| -GAME_BOARD.Close() |
357 |
| -INIT_WINDOW = init_game_window() |
| 408 | + |
| 409 | +# start with the same players or new game |
| 410 | +# session with different players |
| 411 | +start_next_session(CONTINUE_WITH_NEXT_GAME) |
358 | 412 |
|
359 | 413 | elif GAME_BOARD.Element(EVENT).get_text() == PLAYER2_MARKER:
|
360 | 414 | # increase the step counter.
|
@@ -365,6 +419,7 @@ def initialize_game_board():
|
365 | 419 | GAME_BOARD.Element('-P1-').update(text_color='darkblue')
|
366 | 420 | GAME_BOARD.Element('-P2-').update(text_color='white')
|
367 | 421 |
|
| 422 | +# update the button images as per the current players marker. |
368 | 423 | if PLAYER2_MARKER == 'X':
|
369 | 424 | GAME_BOARD.Element(EVENT).update(image_filename=X_IMAGE)
|
370 | 425 | else:
|
@@ -373,18 +428,20 @@ def initialize_game_board():
|
373 | 428 | GAME_BOARD.Element(EVENT).update(disabled=True)
|
374 | 429 |
|
375 | 430 | CONTINUE_WITH_NEXT_GAME = progress_game(EVENT, PLAYER2_MARKER)
|
376 |
| -if CONTINUE_WITH_NEXT_GAME == 'Yes': |
377 |
| -GAME_BOARD.Close() |
378 |
| -reset_game_board() |
379 |
| -elif CONTINUE_WITH_NEXT_GAME == 'No': |
380 |
| -GAME_BOARD.Close() |
381 |
| -INIT_WINDOW = init_game_window() |
| 431 | + |
| 432 | +# start with the same players or new game |
| 433 | +# session with different players |
| 434 | +start_next_session(CONTINUE_WITH_NEXT_GAME) |
382 | 435 |
|
383 | 436 | # The minimum number of steps required
|
384 | 437 | # to win the game board is 5.
|
385 | 438 | if STEP_COUNTER == 4:
|
386 | 439 | CHECK_FOR_WINNER = True
|
387 | 440 |
|
388 |
| -if EVENT == '-RESET-': |
389 |
| -GAME_BOARD.Close() |
390 |
| -reset_game_board() |
| 441 | +if EVENT == '-RESET-' and WINDOW == GAME_BOARD: |
| 442 | +# reset the current board state. |
| 443 | +RESET_GAME = sg.popup_yes_no('Are you sure you want to reset the current board?', |
| 444 | +title='Game Reset', icon=GAME_ICON, grab_anywhere=True) |
| 445 | +if RESET_GAME == 'Yes': |
| 446 | +GAME_BOARD.Close() |
| 447 | +reset_game_board() |
0 commit comments