refactored repo
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
import tictactoe
|
||||
newGame = tictactoe.Tictactoe()
|
||||
newGame.main()
|
||||
@@ -1,69 +0,0 @@
|
||||
import tictactoe
|
||||
import random
|
||||
|
||||
|
||||
class Minimax:
|
||||
|
||||
def minimax(self, current_field, is_maximizing, player1_char, player2_char):
|
||||
checkwin = self.check_win(current_field, player1_char, player2_char)
|
||||
if checkwin == (1, 1): # Draw
|
||||
return 0, 0, 0
|
||||
if checkwin == (1, 0): # Player wins
|
||||
return -1, 0, 0
|
||||
if checkwin == (0, 1): # AI wins
|
||||
return 1, 0, 0
|
||||
|
||||
best_score = float('-inf') if is_maximizing else float('inf')
|
||||
best_move = None
|
||||
|
||||
for j in range(0, len(current_field), 2):
|
||||
for k in range(0, len(current_field), 2):
|
||||
if current_field[j][k] == " ":
|
||||
current_field[j][k] = player1_char if not is_maximizing else player2_char
|
||||
score = self.minimax(current_field, not is_maximizing, player1_char, player2_char)[0]
|
||||
current_field[j][k] = " "
|
||||
|
||||
if is_maximizing and score > best_score:
|
||||
best_score = score
|
||||
best_move = j, k
|
||||
elif not is_maximizing and score < best_score:
|
||||
best_score = score
|
||||
best_move = j, k
|
||||
|
||||
'''if best_score == 0 and best_move == (0, 0): # is None:
|
||||
empty_cells = [(j, k) for j in range(0, len(current_field), 2) for k in range(0, len(current_field), 2) if
|
||||
current_field[j][k] == " "]
|
||||
random.seed()
|
||||
random_move = random.choice(empty_cells)
|
||||
return 0, random_move[0], random_move[1]'''
|
||||
# else:
|
||||
if best_move is None:
|
||||
return 0, -1, -1 # No available moves
|
||||
else:
|
||||
# print('The next best move is:', best_move, "score: ", best_score)
|
||||
return best_score, best_move[1], best_move[0]
|
||||
|
||||
def check_win(self, ifield, player1_char, player2_char):
|
||||
# nothing 0, 0; draw 1, 1; win player1 1, 0; win player2 0, 1
|
||||
for j in range(0, len(ifield), 2):
|
||||
if ifield[j][0] == ifield[j][2] == ifield[j][4] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[j][0] == ifield[j][2] == ifield[j][4] == player2_char:
|
||||
return 0, 1
|
||||
elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player2_char:
|
||||
return 0, 1
|
||||
|
||||
if ifield[0][0] == ifield[2][2] == ifield[4][4] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[0][0] == ifield[2][2] == ifield[4][4] == player2_char:
|
||||
return 0, 1
|
||||
elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player2_char:
|
||||
return 0, 1
|
||||
elif all(ifield[j][k] != " " for j in range(len(ifield)) for k in range(len(ifield))):
|
||||
return 1, 1
|
||||
else:
|
||||
return 0, 0
|
||||
59
MVC/model.py
59
MVC/model.py
@@ -1,59 +0,0 @@
|
||||
import os.path
|
||||
if os.path.isfile("./savestate.py"):
|
||||
from savestate import save
|
||||
|
||||
class Model:
|
||||
field = None
|
||||
def __init__(self):
|
||||
self.field = [[" ", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
[" ", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
[" ", "|", " ", "|", " "]]
|
||||
|
||||
|
||||
|
||||
def do_move(self, x, y, player1, player1_char, player2_char):
|
||||
self.field[y*2][x*2] = (player1_char if player1 else player2_char)
|
||||
# printer()
|
||||
# win = check_win(field)
|
||||
# if win == (0, 0):
|
||||
# savetosavestate
|
||||
"""player1 = not player1
|
||||
turn() controller"""
|
||||
'''elif win == (1, 1):
|
||||
elif win == (1, 0):
|
||||
elif win == (0, 1):
|
||||
'''
|
||||
|
||||
def loadsavestate(self):
|
||||
if os.path.isfile('./savestate.py'):
|
||||
from savestate import save
|
||||
self.field = save
|
||||
|
||||
def checksavestate(self):
|
||||
if os.path.isfile('./savestate.py'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def savetosavestate(self):
|
||||
f = open("savestate.py", "w")
|
||||
f.write("save = " + repr(self.field))
|
||||
f.close()
|
||||
|
||||
def deletesavestate(self):
|
||||
os.remove("savestate.py")
|
||||
|
||||
|
||||
def check_move(self, x, y, verbose):
|
||||
|
||||
x = int(x * 2)
|
||||
y = int(y * 2)
|
||||
if not self.field[y][x] == " ":
|
||||
if verbose:
|
||||
# self.printer.occupied()
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
# else:
|
||||
# do_move(x, y)
|
||||
@@ -1,16 +0,0 @@
|
||||
class Playerhandler:
|
||||
|
||||
player1 = None # bool that states which player is currently playing
|
||||
player1_char = None
|
||||
player2_char = None
|
||||
ai = None
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.player1 = True # bool that states which player is currently playing
|
||||
self.player1_char = "X"
|
||||
self.player2_char = "O"
|
||||
self.ai = False
|
||||
'''
|
||||
def getPlayer(self):
|
||||
return'''
|
||||
@@ -1,82 +0,0 @@
|
||||
# Das hier ist die View
|
||||
|
||||
class Printer:
|
||||
def printfield(self, ifield): # function that prints the field
|
||||
print(" 0 1 2", end="\n")
|
||||
for j in range(0, len(ifield)):
|
||||
print("0" if j == 0 else "1" if j == 2 else "2" if j == 4 else " ", end=" ")
|
||||
for k in range(0, len(ifield)):
|
||||
print(str(ifield[j][k]), end=" ")
|
||||
print("\n", end="")
|
||||
|
||||
|
||||
def occupied(self):
|
||||
print("Your given coordinates are already occupied. \nPlease Try again.\n")
|
||||
|
||||
def aicalc(self):
|
||||
print("Next move is being calculated...")
|
||||
|
||||
def aimoved(self, best_move):
|
||||
print("AI moved to ", best_move[1] // 2, best_move[2] // 2)
|
||||
|
||||
def playermove(self, player1, player1_char, player2_char):
|
||||
while True:
|
||||
next_move_x = int(input(f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}), please choose the x (horizontal) coordinates of your next move: "))
|
||||
if next_move_x in list(range(3)):
|
||||
break
|
||||
else:
|
||||
print("Please be sure to input a valid number (0-2). \nPlease try Again.")
|
||||
|
||||
while True:
|
||||
next_move_y = int(input(
|
||||
f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}), please choose the y ("
|
||||
f"vertical) coordinates of your next move: "))
|
||||
if next_move_y in list(range(3)):
|
||||
break
|
||||
else:
|
||||
print("Please be sure to input a valid number (0-2). \nPlease try Again.")
|
||||
|
||||
next_move = (next_move_x, next_move_y)
|
||||
return next_move
|
||||
|
||||
def welcomemessage(self):
|
||||
print("Welcome to Kat&Paul's TicTacToe:")
|
||||
|
||||
def checksavestate(self):
|
||||
return input("An older savestate has been found. Do you want to continue it? (y/n): ")
|
||||
|
||||
def invalidsavestate(self):
|
||||
return input("That was not a valid input. Type y/n if you want to continue or not: ")
|
||||
|
||||
def checkai(self):
|
||||
inp = input("Do you want to play against AI or local multiplayer? 1/2: ")
|
||||
|
||||
|
||||
while True:
|
||||
if inp == "1":
|
||||
return 1
|
||||
break
|
||||
elif inp == "2":
|
||||
return 2
|
||||
break
|
||||
return 3
|
||||
|
||||
def invalidai(self):
|
||||
print("That was not a valid input. Please try again. ")
|
||||
# return 0
|
||||
# return input("That was not a valid input. Type 1/2 if you want to play against AI or local multiplayer: ")
|
||||
|
||||
def startsplaying(self, player1, player1_char, player2_char):
|
||||
print(f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}) will start playing.")
|
||||
|
||||
|
||||
def endmessage(self,i, j, ai):
|
||||
if i == 1 and j == 1:
|
||||
print("Its a draw.")
|
||||
if i == 1 and j == 0:
|
||||
print("Player 1 won.")
|
||||
if i == 0 and j == 1 and ai:
|
||||
print("AI won.")
|
||||
if i == 0 and j == 1 and not ai:
|
||||
print("Player 2 won.")
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
from unittest.mock import Mock
|
||||
import unittest
|
||||
import tictactoe
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
class MockPrinter:
|
||||
# Define mock methods here that mimic the behavior of the Printer class...
|
||||
def printfield(self, ifield):
|
||||
pass # Mock methods do nothing
|
||||
|
||||
def occupied(self):
|
||||
pass
|
||||
|
||||
def aicalc(self):
|
||||
pass
|
||||
|
||||
def aimoved(self, best_moev):
|
||||
pass
|
||||
|
||||
def playermove(self, player1, player1_char, player2_char):
|
||||
next_move = (0, 1)
|
||||
return next_move
|
||||
|
||||
class TestTicTacToe(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# self.tictactoe = tictactoe.TicTacToe()
|
||||
# self.tictactoe.printer = MockPrinter()
|
||||
self.game = tictactoe.Tictactoe()
|
||||
self.game.printer = MockPrinter()
|
||||
|
||||
@patch('builtins.input', side_effect=[0, 1]) # Mock user inputs 0 for x and 1 for y
|
||||
def test_turn(self, mock_input):
|
||||
# Initialize the field with empty spots
|
||||
self.game.ifield = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]
|
||||
|
||||
player1 = True
|
||||
player1_char = "X"
|
||||
player2_char = "O"
|
||||
|
||||
expected_result = (0, 1)
|
||||
#result = self.game.turn(player1, player1_char, player2_char)
|
||||
result = self.game.turn()
|
||||
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
def test_check_win(self):
|
||||
player1_char = 'X'
|
||||
player2_char = 'O'
|
||||
|
||||
# Testing player 1 win condition
|
||||
field = [["X", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
["X", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
["X", "|", " ", "|", " "]]
|
||||
|
||||
result = self.game.check_win(field, player1_char, player2_char)
|
||||
self.assertEqual(result, (1, 0))
|
||||
|
||||
# Testing player 2 win condition
|
||||
field = [["O", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
["O", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
["O", "|", " ", "|", " "]]
|
||||
|
||||
result = self.game.check_win(field, player1_char, player2_char)
|
||||
self.assertEqual(result, (0, 1))
|
||||
|
||||
# Testing draw condition
|
||||
field = [["X", "|", "O", "|", "X"],
|
||||
["—", "+", "—", "+", "—"],
|
||||
["X", "|", "O", "|", "O"],
|
||||
["—", "+", "—", "+", "—"],
|
||||
["O", "|", "X", "|", "X"]]
|
||||
|
||||
result = self.game.check_win(field, player1_char, player2_char)
|
||||
self.assertEqual(result, (1, 1))
|
||||
|
||||
# Testing no win condition
|
||||
field = [[" ", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
[" ", "|", " ", "|", " "],
|
||||
["—", "+", "—", "+", "—"],
|
||||
[" ", "|", " ", "|", " "]]
|
||||
|
||||
result = self.game.check_win(field, player1_char, player2_char)
|
||||
self.assertEqual(result, (0, 0))
|
||||
|
||||
|
||||
def test_play_game(self):
|
||||
expected_result = True
|
||||
# Call the method you want to test
|
||||
result = self.tictactoe.play_game()
|
||||
# Add assertions to check the result
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
131
MVC/tictactoe.py
131
MVC/tictactoe.py
@@ -1,131 +0,0 @@
|
||||
import os.path
|
||||
import random
|
||||
import printer
|
||||
import playerhandler
|
||||
import model
|
||||
import minimax
|
||||
|
||||
|
||||
class Tictactoe:
|
||||
printer = None
|
||||
playerhandler = None
|
||||
minimax = None
|
||||
model = None
|
||||
|
||||
def __init__(self):
|
||||
self.printer = printer.Printer()
|
||||
self.playerhandler = playerhandler.Playerhandler()
|
||||
self.minimax = minimax.Minimax()
|
||||
self.model = model.Model()
|
||||
|
||||
def turn(self): # function that checks whose turn it is and where they can place their symbol
|
||||
self.printer.printfield(self.model.field)
|
||||
if self.playerhandler.ai and not self.playerhandler.player1:
|
||||
self.printer.aicalc()
|
||||
best_move = self.minimax.minimax(self.model.field, not self.playerhandler.player1,
|
||||
self.playerhandler.player1_char, self.playerhandler.player2_char)
|
||||
self.printer.aimoved(best_move)
|
||||
self.model.do_move(best_move[1] // 2, best_move[2] // 2, self.playerhandler.player1,
|
||||
self.playerhandler.player1_char,
|
||||
self.playerhandler.player2_char)
|
||||
# self.printer.printfield(self.model.field)
|
||||
|
||||
else:
|
||||
while True:
|
||||
nextmove = self.printer.playermove(self.playerhandler.player1, self.playerhandler.player1_char,
|
||||
self.playerhandler.player2_char)
|
||||
next_move_x, next_move_y = nextmove
|
||||
# return self.model.check_move(next_move_x, next_move_y, True)
|
||||
|
||||
if self.model.check_move(next_move_x, next_move_y, True):
|
||||
self.model.do_move(next_move_x, next_move_y, self.playerhandler.player1,
|
||||
self.playerhandler.player1_char, self.playerhandler.player2_char)
|
||||
break
|
||||
# self.playerhandler.player1 = not self.playerhandler.player1
|
||||
else:
|
||||
self.printer.occupied()
|
||||
self.printer.printfield(self.model.field)
|
||||
|
||||
win = self.check_win(self.model.field, self.playerhandler.player1_char, self.playerhandler.player2_char)
|
||||
if win == (0, 0):
|
||||
self.model.savetosavestate()
|
||||
self.playerhandler.player1 = not self.playerhandler.player1
|
||||
self.turn()
|
||||
elif win == (1, 1):
|
||||
self.model.deletesavestate()
|
||||
elif win == (1, 0):
|
||||
self.model.deletesavestate()
|
||||
elif win == (0, 1):
|
||||
self.model.deletesavestate()
|
||||
self.printer.printfield(self.model.field)
|
||||
self.printer.endmessage(win[0], win[1], self.playerhandler.ai)
|
||||
exit()
|
||||
# self.turn()
|
||||
|
||||
def check_win(self, ifield, player1_char, player2_char):
|
||||
# nothing 0, 0; draw 1, 1; win player1 1, 0; win player2 0, 1
|
||||
for j in range(0, len(ifield), 2):
|
||||
if ifield[j][0] == ifield[j][2] == ifield[j][4] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[j][0] == ifield[j][2] == ifield[j][4] == player2_char:
|
||||
return 0, 1
|
||||
elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[0][j] == ifield[2][j] == ifield[4][j] == player2_char:
|
||||
return 0, 1
|
||||
|
||||
if ifield[0][0] == ifield[2][2] == ifield[4][4] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[0][0] == ifield[2][2] == ifield[4][4] == player2_char:
|
||||
return 0, 1
|
||||
elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player1_char:
|
||||
return 1, 0
|
||||
elif ifield[0][4] == ifield[2][2] == ifield[4][0] == player2_char:
|
||||
return 0, 1
|
||||
elif all(ifield[j][k] != " " for j in range(len(ifield)) for k in range(len(ifield))):
|
||||
return 1, 1
|
||||
else:
|
||||
return 0, 0
|
||||
|
||||
# verbose = True
|
||||
|
||||
def main(self):
|
||||
inp = None
|
||||
self.printer.welcomemessage()
|
||||
if self.model.checksavestate():
|
||||
inp = self.printer.checksavestate()
|
||||
while True:
|
||||
if inp == "n":
|
||||
break
|
||||
|
||||
if inp == "y":
|
||||
self.model.loadsavestate() # self.tictactoe.checksavestateplayer()
|
||||
spacecount = 0
|
||||
for j in range(0, len(self.model.field)):
|
||||
for k in range(0, len(self.model.field)):
|
||||
if self.model.field[j][k] == " ":
|
||||
spacecount += 1
|
||||
if spacecount % 2 == 0:
|
||||
self.playerhandler.player1 = False
|
||||
break
|
||||
# self.printer.checkai()
|
||||
|
||||
# inp = self.printer.invalidsavestate()
|
||||
|
||||
# inp = self.printer.checkai()
|
||||
while True:
|
||||
checkai = self.printer.checkai()
|
||||
if checkai == 1:
|
||||
self.playerhandler.ai = True
|
||||
break
|
||||
elif checkai == 2:
|
||||
break
|
||||
elif checkai == 3:
|
||||
self.printer.invalidai()
|
||||
|
||||
# checkai = self.printer.invalidai()
|
||||
|
||||
# printer.printfield(self.model.field)
|
||||
self.printer.startsplaying(self.playerhandler.player1, self.playerhandler.player1_char,
|
||||
self.playerhandler.player2_char)
|
||||
self.turn()
|
||||
Reference in New Issue
Block a user