/// <summary> /// get candidate moves - /// this list is comprehensive - it will contain all empty cells on the board /// and sorted - good moves come first /// the list returned may be longer than the valid cells /// but then will have a null location at the end /// Actual length is (BoardSize ^ 2) - number of moves already played /// </summary> /// <param name="board">the board to read</param> /// <param name="lookaheadDepth">the current depth of lookahead</param> /// <returns>the locations</returns> public IEnumerable<Location> CandidateMoves(HexBoard board, int lookaheadDepth) { // No potential good moves? return them all then if (this.goodMoves.GetCount(lookaheadDepth) == 0) { return board.EmptyCells(); } int maxListLength = (board.Size * board.Size) - this.cellsPlayedCount; // enough space for all the possible moves Location[] result = new Location[maxListLength]; int resultIndex = 0; // mask out the ones that have been used - intialised to false bool[,] maskCellSelected = new bool[board.Size, board.Size]; // good moves are found first Location[] myGoodMoves = this.goodMoves.GetGoodMoves(lookaheadDepth); // copy in the good moves foreach (Location goodMoveLoc in myGoodMoves) { if (board.GetCellAt(goodMoveLoc).IsEmpty() && (!maskCellSelected[goodMoveLoc.X, goodMoveLoc.Y])) { result[resultIndex] = goodMoveLoc; resultIndex++; maskCellSelected[goodMoveLoc.X, goodMoveLoc.Y] = true; } } // copy in all moves where the cell is empty; // and not already in by virtue of being a good move foreach (Cell testCell in board.GetCells()) { if (testCell.IsEmpty() && (!maskCellSelected[testCell.X, testCell.Y])) { result[resultIndex] = testCell.Location; resultIndex++; } } // null marker at the end if (resultIndex < maxListLength) { result[resultIndex] = Location.Null; } return result; }
/// <summary> /// // get the candidate moves /// </summary> /// <param name="board">the board to get moves from</param> /// <param name="lookaheadDepth">the lookahead depth</param> /// <returns>the candiate move locations</returns> public IEnumerable<Location> CandidateMoves(HexBoard board, int lookaheadDepth) { int maxListLength = (board.Size * board.Size) - this.cellsPlayedCount; // enough space for all the possible moves List<Location> result = new List<Location>(maxListLength); // mask out the ones that have been used - intialised to false bool[,] maskCellSelected = new bool[board.Size, board.Size]; if (lookaheadDepth < this.goodMoves.Depth) { // good moves are found first Location[] myGoodMoves = this.goodMoves.GetGoodMoves(lookaheadDepth); // copy in the good moves foreach (Location goodMoveLoc in myGoodMoves) { if (board.GetCellAt(goodMoveLoc).IsEmpty() && (!maskCellSelected[goodMoveLoc.X, goodMoveLoc.Y])) { result.Add(goodMoveLoc); maskCellSelected[goodMoveLoc.X, goodMoveLoc.Y] = true; } } } // copy in all moves where the cell is empty, // and not already in by virtue of being a good move foreach (Cell testCell in board.GetCells()) { if (testCell.IsEmpty() && (!maskCellSelected[testCell.X, testCell.Y])) { if (IsIncluded(testCell, board) || HasFilledNeighbour(testCell, board)) { result.Add(testCell.Location); } } } return result.ToArray(); }
public void GetCellsTest() { HexBoard hexBoard = new HexBoard(BoardSize); Cell[,] cells = hexBoard.GetCells(); Assert.AreEqual(cells[1, 1].IsOccupied, Occupied.Empty); Assert.AreEqual(cells[2, 2].IsOccupied, Occupied.Empty); Assert.AreEqual(cells[3, 3].IsOccupied, Occupied.Empty); hexBoard.PlayMove(1, 1, true); Assert.AreEqual(cells[1, 1].IsOccupied, Occupied.PlayerX); Assert.AreEqual(cells[2, 2].IsOccupied, Occupied.Empty); Assert.AreEqual(cells[3, 3].IsOccupied, Occupied.Empty); hexBoard.PlayMove(2, 2, false); Assert.AreEqual(cells[1, 1].IsOccupied, Occupied.PlayerX); Assert.AreEqual(cells[2, 2].IsOccupied, Occupied.PlayerY); Assert.AreEqual(cells[3, 3].IsOccupied, Occupied.Empty); }