async void PlayMove(int gc, int gr, int bc, int br, int cc, int cr, Boolean isHuman)
        {
            UIEnabled = false;
            // show last turn icon if this is the very first move
            if (lastMoveCol == -1 || lastMoveRow == -1)
            {
                LastTurnImg.Visibility = Windows.UI.Xaml.Visibility.Visible;
            }

            lastMoveState = game.PlayMove(currentPlayer, bc, br, cc, cr);

            if (game.IsMoveSuccess(lastMoveState))
            {
                // save this as the last move
                lastMoveRow = gr;
                lastMoveCol = gc;

                // stop any flash animations
                ClearFlashing();

                // display turn tip for the *next* player
                //AnimateYourTurn();
                TurnImg.Source = new BitmapImage(new Uri(this.BaseUri, currentPlayer == 1 ? oturnSrc : xturnSrc));
                Animations.PopUIElement(
                    TurnImg,
                    0,
                    1,
                    0,
                    1,
                    0.5 * turnImgWidth,
                    0,
                    0.5 * turnImgHeight,
                    0,
                    Animations.popInEasing);

                // flash viable boards for next turn
                if (game.NextBoardCol == -1)
                {
                    for (int i = 0; i < 9; i++)
                    {
                        for (int j = 0; j < 9; j++)
                        {
                            FlashCell(rects[i, j]);
                        }
                    }
                }
                else
                {
                    for (int i = 3 * cc; i < 3 * (cc + 1); i++)
                    {
                        for (int j = 3 * cr; j < 3 * (cr + 1); j++)
                        {
                            FlashCell(rects[j, i]);
                        }
                    }
                }
            }

            StatusText.Text = lastMoveState.ToString();

            if (game.IsMoveSuccess(lastMoveState))
            {
                // put an X/O
                // get original cell coords first
                FillCell(gr, gc, currentPlayer == 1 ? "X" : "O");

                if (soundEffectsEnabled)
                {
                    // play the corresponding sound effect
                    if (currentPlayer == 1)
                    {
                        wavePlayer.PlayWave("playerX");
                    }
                    else
                    {
                        wavePlayer.PlayWave("playerO");
                    }
                }
            }

            switch (lastMoveState)
            {
            case MoveState.SUCCESS_GAME_ON:

                // nothing further for now
                break;

            case MoveState.SUCCESS_BOARD_WON_GAME_ON:

                // if the winner is not AI, color the board then greet the board winner
                if (!(currentPlayer == -1 && gameMode > GameMode.TwoPlayer))
                {
                    ShowRandomGreeting();
                    ColorBoard(bc, br, (currentPlayer == 1) ? GetColor(GameColor.BoardWonX) : GetColor(GameColor.BoardWonO));
                    await Task.Delay(TimeSpan.FromSeconds(greetingDurationSec));
                }

                // color the won board
                ColorBoard(bc, br, (currentPlayer == 1) ? GetColor(GameColor.BoardWonX) : GetColor(GameColor.BoardWonO));
                break;

            case MoveState.SUCCESS_BOARD_WON_GAME_DRAW:

                // color the won board
                ColorBoard(bc, br, (currentPlayer == 1) ? GetColor(GameColor.BoardWonX) : GetColor(GameColor.BoardWonO));

                // then show the game over (draw) popup
                GameOver();
                break;

            case MoveState.SUCCESS_BOARD_WON_GAME_WON:

                // color the won board
                ColorBoard(bc, br, (currentPlayer == 1) ? GetColor(GameColor.BoardWonX) : GetColor(GameColor.BoardWonO));

                // then show the game over popup
                GameOver();
                break;

            case MoveState.SUCCESS_BOARD_DRAW_GAME_WON:

                // color the won board
                ColorBoard(bc, br, GetColor(GameColor.BoardDraw));

                // then show the game over popup
                GameOver();
                break;

            case MoveState.SUCCESS_BOARD_DRAW_GAME_LOST:

                // color the won board
                ColorBoard(bc, br, GetColor(GameColor.BoardDraw));

                // then show the game over popup
                currentPlayer = -1 * currentPlayer;
                GameOver();
                break;

            case MoveState.SUCCESS_BOARD_WON_GAME_LOST:

                // color the won board
                ColorBoard(bc, br, (currentPlayer == 1) ? GetColor(GameColor.BoardWonX) : GetColor(GameColor.BoardWonO));

                // then show the game over popup
                currentPlayer = -1 * currentPlayer;
                GameOver();
                break;

            case MoveState.SUCCESS_BOARD_DRAW_GAME_DRAW:

                ColorBoard(bc, br, GetColor(GameColor.BoardDraw));

                // then show the game over (draw) popup
                GameOver();
                break;

            case MoveState.SUCCESS_BOARD_DRAW_GAME_ON:

                // color the draw board
                ColorBoard(bc, br, GetColor(GameColor.BoardDraw));
                break;
            }

            if (game.IsSuccessAndGameON(lastMoveState))
            {
                currentPlayer *= -1;
                //System.Diagnostics.Debug.WriteLine("Current player " + currentPlayer);

                if (isHuman && gameMode > GameMode.TwoPlayer)
                {
                    int Cc, Cr;

                    // sleep pretend we're thinking
                    turnProgressBar.Visibility = Windows.UI.Xaml.Visibility.Visible;
                    // Wait for AI to finish rendering
                    await Task.Delay(TimeSpan.FromSeconds(1));

                    switch (gameMode)
                    {
                    case GameMode.AI_LVL_1:
                        GreedyAI1.Play(game, currentPlayer, ref cc, ref cr, out Cc, out Cr, 1);
                        break;

                    case GameMode.AI_LVL_2:
                        GreedyAI1.Play(game, currentPlayer, ref cc, ref cr, out Cc, out Cr, 2);
                        break;

                    case GameMode.AI_LVL_3:
                        GreedyAI1.Play(game, currentPlayer, ref cc, ref cr, out Cc, out Cr, 3);
                        break;

                    default:
                        Cc = -1;
                        Cr = -1;
                        break;
                    }
                    turnProgressBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

                    if (cc != -1)
                    {
                        PlayMove(cc * 3 + Cc, cr * 3 + Cr, cc, cr, Cc, Cr, false);
                    }
                }
            }
            UIEnabled = true;
        }
示例#2
0
        private static float PlayBestGlobalMove(int[, , ,] Cells, int player, ref int Bc, ref int Br, out int Cc, out int Cr, ref int age, int maxAge)
        {
            List <int> availableBc = new List <int>();
            List <int> availableBr = new List <int>();
            List <int> availableCc = new List <int>();
            List <int> availableCr = new List <int>();

            Cc = -1;
            Cr = -1;

            if (age > maxAge)
            {
                float wins  = 0;
                float loses = 0;
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        if (
                            Cells[i, j, 0, 0] + Cells[i, j, 0, 1] + Cells[i, j, 0, 2] == player * 3 ||
                            Cells[i, j, 1, 0] + Cells[i, j, 1, 1] + Cells[i, j, 1, 2] == player * 3 ||
                            Cells[i, j, 2, 0] + Cells[i, j, 2, 1] + Cells[i, j, 2, 2] == player * 3 ||
                            Cells[i, j, 0, 0] + Cells[i, j, 1, 0] + Cells[i, j, 2, 0] == player * 3 ||
                            Cells[i, j, 0, 1] + Cells[i, j, 1, 1] + Cells[i, j, 2, 1] == player * 3 ||
                            Cells[i, j, 0, 2] + Cells[i, j, 1, 2] + Cells[i, j, 2, 2] == player * 3 ||
                            Cells[i, j, 0, 0] + Cells[i, j, 1, 1] + Cells[i, j, 2, 2] == player * 3 ||
                            Cells[i, j, 0, 2] + Cells[i, j, 1, 1] + Cells[i, j, 2, 0] == player * 3
                            )
                        {
                            wins++;
                        }
                        else if (
                            Cells[i, j, 0, 0] + Cells[i, j, 0, 1] + Cells[i, j, 0, 2] == -1 * player * 3 ||
                            Cells[i, j, 1, 0] + Cells[i, j, 1, 1] + Cells[i, j, 1, 2] == -1 * player * 3 ||
                            Cells[i, j, 2, 0] + Cells[i, j, 2, 1] + Cells[i, j, 2, 2] == -1 * player * 3 ||
                            Cells[i, j, 0, 0] + Cells[i, j, 1, 0] + Cells[i, j, 2, 0] == -1 * player * 3 ||
                            Cells[i, j, 0, 1] + Cells[i, j, 1, 1] + Cells[i, j, 2, 1] == -1 * player * 3 ||
                            Cells[i, j, 0, 2] + Cells[i, j, 1, 2] + Cells[i, j, 2, 2] == -1 * player * 3 ||
                            Cells[i, j, 0, 0] + Cells[i, j, 1, 1] + Cells[i, j, 2, 2] == -1 * player * 3 ||
                            Cells[i, j, 0, 2] + Cells[i, j, 1, 1] + Cells[i, j, 2, 0] == -1 * player * 3
                            )
                        {
                            loses++;
                        }
                    }
                }
                return((wins - loses) / 9);
                // instead retun a franction between -1 and 1 based on finished boards
            }


            FindAvailableMoves(Cells, Bc, Br, availableBc, availableBr, availableCc, availableCr);

            if (availableBc.Count == 0)
            {
                return(0);
                // instead retun a franction between -1 and 1 based on finished boards
            }

            float bestScore = -10;
            int   bestAge   = 0;

            for (int i = 0; i < availableBc.Count; i++)
            {
                int   localAge = age;
                float score    = -10;
                //int[,,,] cells = new int[3, 3, 3, 3];
                GameEngine localEngine = new GameEngine();
                localEngine.NextPlayer = player;
                int cc, cr;
                Array.Copy(Cells, localEngine.Cells, Cells.Length);
                // do not call the next line for a less smart AI
                localEngine.recalculateBoards();
                MoveState res = localEngine.PlayMove(player, availableBc[i], availableBr[i], availableCc[i], availableCr[i]);
                localAge++;

                if (res == MoveState.SUCCESS_BOARD_WON_GAME_WON || res == MoveState.SUCCESS_BOARD_DRAW_GAME_WON)
                {
                    score = 1;
                }
                else if (res == MoveState.SUCCESS_BOARD_WON_GAME_LOST || res == MoveState.SUCCESS_BOARD_DRAW_GAME_LOST)
                {
                    score = -1;
                }
                else if (!localEngine.IsMoveSuccess(res))
                {
                    break;
                }
                else
                {
                    score = -1 * PlayBestGlobalMove(localEngine.Cells, -1 * player, ref localEngine.NextBoardCol, ref localEngine.NextBoardRow, out cc, out cr, ref localAge, maxAge);
                }

                if (score > bestScore || (bestScore != 1 && score == bestScore && localAge >= bestAge) || (bestScore == 1 && score == bestScore && localAge <= bestAge))
                {
                    if (localAge == bestAge && score == bestScore)
                    {
                        if (new Random().Next() % 2 == 0)
                        {
                            bestScore = score;
                            Bc        = availableBc[i];
                            Br        = availableBr[i];
                            Cc        = availableCc[i];
                            Cr        = availableCr[i];
                            bestAge   = localAge;
                        }
                    }
                    else
                    {
                        bestScore = score;
                        Bc        = availableBc[i];
                        Br        = availableBr[i];
                        Cc        = availableCc[i];
                        Cr        = availableCr[i];
                        bestAge   = localAge;
                    }
                }
            }

            age = bestAge;
            return(bestScore);
        }