<?php
abstract class Game { protected $currentPlayer; protected $board;
abstract public function getLegalMoves();
abstract public function makeMove($move);
abstract public function undoMove($move);
abstract public function isGameOver();
abstract public function evaluate();
abstract public function getWinner(); }
class MinimaxSolver {
public static function minimax(Game $game, $depth, $maximizingPlayer) { if ($depth == 0 || $game->isGameOver()) { return $game->evaluate(); } if ($maximizingPlayer) { $bestValue = -PHP_INT_MAX; foreach ($game->getLegalMoves() as $move) { $game->makeMove($move); $value = self::minimax($game, $depth - 1, false); $game->undoMove($move); $bestValue = max($bestValue, $value); } return $bestValue; } else { $bestValue = PHP_INT_MAX; foreach ($game->getLegalMoves() as $move) { $game->makeMove($move); $value = self::minimax($game, $depth - 1, true); $game->undoMove($move); $bestValue = min($bestValue, $value); } return $bestValue; } }
public static function getBestMove(Game $game, $depth) { $bestMove = null; $bestValue = -PHP_INT_MAX; foreach ($game->getLegalMoves() as $move) { $game->makeMove($move); $value = self::minimax($game, $depth - 1, false); $game->undoMove($move); if ($value > $bestValue) { $bestValue = $value; $bestMove = $move; } } return $bestMove; }
public static function alphabeta(Game $game, $depth, $alpha, $beta, $maximizingPlayer) { if ($depth == 0 || $game->isGameOver()) { return $game->evaluate(); } if ($maximizingPlayer) { $value = -PHP_INT_MAX; foreach ($game->getLegalMoves() as $move) { $game->makeMove($move); $value = max($value, self::alphabeta($game, $depth - 1, $alpha, $beta, false)); $game->undoMove($move); $alpha = max($alpha, $value); if ($value >= $beta) { break; } } return $value; } else { $value = PHP_INT_MAX; foreach ($game->getLegalMoves() as $move) { $game->makeMove($move); $value = min($value, self::alphabeta($game, $depth - 1, $alpha, $beta, true)); $game->undoMove($move); $beta = min($beta, $value); if ($value <= $alpha) { break; } } return $value; } }
public static function getBestMoveAlphaBeta(Game $game, $depth) { $bestMove = null; $bestValue = -PHP_INT_MAX; $alpha = -PHP_INT_MAX; $beta = PHP_INT_MAX; foreach ($game->getLegalMoves() as $move) { $game->makeMove($move); $value = self::alphabeta($game, $depth - 1, $alpha, $beta, false); $game->undoMove($move); if ($value > $bestValue) { $bestValue = $value; $bestMove = $move; } $alpha = max($alpha, $bestValue); } return $bestMove; }
public static function getBestMoveWithOrdering(Game $game, $depth) { $bestMove = null; $bestValue = -PHP_INT_MAX; $alpha = -PHP_INT_MAX; $beta = PHP_INT_MAX; $moves = self::orderMoves($game, $game->getLegalMoves()); foreach ($moves as $move) { $game->makeMove($move); $value = self::alphabeta($game, $depth - 1, $alpha, $beta, false); $game->undoMove($move); if ($value > $bestValue) { $bestValue = $value; $bestMove = $move; } $alpha = max($alpha, $bestValue); if ($alpha >= $beta) { break; } } return $bestMove; }
private static function orderMoves(Game $game, $moves) { $scoredMoves = []; foreach ($moves as $move) { $score = 0; if (method_exists($game, 'isCapture') && $game->isCapture($move)) { $score += 100; } if (method_exists($game, 'isThreatening') && $game->isThreatening($move)) { $score += 50; } $scoredMoves[] = ['move' => $move, 'score' => $score]; } usort($scoredMoves, function($a, $b) { return $b['score'] - $a['score']; }); return array_column($scoredMoves, 'move'); } }
?>
|