Skip to content

Instantly share code, notes, and snippets.

@Julien00859
Created March 21, 2024 22:48
Show Gist options
  • Save Julien00859/728cb6f53f60fff3b5a7c48779588073 to your computer and use it in GitHub Desktop.
Save Julien00859/728cb6f53f60fff3b5a7c48779588073 to your computer and use it in GitHub Desktop.
class TicTacToe:
def __init__(self, first_player="x"):
self.board = [[" " for _ in range(3)] for _ in range(3)]
self.player = first_player
self._turns = []
@property
def other_player(self):
return {"x": "y", "y": "x"}[self.player]
@property
def turn_no(self):
return len(self._turns)
def play(self, y, x):
if self.board[y][x] != " ":
return
self.board[y][x] = self.player
self.player = self.other_player
self._turns.append((y, x))
def cancel(self):
if not self._turns:
return
self.player = self.other_player
y, x = self._turns.pop()
self.board[y][x] = " "
return y, x
def plays(self):
for y in range(3):
for x in range(3):
if self.board[y][x] == " ":
yield y, x
def winner(self):
b = self.board
for y in range(3):
if all(b[y][0] == b[y][x] != " " for x in (1, 2)):
return b[y][0]
for x in range(3):
if all(b[0][x] == b[y][x] != " " for y in (1, 2)):
return b[0][x]
if all(b[0][0] == b[i][i] != " " for i in (1, 2)):
return b[0][0]
if all(b[2][0] == b[2-i][i] != " " for i in (1, 2)):
return b[2][0]
def draw(self):
return not next(self.plays(), False)
def __str__(self):
out = []
lines = iter(self.board)
out.append("|".join(next(lines)))
for line in lines:
out.append("-+-+-")
out.append("|".join(line))
return "\n".join(out)
def minmax(ttt, maxi):
if winner := ttt.winner():
return 1 if winner == "y" else -1
if ttt.draw():
return 0
scores = []
for y, x in ttt.plays():
ttt.play(y, x)
scores.append(minmax(ttt, not maxi))
ttt.cancel()
#if maxi and scores[-1] == 1:
# return 1
#if not maxi and scores[-1] == -1:
# return -1
return max(scores) if maxi else min(scores)
def ai(ttt):
scores = []
for y, x in ttt.plays():
ttt.play(y, x)
scores.append(((y, x), minmax(ttt, False)))
ttt.cancel()
#if scores[-1] == 1:
# return y, x
print(scores)
best = max(scores, key=lambda t: t[1])[0]
print("=>", best)
return best
print("Human plays x, AI plays y")
ttt = TicTacToe(input("First player (x/y)? "))
print(ttt)
while True:
#print(list(ttt.plays()))
if ttt.player == "x":
y, x = input("x: ").split()
else:
y, x = ai(ttt)
print("y:", y, x)
ttt.play(int(y), int(x))
print(ttt)
if winner := ttt.winner():
print(winner, "wins!")
break
if ttt.draw():
print("Draw!")
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment