I'm coding simple terminal Tic Tac Toe game in python. I'm having problems with how should I implement the setting and checking for the 9 slots. I now have set functions for all the slots but it just feels stupid doing that is there any better way? I'm also coding the checking system where I would need Switch something even better.
Thank you!
main.py
#!/usr/bin/env python3
#file -- grid.py --
import grid
def welcome():
print("Welcome")
def main():
welcome()
grid.setgrid()
print(grid.grid)
while 1:
xinput = input("Player X: ")
if xinput.lower() == "a1":
grid.seta1("X")
elif xinput.lower() == "a2":
grid.seta2("X")
elif xinput.lower() == "a3":
grid.seta3("X")
#and so on
print(grid.grid)
oinput = input("Player O: ")
if __name__ == "__main__":
main()
grid.py
a1,a2,a3,b1,b2,b3,c1,c2,c3 = " "," "," "," "," "," "," "," "," "
grid = f"""
1 2 3
┌───┬───┬───┐\n
a │ {a1} │ {a2} │ {a3} │\n
├───┼───┼───┤\n
b │ {b1} │ {b2} │ {b3} │\n
├───┼───┼───┤\n
c │ {c1} │ {c2} │ {c3} │\n
└───┴───┴───┘"""
def setgrid():
global grid
grid = f""" ┌───┬───┬───┐\n
│ {a1} │ {a2} │ {a3} │\n
├───┼───┼───┤\n
│ {b1} │ {b2} │ {b3} │\n
├───┼───┼───┤\n
│ {c1} │ {c2} │ {c3} │\n
└───┴───┴───┘"""
#set functions
def seta1(val):
global a1
a1=val
setgrid()
def seta2(val):
global a2
a2=val
setgrid()
def seta3(val):
global a3
a3=val
setgrid()
def setb1(val):
global b1
b1=val
setgrid()
def setb2(val):
global b2
b2=val
setgrid()
def setb3(val):
global b3
b3=val
setgrid()
def setc1(val):
global c1
c1=val
setgrid()
def setc2(val):
global c2
c2=val
setgrid()
def setc3(val):
global c3
c3=val
setgrid()
CodePudding user response:
The #1 thing that will make your life easier is using a single data structure rather than N different variables. I'd suggest getting rid of everything in grid.py
and using a simple two-dimensional list, like this:
grid = [[" " for _ in range(3)] for _ in range(3)]
while True:
for mark in "XO":
row, col = input(f"Player {mark}: ")
grid[ord(row) - ord('a')][int(col) - 1] = mark
print(*('|'.join(row) for row in grid), sep='\n-----\n')
prints:
Player X: a2
|X|
-----
| |
-----
| |
Player O: b3
|X|
-----
| |O
-----
| |
Player X:
Modifying the print
statement so that it prints the grid in the exact form you want is left as an exercise to the reader (hint: you probably want to define a function like def print_grid(grid):
with a couple of nested for
loops), but hopefully seeing that you can handle the input part with one line of code instead of thirty-six lines of code gives you the general idea of how much easier the logic of looking up individual squares in the grid can be if you use a data structure rather than one variable per square.
(Having things in an organized data structure can also make it easier when it's time to implement checking for win conditions -- instead of enumerating every possible winning board configuration by hand, you can iterate over each row, iterate over each column across all rows, etc.)
CodePudding user response:
This isn't a complete solution but it covers the core elements for simplifying the task. The game grid has 9 locations:
1 | 2 | 3
---------
4 | 5 | 6
---------
7 | 8 | 9
It's much simpler to use the numbers 1 to 9 as possible input values.
def initialise_grid():
return [str(n) for n in range(1, 10)]
grid_state = initialise_grid()
# ['1', '2', '3', '4', '5', '6', '7', '8', '9']
Validating the player input becomes a lot simpler.
player_move = int(input())
if (player_move < 1
or player_move > 9
or grid_state[player_move - 1] != str(player_move)):
print("Invalid choice!")
Update grid_state
to assign the player's token ('X' / 'O') to the chosen grid location.
grid_state[player_move - 1] = player_token
There are 8 possible winning scenarios to check. A win is determined by confirming that the current player's token is present in each of the three locations for one of the listed winning scenarios.
def has_won(player_token, grid_state):
win_scenarios = [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6),
(1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]
for scenario in win_scenarios:
if all(player_token in grid_state[position] for position in scenario):
return True
return False