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(): 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 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) def game(train): global state state = 12 lastMove = None while True: # KI beginnt, sonst kann sie nicht gewinnen move = ki_move() 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.")