TicTacToe in Python

This is my second attempt to make Tic Tac Toe in Python. It's a part of my learning. Tomorrow I'll work on some simple AI and better menu. What do you think about it? What changes do you suggest? Code:

class Field:
val = " "
pos = 0
weight = 0

def __init__(self, n):
self.pos = n
self.val = str(n)

def display_board(b):
br = 1

for i in b:
if br >= 3:
print("[", i.val, "]", end='\n')
br = 0
else:
print("[", i.val, "]", end='')

br += 1

def did_player_won(b, t):
indexes = (
(0, 1, 2), (3, 4, 5), (6, 7, 8),  # Rows
(0, 3, 6), (1, 4, 7), (2, 5, 8),  # Cols
(0, 4, 8), (2, 4, 6)              # Diag
)

for idx in indexes:
if sum(b[i].weight for i in idx if b[i].val == t) == 15:
return True

def get_move(b, turn):
# Get user input while it's wrong
while True:
try:
move = int(input("Player %s turn!\n>>>" % turn))
# if input isn't an integer
except ValueError:
print("Wrong field!")
continue
else:
if 0 < move < 10:
for item in b:
if item.pos == move:
# Check if place is taken
if item.val == "X" or item.val == "O":
print("Field is taken!")
continue
else:
item.val = turn
item.weight = 5
print("Player %s took place %d" % (turn, move))
return True
else:
print("Incorrect field!")
continue

def next_turn(currentturn):
if currentturn == "X":
return "O"
else:
return "X"

def reset_game():
global board
global turn
global turns

board = [Field(7), Field(8), Field(9),
Field(4), Field(5), Field(6),
Field(1), Field(2), Field(3)]

turn = "X"
turns = 0

board = [Field(7), Field(8), Field(9),
Field(4), Field(5), Field(6),
Field(1), Field(2), Field(3)]

turn = "X"
turns = 0
moveMessage = "Player (%s) move: " % turn

while True:
display_board(board)

if turns >= 9:
display_board(board)
print("Draw!")
choice = input(">>>")

if choice == "play":
reset_game()
else:
break

if get_move(board, turn):
if did_player_won(board, turn):
display_board(board)
print("Player %s won! Congrats Comrade! It's OUR win!" % turn)
choice = input(">>>")

if choice == "play":
reset_game()
else:
break
else:
turn = next_turn(turn)
turns += 1


There is a general principle in programming that you want to avoid repeating yourself. For example, you define the starting game set up twice, once in the reset function and once in the main script. You could just have the function and then call it in the main script to set up the first game. This means if you ever want to change it, you just have to update one place.

When using try and catch, it is often easier to read if your logic for when stuff works goes in the try. That helps with reading the code in sequence as it is meant to be executed. This is a bit of a balancing act because you do want to be clear about what possible failures you are catching. In this case I would have padded it out.

My last suggestion is to consider using a class to hold the game state. This just helps keep things neat and tidy, especially when you look at doing AI. After all, your AI will need to imagine a bunch of game boards, and if you just have one board variable it will be hard.

The main loop that takes player input should be outside the class, but most other things should be in it.

• Thanks for suggestions! I know the "don't repeat yourself rule" but I completely forgot about changing game setup. Commented Apr 20, 2018 at 19:42

Not a major suggestion, but just a style suggestion.
You could use indent spacing of 2 instead of 4.
It would make the code look nicer.

Example

4 spaces indenting
def hi(crazy):
if crazy:
print("...")
else:
print("Hi there")

2 spaces indenting
def hi(crazy):
if crazy:
print("...")
else:
print("Hi there")

• PEP 8 python.org/dev/peps/pep-0008 recommends 4 spaces. While you are free to format your code at will you should not give misleading advice to others. Commented Apr 20, 2018 at 18:24
• I accept your answer. But just FYI, according to Google developers, they have an internal guideline that dictate 2 space instead of 4 spaces. Commented Apr 21, 2018 at 2:42