/// <summary>
        /// Performs a step in the game and notifies all associated clients using a push notification.
        /// </summary>
        /// <param name="SessionID">Identifier of the client who performed the move.</param>
        /// <param name="x">The X position of the move performed.</param>
        /// <param name="y">The Y position of the move performed.</param>
        /// <param name="playerLetter">Letter representing the player's move. Either "X" or "O".</param>
        public void GameStep(Guid SessionID, int x, int y, string player)
        {
            TicTacToeMove move = new TicTacToeMove()
            {
                X = x, Y = y, Player = player
            };

            if (!ValidateTicTacToeMove(move))
            {
                return;
            }

            gameState.StepsMade++;

            // Perform the requested move
            MakeMove(move);

            // Update the game state in light of the move performed
            UpdateState(move);

            byte[] bytes = GetBytes <TicTacToeMove>(move);

            // Notify all the relevant clients of the move
            foreach (KeyValuePair <Guid, Subscription> sub in subscribers)
            {
                if (sub.Value.SessionID != SessionID)
                {
                    SendMessage(sub.Value.ChannelUri, bytes);
                }
            }
        }
        /// <summary>
        /// Check if a move is legal.
        /// </summary>
        /// <param name="move">Move the validate.</param>
        /// <returns>True if the move is valid and false otherwise.</returns>
        private bool ValidateTicTacToeMove(TicTacToeMove move)
        {
            if (gameState.StepsMade == 0)
            {
                if (move.Player == ConstData.XString)
                {
                    gameState.CurrentState = TicTacToeState.XPlayerTurn;
                }
                else
                {
                    gameState.CurrentState = TicTacToeState.OPlayerTurn;
                }
            }
            bool isValid = true;

            // Invalidate the move if it is illegal because of the game state
            switch (gameState.CurrentState)
            {
            case TicTacToeState.XPlayerTurn:
                if (move.Player == ConstData.OString)
                {
                    isValid = false;
                }
                break;

            case TicTacToeState.OPlayerTurn:
                if (move.Player == ConstData.XString)
                {
                    isValid = false;
                }
                break;

            case TicTacToeState.XPlayerWin:
            case TicTacToeState.OPlayerWin:
            case TicTacToeState.Tie:
                isValid = false;
                break;

            default:
                break;
            }

            // Check if the requested cell is off the board
            if (move.X < 0 || move.X > ColumnMaxSize || move.Y < 0 || move.Y > RowMaxSize)
            {
                isValid = false;
            }

            // Checks that the cell is empty
            if (gameState.Board[move.X][move.Y] != string.Empty)
            {
                isValid = false;
            }
            return(isValid);
        }
 /// <summary>
 /// Put a move on the board.
 /// </summary>
 /// <param name="move">Move to perform.</param>
 private void MakeMove(TicTacToeMove move)
 {
     gameState.Board[move.X][move.Y] = move.Player;
 }
        /// <summary>
        /// Update the state of the game in light of a move performed by one of the clients. This checks whether or
        /// not the game has ended. If the game ended determines the game result and otherwise changes the currently
        /// active player.
        /// </summary>
        /// <param name="move">The move performed by one of the clients.</param>
        private void UpdateState(TicTacToeMove move)
        {
            bool isGameOver = false;

            // In order to win this game, a player must perform at least 3 steps.
            // Therefore, if we count 5 steps for both players it means that player "X" already made 3 steps.
            if (gameState.StepsMade >= MinimumStepsToCheckVictory)
            {
                int col           = 0;
                int row           = 0;
                int leftDiagonal  = 0;
                int rightDiagonal = 0;

                // See if the player won by performing the supplied move
                for (int i = 0; i < RowMaxSize; i++)
                {
                    // Checks the move's column
                    if (gameState.Board[move.X][i] == move.Player)
                    {
                        col++;
                    }
                    // Checks the move's row
                    if (gameState.Board[i][move.Y] == move.Player)
                    {
                        row++;
                    }
                    // Checks the primary diagonal
                    if (gameState.Board[i][i] == move.Player)
                    {
                        leftDiagonal++;
                    }
                    // Checks the secondary diagonal
                    if (gameState.Board[i][2 - i] == move.Player)
                    {
                        rightDiagonal++;
                    }
                }

                // If we have a winner: change the state
                if (row == RowMaxSize || col == ColumnMaxSize ||
                    leftDiagonal == RowMaxSize || rightDiagonal == RowMaxSize)
                {
                    if (move.Player == ConstData.XString)
                    {
                        gameState.CurrentState = TicTacToeState.XPlayerWin;
                    }
                    else
                    {
                        gameState.CurrentState = TicTacToeState.OPlayerWin;
                    }
                    isGameOver = true;
                }

                // If all the board is full and no one wins then there is a tie
                if (gameState.StepsMade == TotalCellCount && !isGameOver)
                {
                    gameState.CurrentState = TicTacToeState.Tie;
                    isGameOver             = true;
                }
            }

            // If there is no winner and the board is not full, change the active player
            if (!isGameOver)
            {
                if (gameState.CurrentState == TicTacToeState.XPlayerTurn)
                {
                    gameState.CurrentState = TicTacToeState.OPlayerTurn;
                }
                else
                {
                    gameState.CurrentState = TicTacToeState.XPlayerTurn;
                }
            }
            move.GameFlow = gameState.CurrentState.ToString();
        }