/// <summary> /// Plays the AI turn /// </summary> public int PlayAiTurn(GameObject gameObject) { int aiPlayChoice = GameController.playersChoice.Equals("X") ? -1 : 1; minimaxAlgo.aiPick = aiPlayChoice; EndTurnPosition bestPositionToEndTurn = minimaxAlgo.GetBestPosition(aiPlayChoice, ConvertBoardToInt(gameObject), 0); int newBestPositionToPick = bestPositionToEndTurn.position; //hide ai ui choices from player foreach (GameObject boardPositions in this.positionArr) { foreach (KeyValuePair <string, int> integerStringMapperEntry in boardStringIntegerMapper) { if (integerStringMapperEntry.Key == boardPositions.name && integerStringMapperEntry.Value == newBestPositionToPick) { if (GameController.playersChoice != boardPositions.transform.GetChild(0).gameObject.name) { gameObject.GetComponent <MouseEvents>().renderPositionClicked(boardPositions.transform.GetChild(0).gameObject); gameObject.GetComponent <ColorControl>().RenderAiOtherChoiceInvisible(boardPositions); } else { gameObject.GetComponent <MouseEvents>().renderPositionClicked(boardPositions.transform.GetChild(1).gameObject); gameObject.GetComponent <ColorControl>().RenderAiOtherChoiceInvisible(boardPositions); } } } } return(newBestPositionToPick); }
public EndTurnPosition GetBestPosition(int calculateBestRouteFor, int[] gameBoard, int depth) { int isGameOver = IsGameOver(gameBoard); if (IsBoardFull(gameBoard) && isGameOver == 0) //tie { return(new EndTurnPosition(0)); } else if (isGameOver == 10) //win { return(new EndTurnPosition(10 - depth)); } else if (isGameOver == -10) //lose { return(new EndTurnPosition(depth - 10)); } depth++; EndTurnPosition levelBestPosition = createEndPositionForLevel(calculateBestRouteFor); //iterate over this tree level (all possible moves for the current game state) for (int boardPosition = 0; boardPosition < gameBoard.Length; boardPosition++) { //if current board position isnt filled by X or O if (gameBoard[boardPosition] == 0) { gameBoard[boardPosition] = calculateBestRouteFor; //invert turns between the opponents by multiplying by -1, clone the board (pass by value) so it wont reflect in other decisions on same level EndTurnPosition newPosition = GetBestPosition(calculateBestRouteFor * -1, (int[])gameBoard.Clone(), depth); //opponent to the AI - minimizes the result if (aiPick != calculateBestRouteFor) { if (newPosition.score <= levelBestPosition.score) { levelBestPosition.position = boardPosition; levelBestPosition.score = newPosition.score; } } else { //AI - maximizes the result if (newPosition.score >= levelBestPosition.score) { levelBestPosition.position = boardPosition; levelBestPosition.score = newPosition.score; } } //clears the selection that was made so next iteration (which is a node in same tree level) represents the board without it - the next permutation gameBoard[boardPosition] = 0; } } return(levelBestPosition); }
public EndTurnPosition GetMelhorPosicao(int calcularMelhorCaminho, int[] gameBoard, int nível) { int checkFimDeJogo = CheckFimDeJogo(gameBoard); if (tabuleiroCompleto(gameBoard) && checkFimDeJogo == 0) { return(new EndTurnPosition(0)); } else if (checkFimDeJogo == 10) { return(new EndTurnPosition(10 - nível)); } else if (checkFimDeJogo == -10) { return(new EndTurnPosition(nível - 10)); } nível++; EndTurnPosition levelBestPosition = CriarNoFolhaPorNivel(calcularMelhorCaminho); for (int boardPosition = 0; boardPosition < gameBoard.Length; boardPosition++) { if (gameBoard[boardPosition] == 0) { gameBoard[boardPosition] = calcularMelhorCaminho; //inverte o turno entre os jogadores, multiplicando por -1, clonando o tabuleiro (por parâmetro) para não refletir no mesmo nível de decisão do outro jogador EndTurnPosition newPosition = GetMelhorPosicao(calcularMelhorCaminho * -1, (int[])gameBoard.Clone(), nível); //oponente - minimizar resultado if (aiEscolha != calcularMelhorCaminho) { if (newPosition.score <= levelBestPosition.score) { levelBestPosition.position = boardPosition; levelBestPosition.score = newPosition.score; } } else { //AI - maximizar resultado if (newPosition.score >= levelBestPosition.score) { levelBestPosition.position = boardPosition; levelBestPosition.score = newPosition.score; } } //limpa a seleção para nao atrapalhar aproxima iteração do oponente (que é no mesmo nível de profundidade) gameBoard[boardPosition] = 0; } } return(levelBestPosition); }
private EndTurnPosition CriarNoFolhaPorNivel(int calcularMelhorCaminho) { EndTurnPosition levelBestPosition = new EndTurnPosition(); if (aiEscolha != calcularMelhorCaminho) { levelBestPosition.score = int.MaxValue; } else { levelBestPosition.score = int.MinValue; } return(levelBestPosition); }
private EndTurnPosition createEndPositionForLevel(int calculateBestRouteFor) { EndTurnPosition levelBestPosition = new EndTurnPosition(); //set default values for AI and opponent so they always pick first position returned to override default if (aiPick != calculateBestRouteFor) { levelBestPosition.score = int.MaxValue; } else { levelBestPosition.score = int.MinValue; } return(levelBestPosition); }