public virtual BoardStatus? CheckForWinner(IBoardCells boardCells)
        {
            foreach (var combination in _winningCombinations)
            {
                var firstCell = boardCells.GetCell(combination[0]);

                //if one cell of the combination is empty, it can't be part of a winning combination - move on
                if (firstCell == PieceType.Neither) continue;

                //if all three cells have the same non-empty value, we have a winner
                if (
                        boardCells.GetCell(combination[1]) == firstCell
                            &&
                        boardCells.GetCell(combination[2]) == firstCell
                    )
                {
                    return firstCell == PieceType.Nought
                        ? BoardStatus.NoughtsWins
                        : BoardStatus.CrossesWins;
                }

            }

            //no winning combination found
            return null;
        }
예제 #2
0
        public virtual BoardStatus?CheckForWinner(IBoardCells boardCells)
        {
            foreach (var combination in _winningCombinations)
            {
                var firstCell = boardCells.GetCell(combination[0]);

                //if one cell of the combination is empty, it can't be part of a winning combination - move on
                if (firstCell == PieceType.Neither)
                {
                    continue;
                }

                //if all three cells have the same non-empty value, we have a winner
                if (
                    boardCells.GetCell(combination[1]) == firstCell
                    &&
                    boardCells.GetCell(combination[2]) == firstCell
                    )
                {
                    return(firstCell == PieceType.Nought
                        ? BoardStatus.NoughtsWins
                        : BoardStatus.CrossesWins);
                }
            }

            //no winning combination found
            return(null);
        }
예제 #3
0
        public Board(IBoardCells boardCells, IBoardWinningRules boardWinningRules, IBoardRenderer boardRenderer)
        {
            _boardCells        = boardCells;
            _boardRenderer     = boardRenderer;
            _boardWinningRules = boardWinningRules;

            _random    = new Random(DateTime.Now.Millisecond); //seed is current time's milliseconds, which is a simple way to get a random number
            _boardSize = _boardCells.Size();
        }
예제 #4
0
        public Board(IBoardCells boardCells, IBoardWinningRules boardWinningRules, IBoardRenderer boardRenderer)
        {
            _boardCells = boardCells;
            _boardRenderer = boardRenderer;
            _boardWinningRules = boardWinningRules;

            _random = new Random(DateTime.Now.Millisecond); //seed is current time's milliseconds, which is a simple way to get a random number
            _boardSize = _boardCells.Size();
        }
예제 #5
0
        public BoardCells(IBoardCells boardCells)
        {
            if (boardCells == null) { throw new ArgumentNullException(nameof(boardCells)); }

            Board = boardCells.Board;
            Rows = boardCells.Rows;
            Columns = boardCells.Columns;
            Squares = boardCells.Squares;

            BoardCells other = (BoardCells)boardCells;
            if(other != null) {
                _squaresData = other._squaresData;
            }
        }
예제 #6
0
        public MoveResult(IBoardCells board, List<IMove> movesPlayed, List<Cell> cellMoves)
            : this(board,movesPlayed, (List<IMove>)null)
        {
            MovesRemaining = new List<IMove>();

            if(cellMoves != null) {
                foreach(var cell in cellMoves) {
                    if (cell.Moves != null) {
                        foreach (var move in cell.Moves) {
                            MovesRemaining.Add(move);
                        }
                    }
                }
            }
        }
        public string RenderAsText(IBoardCells boardCells)
        {
            Func <int, char> cell = x => _renderLookup[boardCells.GetCell(x)];

            return(string.Format(
                       " {0} | {1} | {2} \n" +
                       "-----------\n" +
                       " {3} | {4} | {5} \n" +
                       "-----------\n" +
                       " {6} | {7} | {8} \n",
                       cell(0), cell(1), cell(2),
                       cell(3), cell(4), cell(5),
                       cell(6), cell(7), cell(8)
                       ));
        }
        public string RenderAsText(IBoardCells boardCells)
        {
            Func<int, char> cell = x => _renderLookup[boardCells.GetCell(x)];

            return string.Format(
                " {0} | {1} | {2} \n" +
                "-----------\n" +
                " {3} | {4} | {5} \n" +
                "-----------\n" +
                " {6} | {7} | {8} \n",
                cell(0), cell(1), cell(2),
                cell(3), cell(4), cell(5),
                cell(6), cell(7), cell(8)
            );
        }
예제 #9
0
        public List<Cell> FindMoves(IBoardCells boardCells)
        {
            if (boardCells.Board.MovesRemaining == null) {

                var moves = new List<Cell>();
                // visit each cell and get available moves
                for (int row = 0; row < boardCells.Board.Size; row++) {
                    for (int col = 0; col < boardCells.Board.Size; col++) {
                        var cellMoves = GetMovesForCell(boardCells, row, col);
                        if (cellMoves.Moves.Count > 0) {
                            moves.Add(cellMoves);
                        }
                    }
                }

                boardCells.Board.MovesRemaining = moves;
            }

            return boardCells.Board.MovesRemaining;
        }
예제 #10
0
        public override IScore GetColScore(IBoardCells board, int col)
        {
            int numMoves = 0;
            int numEmptyCells = 0;
            for (int row = 0; row < board.Board.Size; row++) {
                var cell = MoveFinder.GetMovesForCell(board, row, col);

                if (cell.Moves != null) {
                    numMoves += cell.Moves.Count;
                }

                if (board.Board[row, col] == 0) {
                    numEmptyCells++;
                }
            }

            if (numEmptyCells == 0) {
                return Score.SolvedRegionScore;
            }

            return new MultiPartScore(new double[] { -numMoves, numEmptyCells });
        }
예제 #11
0
        public override IScore GetRowScore(IBoardCells board, int row)
        {
            // row score = #-1*empty cells.#total moves in row gd
            int numMoves = 0;
            int numEmptyCells = 0;
            for (int col = 0; col < board.Board.Size; col++) {
                var cell = MoveFinder.GetMovesForCell(board, row, col);

                if (cell.Moves != null && cell.Moves.Count > 0) {
                    numMoves += cell.Moves.Count;
                }

                if (board.Board[row, col] == 0) {
                    numEmptyCells++;
                }
            }

            if (numEmptyCells == 0) {
                return Score.SolvedRegionScore;
            }

            return new MultiPartScore(new double[] { -numMoves, numEmptyCells });
        }
예제 #12
0
        public Cell GetMovesForCell(IBoardCells boardCells, int row, int col)
        {
            List<IMove> moves = new List<IMove>();

            if (boardCells.Board[row, col] == 0) {
                int[] availableNumbers = new int[boardCells.Board.Size];
                for (int i = 0; i < boardCells.Board.Size; i++) {
                    availableNumbers[i] = i + 1;
                }

                foreach (int num in boardCells.GetRowForCell(row, col)) {
                    if (num == 0) { continue; }
                    availableNumbers[num - 1] = 0;
                }

                foreach (int num in boardCells.GetColumnForCell(row, col)) {
                    if (num == 0) { continue; }
                    availableNumbers[num - 1] = 0;
                }

                foreach (int num in boardCells.GetSquareForCell(row, col)) {
                    if (num == 0) { continue; }
                    availableNumbers[num - 1] = 0;
                }

                foreach (int num in availableNumbers) {
                    if (num == 0) { continue; }
                    moves.Add(new Move(boardCells.Board, row, col, num));
                }

                // if there is only one move for a cell then it's forced
                if (moves.Count == 1) {
                    moves[0].IsForcedMove = true;
                }
            }
            return new Cell(row, col, moves);
        }
예제 #13
0
 public MoveResult(IBoardCells board, List<IMove> movesPlayed, List<IMove> movesRemaining)
 {
     CurrentBoard = board;
     MovesPlayed = movesPlayed;
     MovesRemaining = movesRemaining;
 }
예제 #14
0
        /// <summary>
        /// Will play all forced moves. The result returned will be the resulting
        /// board and an unsorted move list which does not have any forced moves.
        /// </summary>
        protected MoveResult PlayForcedMoves(IBoardCells board, List<IMove> moves,IList<IMove>previousMovesPlayed)
        {
            IBoard playboard = board.Board;
            List<IMove> movesPlayed = new List<IMove>();
            if(previousMovesPlayed != null) {
                movesPlayed.AddRange(previousMovesPlayed);
            }
            List<IMove> forcedMoves = GetForcedMoves(moves);
            IBoardCells playboardCells = new BoardCells(playboard);

            List<Cell> movesRemaining = null;
            do {
                foreach (var move in forcedMoves) {
                    playboard = new Board(playboard, move);
                    movesPlayed.Add(move);
                    _numMovesTried++;
                }

                playboardCells = new BoardCells(playboard);
                movesRemaining = MoveFinder.FindMoves(playboardCells);
                forcedMoves = GetForcedMoves(Board.GetMovesFrom(movesRemaining));
            } while (forcedMoves.Count > 0);

            if (!Board.IsValid((Board)playboard)) {
                return null;
            }

            return new MoveResult(playboardCells, movesPlayed, movesRemaining);
        }
예제 #15
0
        public override IScore GetScore(IBoardCells boardCells)
        {
            if (boardCells == null) { throw new ArgumentNullException(nameof(boardCells)); }

            if (Board.IsSolved((Board)boardCells.Board)) {
                return Score.SolvedBoardScore;
            }

            if (boardCells.BoardScore == null) {
                // for this basic implementation the score is 1/(# moves on board)
                var moves = MoveFinder.FindMoves(boardCells);
                int numMoves = 0;
                int numForcedMoves = 0;
                foreach (var cell in moves) {
                    numMoves += cell.Moves.Count;

                    foreach (var move in cell.Moves) {
                        if (move.IsForcedMove.HasValue && move.IsForcedMove.Value) {
                            numForcedMoves++;
                        }
                    }
                }

                if (numMoves == 0) {
                    // board should be solved
                    if (HasMoves(boardCells.Board)) {
                        // unsolvable board
                        return Score.InvalidBoardScore;
                    }

                    // the board is solved
                    return Score.SolvedBoardScore;
                }

                double score = -1 * numMoves;
                if (numForcedMoves > 0) {
                    score += ((double)numForcedMoves / (double)numMoves) * 0.5;
                }
                boardCells.BoardScore = new MultiPartScore(new double[1] { score });
                // return new Score(score);
                // return new Score(1.0d/(1+numMoves + (numMoves-numForcedMoves)));
            }
            else {
                var foo = "bar";
            }

            return boardCells.BoardScore;
        }
예제 #16
0
 public abstract IScore GetSquareScore(IBoardCells board, int sqRow, int sqCol);
예제 #17
0
 public abstract IScore GetScore(IBoardCells boardCells);
예제 #18
0
 public abstract IScore GetRowScore(IBoardCells board, int row);
예제 #19
0
 public abstract IScore GetColScore(IBoardCells board, int col);
예제 #20
0
        public override IScore GetSquareScore(IBoardCells board, int sqRow, int sqCol)
        {
            int numMoves = 0;
            int numEmptyCells = 0;

            int sqSize = (int)Math.Sqrt(board.Board.Size);
            int row = sqRow * sqSize;
            int col = sqCol * sqSize;

            for (int r = row; r < row + sqSize; r++) {
                for (int c = col; c < col + sqSize; c++) {
                    var cell = MoveFinder.GetMovesForCell(board, r, c);
                    if (cell.Moves != null) {
                        numMoves += cell.Moves.Count;
                    }

                    if (board.Board[r, c] == 0) {
                        numEmptyCells++;
                    }
                }
            }

            if (numEmptyCells == 0) {
                return Score.SolvedRegionScore;
            }

            return new MultiPartScore(new double[] { -numMoves, numEmptyCells });
        }