80 lines
2.0 KiB
Python
80 lines
2.0 KiB
Python
import random
|
|
from dataclasses import dataclass
|
|
|
|
@dataclass
|
|
class Move:
|
|
state: int
|
|
move: int
|
|
|
|
def optimal_move():
|
|
global state
|
|
for n in [1, 2, 3]:
|
|
if (state - n) % 4 == 1:
|
|
return n
|
|
return random.randint(1, 3) # Wenn keine perfekte Wahl, dann irgendein Zug
|
|
|
|
def ki_move(lastMove):
|
|
global state
|
|
antiMoves = lostMoves.get(state)
|
|
if antiMoves == None:
|
|
return random.randint(1, 3)
|
|
availableMoves = [True, True, True]
|
|
for badMove in antiMoves:
|
|
availableMoves[badMove - 1] = False
|
|
for i, good in enumerate(availableMoves):
|
|
if good:
|
|
return i + 1
|
|
|
|
# Es gibt keine guten Züge mehr, also muss der letzte Zug schlecht gewesen sein.
|
|
addLostMove(lastMove.state, lastMove.move)
|
|
return random.randint(1, 3)
|
|
|
|
def makeMove(move): # gibt True zurück, wenn der Spieler verloren hat
|
|
global state
|
|
state -= move
|
|
|
|
# state kann auch kleiner 0 sein, da der Einfachheit halber am Ende auch Züge gemacht werden,
|
|
# die mehr alle Hölzchen wegnehmen. Dies wird dann so betrachtet, wie als wären 0 Hölzchen da.
|
|
return state <= 0
|
|
|
|
def addLostMove(state, move):
|
|
moves = lostMoves.get(state)
|
|
if moves == None:
|
|
moves = []
|
|
moves.append(move)
|
|
lostMoves[state] = moves
|
|
|
|
def game(train):
|
|
global state
|
|
state = 12
|
|
lastMove = None
|
|
while True:
|
|
# KI beginnt, sonst kann sie nicht gewinnen
|
|
move = ki_move(lastMove)
|
|
lost = makeMove(move)
|
|
if lost:
|
|
if train:
|
|
addLostMove(state + move, move)
|
|
return 0 # optimale Strategie hat gewonnen
|
|
lastMove = Move(state + move, move)
|
|
|
|
move = optimal_move()
|
|
lost = makeMove(move)
|
|
if lost:
|
|
return 1 # KI hat gewonnen
|
|
|
|
state = 12
|
|
lostMoves = {}
|
|
|
|
# train
|
|
for _ in range(1000):
|
|
game(True)
|
|
|
|
# eval
|
|
numberEvalGames = 100000
|
|
wonGames = 0
|
|
for _ in range(numberEvalGames):
|
|
wonGames += game(False)
|
|
|
|
print(f"Die KI hat {wonGames / numberEvalGames * 100}% der Spiele gewonnen.")
|