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: # Wenn der andere Spieler bei diesem Zug verliert return n return random.randint(1, 3) # Wenn keine perfekte Wahl, dann irgendein Zug def random_move(): return random.randint(1, 3) def ki_move(lastMove, better_version): 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. if better_version: 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, opponent, better_version): global state state = 12 lastMove = None while True: # KI beginnt, sonst kann sie nicht gewinnen move = ki_move(lastMove, better_version) lost = makeMove(move) if lost: if train: addLostMove(state + move, move) return 0 # optimale Strategie hat gewonnen lastMove = Move(state + move, move) move = opponent() lost = makeMove(move) if lost: return 1 # KI hat gewonnen state = 12 lostMoves = {} # train opponents = [random_move, optimal_move] for ki_version in [False, True]: for train_opponent in opponents: for eval_opponent in opponents: ki_text = "optimale Version" if ki_version else "erste Version" print(f"KI: {ki_text} trainiert mit {train_opponent.__name__} und evaluiert mit {eval_opponent.__name__}") for _ in range(1000): game(train=True, opponent=train_opponent, better_version=ki_version) # eval numberEvalGames = 100000 wonGames = 0 for _ in range(numberEvalGames): wonGames += game(False, opponent=eval_opponent, better_version=ki_version) print(f"Die KI hat {wonGames / numberEvalGames * 100}% der Spiele gewonnen.\n")