/// <summary>
        /// Determine if the placement of the specified symbol on the specified square resulted in a victory.
        /// </summary>
        /// <param name="symbol">
        /// Symbol that was just recently placed.
        /// </param>
        /// <param name="square">
        /// Square where symbol was placed
        /// </param>
        /// <param name="victorySquares">
        /// In case of victory, this out parameter will hold the set of squares that participated in this victory.
        /// </param>
        /// <returns>
        /// true if placement was determined to result in victory. false otherwise.
        /// </returns>
        private bool IsPlayerVictory(PlayerSymbol symbol, BoardSquare square, out IEnumerable <BoardSquare> victorySquares)
        {
            victorySquares = null;

            if (symbol != square.Symbol)
            {
                return(false);
            }

            var victorySet = new HashSet <BoardSquare>();

            foreach (var direction in VictoryDirections)
            {
                int numSquaresMatching = 0;

                // Find the edge of the board, in current direction from square
                int beginRow    = square.Row;
                int beginColumn = square.Column;
                while ((beginRow - direction[0] >= 0) && (beginColumn - direction[1] >= 0) &&
                       (beginRow - direction[0] < Board.Size) && (beginColumn - direction[1] < Board.Size))
                {
                    beginRow    -= direction[0];
                    beginColumn -= direction[1];
                }

                // go to the other edge of the board, looking for matching squares
                for (int row = beginRow, column = beginColumn;
                     (row >= 0) && (column >= 0) && (row < Board.Size) && (column < Board.Size);
                     row += direction[0], column += direction[1])
                {
                    if (symbol == board.GetAt(row, column).Symbol)
                    {
                        ++numSquaresMatching;
                    }
                }

                // A full board length of matching squares is required for victory
                if (numSquaresMatching < Board.Size)
                {
                    continue;
                }

                // Add the squares as victory squares, but keep iterating because there might be victory squares in other directions
                for (int row = beginRow, column = beginColumn;
                     (row >= 0) && (column >= 0) && (row < Board.Size) && (column < Board.Size);
                     row += direction[0], column += direction[1])
                {
                    victorySet.Add(board.GetAt(row, column));
                }
            }

            // If victory set is non-empty, then there was victory in at least one direction
            if (0 == victorySet.Count)
            {
                return(false);
            }

            victorySquares = victorySet;
            return(true);
        }
        /// <summary>
        /// Attempt to place specified symbol in specified board square.
        /// </summary>
        /// <param name="symbol">
        /// Symbol to be placed.
        /// </param>
        /// <param name="square">
        /// Square where placement will be attempted.
        /// </param>
        /// <returns>
        /// PlacementStatus indicating whether the move attempted was valid or invalid.
        /// </returns>
        public PlacingStatus PlaceSymbol(PlayerSymbol symbol, BoardSquare square)
        {
            if (null == square)
            {
                throw new ArgumentException(
                          Properties.Resources.InvalidPlacingSquare, "square");
            }

            // If game has already ended, let player know
            if (this.hasEnded)
            {
                return(PlacingStatus.GameEnded);
            }

            // If square is already occupied, let player know
            if (PlayerSymbol.None != square.Symbol)
            {
                return(PlacingStatus.SquareOccupied);
            }

            // If it's currently not the turn of the player that spoke, let them know
            if (currentSymbol != symbol)
            {
                return(PlacingStatus.OutOfTurn);
            }

            // Move was valid, so place symbol in square
            square.Symbol = symbol;

            // Check if player has won
            IEnumerable <BoardSquare> victorySquares;

            if (IsPlayerVictory(symbol, square, out victorySquares))
            {
                foreach (BoardSquare victorySquare in victorySquares)
                {
                    victorySquare.IsHighlighted = true;
                }

                this.hasEnded = true;
                return(PlacingStatus.Victory);
            }

            if (this.board.IsFull())
            {
                this.hasEnded = true;
                return(PlacingStatus.Draw);
            }

            // If player did not win, it's the other player's turn
            this.currentSymbol = this.currentSymbol.Opponent();

            return(PlacingStatus.Valid);
        }
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Board"/> class.
        /// </summary>
        public Board()
        {
            boardSquares = new BoardSquare[BoardSize][];
            for (int row = 0; row < BoardSize; ++row)
            {
                boardSquares[row] = new BoardSquare[BoardSize];

                for (int column = 0; column < BoardSize; ++column)
                {
                    boardSquares[row][column] = new BoardSquare(row, column);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Try to place symbol in specified board square and update game logic state and
        /// status display accordingly.
        /// </summary>
        /// <param name="symbol">
        /// PlayerSymbol to try to place in board square.
        /// </param>
        /// <param name="square">
        /// BoardSquare where symbol should be placed, if possible.
        /// </param>
        private void UpdateGameState(PlayerSymbol symbol, BoardSquare square)
        {
            // If we're in cheating mode, we place symbols on board without checking any game rules.
            // We also don't check for victory when in cheating mode.
            if (!this.rulesEnabled)
            {
                square.Symbol = symbol;
                return;
            }

            // Place symbol on square according to game rules
            var status = this.gameLogic.PlaceSymbol(symbol, square);

            switch (status)
            {
            case PlacingStatus.SquareOccupied:
                UpdateStatusDisplay(Properties.Resources.OccupiedSquare);
                break;

            case PlacingStatus.OutOfTurn:
                UpdateStatusDisplay(symbol.Opponent().GetTurnWarningText());
                break;

            case PlacingStatus.Valid:
                UpdateStatusDisplay(null);
                break;

            case PlacingStatus.Draw:
                UpdateStatusDisplay(Properties.Resources.GameDraw);
                ShowGameEnd();
                break;

            case PlacingStatus.Victory:
                UpdateStatusDisplay(symbol.GetWinAnnouncementText());
                ShowGameEnd();
                break;

            case PlacingStatus.GameEnded:
                this.ShowGameEnd();
                break;
            }
        }
Beispiel #5
0
        /// <summary>
        /// Find board square with specified ID.
        /// </summary>
        /// <param name="id">
        /// ID corresponding to square to be found.
        /// </param>
        /// <returns>
        /// Square that has specified Id, or null if no square was found with that ID.
        /// </returns>
        public BoardSquare Find(string id)
        {
            if (null == id)
            {
                return(null);
            }

            BoardSquare match = null;

            foreach (var row in boardSquares)
            {
                foreach (var square in row)
                {
                    if (id.Equals(square.Id))
                    {
                        match = square;
                        break;
                    }
                }
            }

            return(match);
        }