public IActionResult Index() { TicTacToeBoard board = new TicTacToeBoard(); List <Cell> cells = board.GetCells(); foreach (Cell cell in cells) { cell.Mark = TempData[cell.Id]?.ToString(); } board.CheckForWinner(); TicTacViewModel model = new TicTacViewModel { Cells = cells, Selected = new Cell { Mark = TempData["nextTurn"]?.ToString() ?? "X" }, IsGameOver = board.HasWinner || board.HasAllCellsSelected }; if (model.IsGameOver) { TempData["nextTurn"] = "X"; TempData["message"] = board.HasWinner ? $"{board.WinningMark} wins" : "Its a tie"; } else { TempData.Keep(); } return(View(model)); }
public int NegaMax(TicTacToeBoard game, Marker player, int depth) { int maxScore = -1; int sign = 1; if (game.CheckForWinner(game.Board, Marker.X)) // return score/move { return(StaticEvaluation(Marker.X)); } else if (game.CheckForWinner(game.Board, Marker.O)) { return(StaticEvaluation(Marker.O)); } else if (game.CheckForDraw(game.Board)) //return score/move { return(StaticEvaluation(Marker.Blank)); } if (player != Marker.X) { sign = -1; } List <Vector2> moves = game.FindBlankCells(game.Board); TicTacToeBoard gameCopy = new TicTacToeBoard(); int score = 0; foreach (Vector2 nextMove in moves) { gameCopy.Board = gameCopy.CopyBoard(game.Board); gameCopy.PlaceMarker(gameCopy.Board, player, nextMove); score = sign * NegaMax(gameCopy, gameCopy.GetOppositeMarker(player), depth + 1); if (score > maxScore) { maxScore = score; } } return(maxScore * sign); }
public void PlayTicTacToe( ) { if (IsGameover == false) { if (p1_X == null || p2_O == null) { return; } if (p1_X.IsTurnActive == true) { if (timed == false) { t = turnDelay + Time.time; timed = true; } if (Time.time < t) { return; } timed = false; TicTacToeMove bestMove = null; if (isSearching == false) { bestMove = p1_X.NegaMaxMove(board); // NEGAMAX tree-search isSearching = true; } if (bestMove != null) { FireRandomScribbleSFX( ); boardState[(int)bestMove.Cell.x][(int)bestMove.Cell.y] = Marker.X; cells[bestMove.Cell].GetComponent <SpriteRenderer>().sprite = Resources.Load <Sprite> (ResourcePath.x); p1_X.IsTurnActive = false; p2_O.IsTurnActive = true; if (board.CheckForWinner(boardState, Marker.X)) { GameWinner = "You lost!"; WinningCoordinates = board.WinningCoordinates; IsGameover = true; } if (board.CheckForDraw(boardState)) { GameWinner = "A draw - better than losing."; WinningCoordinates = null; IsGameover = true; } isSearching = false; } else { Debug.Log("AI is searching for a move ... "); return; } } else if (p2_O.IsTurnActive == true) { GameObject clicked = p2_O.ClickHandler <Grid2DVertexComponent> ( ); if (clicked == null) { return; } Vector2 m = clicked.transform.position; if (boardState[(int)m.x][(int)m.y] == Marker.Blank) //move success { FireRandomScribbleSFX( ); boardState[(int)m.x][(int)m.y] = Marker.O; clicked.GetComponent <SpriteRenderer> ( ).sprite = Resources.Load <Sprite> (ResourcePath.o); if (board.CheckForWinner(boardState, Marker.O)) { GameWinner = "You won!"; WinningCoordinates = board.WinningCoordinates; IsGameover = true; } if (board.CheckForDraw(boardState)) { GameWinner = "A draw - better than losing."; WinningCoordinates = null; IsGameover = true; } p2_O.IsTurnActive = false; p1_X.IsTurnActive = true; } } } else { Debug.Log("GAMEOVER"); } }