Skip to main content
deleted 363 characters in body
Source Link

Excess usage of functions

While using functions is generally a good idea, it increases code reusability and makes code more organized, here you have way too many functions and most of them are pretty simple, they clutter your script and calling functions is expensive in Python. You need to refactor your code to merge the functions into bigger ones.

Missing input validation

The user can input any text, only some of them will be successfully converted to int, and even fewer is valid (x in range(1, 10)). What if the user inputs cat, what happens then? A ValueError exception is thrown, because 'cat' cannot be converted to an integer (unless you are converting a numeral from a base no less than 30, cat30 = 1112910, in this case you need to specify base parameter in int call: int('cat', 30) == 11129):

Excess usage of functions

While using functions is generally a good idea, it increases code reusability and makes code more organized, here you have way too many functions and most of them are pretty simple, they clutter your script and calling functions is expensive in Python. You need to refactor your code to merge the functions into bigger ones.

Missing input validation

The user can input any text, only some of them will be successfully converted to int, and even fewer is valid (x in range(1, 10)). What if the user inputs cat, what happens then? A ValueError exception is thrown, because 'cat' cannot be converted to an integer (unless you are converting a numeral from a base no less than 30, cat30 = 1112910):

Missing input validation

The user can input any text, only some of them will be successfully converted to int, and even fewer is valid (x in range(1, 10)). What if the user inputs cat, what happens then? A ValueError exception is thrown, because 'cat' cannot be converted to an integer (unless you are converting a numeral from a base no less than 30, cat30 = 1112910, in this case you need to specify base parameter in int call: int('cat', 30) == 11129):

deleted 143 characters in body
Source Link
LINES = ( (0, 3, 1), (3, 6, 1), (6, 9, 1), (0, 7, 3), (1, 8, 3), (2, 9, 3), (0, 9, 4), (2, 7, 2) ) def check_winner(game_board): """check if there is a win, draw""" for start, stop, step in LINES: if len(set(game_board[start:stop:step])) == 1 and (winner := game_board[start]) in {'X', 'O'}: return winner return 'TIE' if all(x in ('X', 'O') for x in game_board) else False 
LINES = ( (0, 3, 1), (3, 6, 1), (6, 9, 1), (0, 7, 3), (1, 8, 3), (2, 9, 3), (0, 9, 4), (2, 7, 2) ) def check_winner(game_board): """check if there is a win, draw""" for start, stop, step in LINES: if len(set(game_board[start:stop:step])) == 1 and (winner := game_board[start]) in {'X', 'O'}: return winner return 'TIE' if all(x in ('X', 'O') for x in game_board) else False 
def check_winner(game_board): """check if there is a win, draw""" for start, stop, step in LINES: if len(set(game_board[start:stop:step])) == 1 and (winner := game_board[start]) in {'X', 'O'}: return winner return 'TIE' if all(x in ('X', 'O') for x in game_board) else False 
Source Link

Excess usage of functions

While using functions is generally a good idea, it increases code reusability and makes code more organized, here you have way too many functions and most of them are pretty simple, they clutter your script and calling functions is expensive in Python. You need to refactor your code to merge the functions into bigger ones.

Missing input validation

The user can input any text, only some of them will be successfully converted to int, and even fewer is valid (x in range(1, 10)). What if the user inputs cat, what happens then? A ValueError exception is thrown, because 'cat' cannot be converted to an integer (unless you are converting a numeral from a base no less than 30, cat30 = 1112910):

In [76]: int('cat') --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[76], line 1 ----> 1 int('cat') ValueError: invalid literal for int() with base 10: 'cat' 

And for numbers not in range(1, 10), your code will cause IndexError:

First player starts with X Please make a move on an unoccupied square player with piece X 11 IndexError: list index out of range 

I have refactored your function to get user input and added input validation:

import contextlib def get_player_move(game_board, user_piece): """ Get the player's move """ while True: choice = -1 while not 0 < choice < 10: while True: with contextlib.suppress(ValueError): choice = int(input(f" Please make a move on an unoccupied square player with piece {user_piece} ")) break if game_board[choice -1] not in {'X','O'}: break return choice 

Complicated code to check winner

Your code to check winner is very complicated, and much more complicated than it should be.

There is a lot of repetition in the code, the conditions to check for columns, rows and diagonals are almost identical, except for the indices.

(0, 1, 2), (3, 4, 5), (6, 7, 8) indices are on the same row, (0, 3, 6), (1, 4, 7), (2, 5, 8) indices are on the same column. (0, 4, 8), (2, 4, 6) are the diagonals.

How to get values at those indices? Notice in each group, the difference between two consecutive indices are the same? For indices in the same row, the step is 1, in the same column the step is 3, then for one diagonal the step is 4 for the other diagonal the step is 2.

In Python we use range to generate numbers, range(start, stop, step) will generate the following numbers: start, start + step, start + 2 * step ... (stop), the stop value is not included. For example, list(range(0, 3, 1)) == [0, 1, 2].

We can use slicing to get values located at those indices, for example, list(range(1, 10)[0:9:4]) == [1, 5, 9].

We can store the start and stop indices and the steps in a nested tuple and just then iterate through it to check all conditions.

LINES = ( (0, 3, 1), (3, 6, 1), (6, 9, 1), (0, 7, 3), (1, 8, 3), (2, 9, 3), (0, 9, 4), (2, 7, 2) ) 

Now how do we check if all elements are equal? In Python, elements of a set are unique, so if len(set(collection)) == 1, then all elements in collection are the same.

LINES = ( (0, 3, 1), (3, 6, 1), (6, 9, 1), (0, 7, 3), (1, 8, 3), (2, 9, 3), (0, 9, 4), (2, 7, 2) ) def check_winner(game_board): """check if there is a win, draw""" for start, stop, step in LINES: if len(set(game_board[start:stop:step])) == 1 and (winner := game_board[start]) in {'X', 'O'}: return winner return 'TIE' if all(x in ('X', 'O') for x in game_board) else False