// a sort of alpha-beta pruning greedy algorithm, hacky, but it works (Originally used for GOMOKU, but the principle should still work) private int[] AlphaBetaMax(Board board, int depth, float alpha, float beta, GameplayPieceTypes playingPieces) { int[] v = MaxModelPoints((int)playingPieces, board); if (depth <= 0) { return(v); } int[] best = new int[] { -1, -1, -10000 }; ArrayList points = Gen(board); for (int i = 0; i < points.Count; i++) { int[] p = (int[])points[i]; board.GetSimplifiedGameBoard()[p[0], p[1]] = (int)playingPieces == 1 ? GameplayPieceTypes.X_Pieces : GameplayPieceTypes.O_Pieces; v = AlphaBetaMax(board, depth - 1, best[2] > alpha ? best[2] : alpha, beta, playingPieces); board.GetSimplifiedGameBoard()[p[0], p[1]] = 0; if (v[2] > best[2]) { best = v; } if (v[2] > beta) { break; } } return(best); }
public void InitTurnTracker(GameplayMatchPresets presets) { player1GamePiece = presets.P1Pieces; _player2GamePiece = presets.P2Pieces; player1Type = presets.P1Type; player2Type = presets.P2Type; _currentPlayerTurn = GameplayPlayerTurnTypes.P1Turn; // _currentPlayerTurn = startingPlayerTurn; // _player2GamePiece = player1GamePiece == GameplayPieceTypes.O_Pieces ? GameplayPieceTypes.X_Pieces : GameplayPieceTypes.O_Pieces; }
// Somewhat naive approach to implement a Tic Tac Toe A.I. // I honestly don't know much about the strategy involved in the game, but i'm assuming // the steps described below make sense and work as a base for a somewhat decent A.I. that can play this sort of games public Vector2Int MakeMove(Board gameplayBoard, TurnTracker turnTracker, GameplayBotDifficulty difficulty = GameplayBotDifficulty.EASY) { // Get available spaces var boardFreePositions = gameplayBoard.GetAvailableLocations(); // if the game is set to easy difficulty if (difficulty == GameplayBotDifficulty.EASY) { // Just pick something at random return(boardFreePositions[Mathf.FloorToInt(Random.Range(0, boardFreePositions.Count))]); } // Else make a move using a better strategy // Get the play pieces for each player GameplayPieceTypes ownedPieces = turnTracker.GetCurrentTurnPieceType(); GameplayPieceTypes rivalPieces = turnTracker.GetRivalTurnPieceType(); //if first move, or the center has not been taken, take center (assuming this is the best possible position to take, as this is the case in most board games) var bestMove = new Vector2Int(1, 1); if (difficulty == GameplayBotDifficulty.MEDIUM) { if (boardFreePositions.Contains((bestMove))) { // Just pick something at random return(boardFreePositions[Mathf.FloorToInt(Random.Range(0, boardFreePositions.Count))]); } var scoresMedium = this.AlphaBetaMax(gameplayBoard, 0, Mathf.Infinity, -Mathf.Infinity, ownedPieces); // return bestMove; return(new Vector2Int(scoresMedium[0], scoresMedium[1])); } //if first move, or the center has not been taken, take center (assuming this is the best possible position to take, as this is the case in most board games) if (boardFreePositions.Contains((bestMove))) { return(bestMove); } // higher depth means, even further analisis of deeper brancher of the possible plays var scoresHard = this.AlphaBetaMax(gameplayBoard, 3, Mathf.Infinity, -Mathf.Infinity, ownedPieces); // return bestMove; return(new Vector2Int(scoresHard[0], scoresHard[1])); }
private bool CheckGameOver(int x, int y, GameplayPieceTypes gamePiece) { int score = 1; int pieceGoal = 3; // check for 3 in a row for (int i = 1; i < 3; i++) { if (x + i < this._gameBoard.BoardWidth) { if (this._gameBoard.GetSimplifiedGameBoard()[x + i, y] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } for (int i = 1; i < 3; i++) { if (x - i >= 0) { if (this._gameBoard.GetSimplifiedGameBoard()[x - i, y] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } // 3 in a colum score = 1; for (int i = 1; i < 3; i++) { if (y + i < this._gameBoard.BoardHeight) { if (this._gameBoard.GetSimplifiedGameBoard()[x, y + i] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } for (int i = 1; i < 3; i++) { if (y - i >= 0) { if (this._gameBoard.GetSimplifiedGameBoard()[x, y - i] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } // 3 in diagonal score = 1; for (int i = 1; i < 3; i++) { if (x + i < this._gameBoard.BoardWidth && y + i < this._gameBoard.BoardHeight) { if (this._gameBoard.GetSimplifiedGameBoard()[x + i, y + i] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } for (int i = 1; i < 3; i++) { if (x - i >= 0 && y - i >= 0) { if (this._gameBoard.GetSimplifiedGameBoard()[x - i, y - i] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } //3 in inverse diagonal score = 1; for (int i = 1; i < 3; i++) { if (x + i < this._gameBoard.BoardWidth && y - i >= 0) { if (this._gameBoard.GetSimplifiedGameBoard()[x + i, y - i] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } for (int i = 1; i < 3; i++) { if (x - i >= 0 && y + i < this._gameBoard.BoardHeight) { if (this._gameBoard.GetSimplifiedGameBoard()[x - i, y + i] == gamePiece) { score++; } else { break; } } } if (score >= pieceGoal) { return(true); } return(false); }