I’m using a connect four class I wrote a while back:
class ConnectFour():
turn = 0
evanorodd = 0
gameover = False
xwin = 0
owin = 0
def __init__(self):
self.board = [[" " for column in range(15)] for row in range(6)]
for row_index, row in enumerate(self.board):
for col_index, item in enumerate(row):
if col_index % 2 == 0:
self.board[row_index][col_index] = "|"
def printer(self):
if self.gameover == True:
print("\nThe final board state:")
else:
print("\nTurn {turn}.".format(turn=ConnectFour.turn))
print("\n 1 2 3 4 5 6 7")
for row in self.board:
for item in row:
print(item, end = " ")
print()
def available_moves(self):
moves = []
for i in range(1, 14, 1):
if self.board[0][i] == " ":
moves.append(i)
return moves
moves.clear()
def inputter(self, col_index):
self.turn += 1
self.evanorodd += 1
num = col_index * 2 - 1
if num >=1 and num <= 13 and num % 2 != 0:
if self.board[0][num] == " ":
for i in range(5, -1, -1):
if self.board[i][num] == " ":
if self.evanorodd % 2 != 0:
self.board[i][num] = "X"
break
else:
self.board[i][num] = "O"
break
else:
self.evanorodd -= 1
print("\nI'm afraid that column is full. Choose another one.")
else:
self.evanorodd -= 1
print("\nYou need to give a column number from one to seven.")
def checker(self):
# checks vertical
for row in range(5, 2, -1):
for column in range(1, 14, 2):
if self.board[row][column] == self.board[row-1][column] and self.board[row][column] == self.board[row-2][column] and self.board[row][column] == self.board[row-3][column]:
if self.board[row][column] == "X":
print("\nThe game is over! Crosses win with a vertical connect four!")
self.gameover = True
self.xwin = 1
elif self.board[row][column] == "O":
print("\nThe game is over! Naughts win with a vertical connect four!")
self.gameover = True
self.owin = -1
# checks horizontal
for row in range(5, -1, -1):
for column in range(1, 8, 2):
if self.board[row][column] == self.board[row][column+2] and self.board[row][column] == self.board[row][column+4] and self.board[row][column] == self.board[row][column+6]:
if self.board[row][column] == "X":
print("\nThe game is over! Crosses win with a horizontal connect four!")
self.gameover = True
self.xwin = 1
elif self.board[row][column] == "O":
print("\nThe game is over! Naughts win with a horizontal connect four!")
self.gameover = True
self.owin = -1
# checks diagonal going from left to right
for row in range(5, 2, -1):
for column in range(1, 8, 2):
if self.board[row][column] == self.board[row-1][column+2] and self.board[row][column] == self.board[row-2][column+4] and self.board[row][column] == self.board[row-3][column+6]:
if self.board[row][column] == "X":
print("\nThe game is over! Crosses win along a positive diagonal!")
self.gameover = True
self.xwin = 1
elif self.board[row][column] == "O":
print("\nThe game is over! Naughts win along a positive diagonal!")
ConnectFour.gameover = True
ConnectFour.owin = -1
# checks diagonal going from right to left
for row in range(5, 2, -1):
for column in range(13, 6, -2):
if self.board[row][column] == self.board[row-1][column-2] and self.board[row][column] == self.board[row-2][column-4] and self.board[row][column] == self.board[row-3][column-6]:
if self.board[row][column] == "X":
print("\nThe game is over! Crosses win along a negative diagonal!")
self.gameover = True
self.xwin = 1
elif self.board[row][column] == "O":
print("The game is over! Naughts win along a negative diagonal!")
self.gameover = True
self.owin = -1
play = ConnectFour()
play.inputter(3)
def evaluate_board(play):
if ConnectFour.gameover == True:
if play.xwin == 1:
return float("Inf")
elif play.owin == -1:
return -float("Inf")
else:
num_top_x = 0
num_top_o = 0
if play.board[5][5] == "X":
num_top_x += 1
return num_top_x - num_top_o
def minimax(play, is_maximizing, depth, alpha, beta, evaluate_board):
if ConnectFour.gameover or depth == 0:
return [evaluate_board(play), ""]
if is_maximizing == True:
best_value = -float("Inf")
moves = play.available_moves()
random.shuffle(moves)
best_move = moves[0]
for move in moves:
copied = copy.deepcopy(play)
copied.inputter(move)
hypothetical_value = minimax(copied, False, depth - 1, alpha, beta, evaluate_board)[0]
if hypothetical_value > best_value:
best_value = hypothetical_value
best_move = move
alpha = max(alpha, best_value)
if alpha >= beta:
break
return [best_value, best_move]
else:
best_value = float("Inf")
moves = play.available_moves()
random.shuffle(moves)
best_move = moves[0]
for move in moves:
copied = copy.deepcopy(play)
copied.inputter(move)
hypothetical_value = minimax(copied, True, depth -1, alpha, beta, evaluate_board)[0]
if hypothetical_value < best_value:
best_value = hypothetical_value
best_move = move
beta = min(beta, best_move)
if alpha >= beta:
break
return [best_value, best_move]
print(minimax(play, True, 4, -float("Inf"), float("Inf"), evaluate_board))
ai = input("Would you like to play against an AI? Y or N?: ")
while ai.lower() != "y" and ai.lower() != "n":
ai = input("Please enter either Y for yes or N for no: ")
if ai.lower() == "n":
while ConnectFour.evanorodd < 43:
play.printer()
try:
columnnumber = int(input("Enter a column number from one to seven: "))
except ValueError:
columnnumber = int(input("\nPlease give an integer!: "))
play.inputter(columnnumber)
play.checker()
if ConnectFour.gameover == True:
play.printer()
break
if ConnectFour.evanorodd == 42:
ConnectFour.gameover = True
print("\nThe game is drawn!")
play.printer()
break
elif ai.lower() == "y":
print("eee")
When I run the code, I get this error:
Traceback (most recent call last):
File "connect4.py", line 166, in <module>
print(minimax(play, True, 4, -float("Inf"), float("Inf"), evaluate_board))
File "connect4.py", line 135, in minimax
hypothetical_value = minimax(copied, False, depth - 1, alpha, beta, evaluate_board)[0]
File "connect4.py", line 151, in minimax
hypothetical_value = minimax(copied, True, depth -1, alpha, beta, evaluate_board)[0]
File "connect4.py", line 135, in minimax
hypothetical_value = minimax(copied, False, depth - 1, alpha, beta, evaluate_board)[0]
File "connect4.py", line 152, in minimax
if hypothetical_value < best_value:
TypeError: '<' not supported between instances of 'NoneType' and 'float'
I guess this error means that hypothetical_value currently equals “NoneType” rather than a number like a float or integer etc. Been playing around with this for a while, but this error persists.
I originally had my own code for the minimax function, but ended up using the one from this project to see what I was doing wrong (modified though as I used a class):
https://www.codecademy.com/courses/machine-learning/projects/minimax-connect-four
That did not help. I kind of realise the error must be something to do with how I’m using the ConnectFour class, but I don’t think I know enough about OOP to understand what I’m doing wrong.
I realise this might be quite the ask. I’d appreciate any help at all.