/// <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; }
public void BoardLayoutTest() { HexBoard hexBoard = new HexBoard(BoardSize); for (int x = 0; x < hexBoard.Size; x++) { for (int y = 0; y < hexBoard.Size; y++) { Cell cell = hexBoard.GetCellAt(x, y); Assert.IsNotNull(cell); Assert.IsTrue(cell.X == x); Assert.IsTrue(cell.Y == y); } } }
public void CopyStateFrom(HexBoard otherBoard) { if (otherBoard != null) { if (otherBoard.Size != this.Size) { throw new Exception("Board sizes do not match"); } foreach (Cell cell in this.cells) { cell.IsOccupied = otherBoard.GetCellAt(cell.Location).IsOccupied; } this.movesPlayedCount = otherBoard.MovesPlayedCount; } }
/// <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(); }
/// <summary> /// are two boards the same, ie same state in all cells /// </summary> /// <param name="otherBoard">the other board</param> /// <returns>the equality boolean</returns> public bool Equals(HexBoard otherBoard) { if (otherBoard == null) { return(false); } if (otherBoard.Size != this.Size) { return(false); } foreach (Cell cell in this.cells) { if (cell.IsOccupied != otherBoard.GetCellAt(cell.Location).IsOccupied) { return(false); } } return(true); }
/// <summary> /// are two boards the same, ie same state in all cells /// </summary> /// <param name="otherBoard">the other board</param> /// <returns>the equality boolean</returns> public bool Equals(HexBoard otherBoard) { if (otherBoard == null) { return false; } if (otherBoard.Size != this.Size) { return false; } foreach (Cell cell in this.cells) { if (cell.IsOccupied != otherBoard.GetCellAt(cell.Location).IsOccupied) { return false; } } return true; }
/// <summary> /// set self equal to the other board /// </summary> /// <param name="otherBoard">the board to copy</param> public void CopyStateFrom(HexBoard otherBoard) { if (otherBoard != null) { if (otherBoard.Size != this.Size) { throw new Exception("Board sizes do not match"); } foreach (Cell cell in this.cells) { cell.IsOccupied = otherBoard.GetCellAt(cell.Location).IsOccupied; } this.movesPlayedCount = otherBoard.MovesPlayedCount; } }
public void TestCalculateMove2SituationScoreMiddle() { HexBoard board = new HexBoard(3); PlayTwoMoves(board); // playing middle gets adavantage board.PlayMove(1, 1, true); PathLengthLoop pathLength = new PathLengthLoop(board); int moveScore = pathLength.SituationScore(); Assert.AreEqual(1, moveScore); board.GetCellAt(1, 1).IsOccupied = Occupied.PlayerY; moveScore = pathLength.SituationScore(); Assert.AreEqual(-1, moveScore); board.GetCellAt(1, 1).IsOccupied = Occupied.Empty; }
public void MoveSetsCellOccupied() { HexBoard hexBoard = new HexBoard(BoardSize); Assert.AreEqual(Occupied.Empty, hexBoard.GetCellOccupiedAt(1, 1)); hexBoard.PlayMove(1, 1, true); Assert.AreEqual(Occupied.PlayerX, hexBoard.GetCellAt(1, 1).IsOccupied); Assert.AreEqual(Occupied.PlayerX, hexBoard.GetCellOccupiedAt(1, 1)); }
public void GetCellAtArrayTwoTest() { const int SmallBoardSize = 4; HexBoard source = new HexBoard(SmallBoardSize); Location[] locs = new Location[2]; locs[0] = new Location(1, 1); locs[1] = new Location(2, 2); Cell[] result = source.GetCellAt(locs); Assert.AreEqual(2, result.Length); Assert.AreEqual(1, result[0].Location.X); Assert.AreEqual(1, result[0].Location.Y); Assert.AreEqual(2, result[1].Location.X); Assert.AreEqual(2, result[1].Location.Y); }
public void GetCellAtTest() { const int SmallBoardSize = 4; HexBoard source = new HexBoard(SmallBoardSize); for (int x = 0; x < SmallBoardSize; x++) { for (int y = 0; y < SmallBoardSize; y++) { Cell cell = source.GetCellAt(x, y); Assert.AreEqual(x, cell.X); Assert.AreEqual(y, cell.Y); } } }
public void GetCellAtArrayNullTest() { const int SmallBoardSize = 4; HexBoard source = new HexBoard(SmallBoardSize); Location[] locs = null; Cell[] result = source.GetCellAt(locs); Assert.AreEqual(0, result.Length); }
public void BoardNeighbours2Test() { HexBoard hexBoard = new HexBoard(BoardSize); for (int x = 0; x < hexBoard.Size; x++) { for (int y = 0; y < hexBoard.Size; y++) { Cell cell = hexBoard.GetCellAt(x, y); var neigbours2 = hexBoard.Neighbours2(cell); Assert.IsNotNull(neigbours2); /* all cells have at least 1 neighbours, and at most 6 */ Assert.Greater(neigbours2.GetLength(0), 0); Assert.Less(neigbours2.GetLength(0), 7); foreach (Cell[] triplet in neigbours2) { TestNeighbour2Triplet(cell, triplet); } } } }
public void TestGetEmptyNeighbours2Edge() { HexBoard hexBoard = new HexBoard(BoardSize); // get the neighbours2 with nothing in between Cell focus = hexBoard.GetCellAt(3, 0); Cell[][] neighbours2EmptyBoard = hexBoard.EmptyNeighbours2(focus); Assert.AreEqual(3, neighbours2EmptyBoard.Length); }
public void TestGetEmptyNeighbours2() { HexBoard hexBoard = new HexBoard(BoardSize); // get the neighbours2 with nothing inbetween Cell focus = hexBoard.GetCellAt(3, 3); Cell[][] neighbours2EmptyBoard = hexBoard.EmptyNeighbours2(focus); // should be six sets Assert.AreEqual(6, neighbours2EmptyBoard.Length); // playing an ajoining cell removes 2 sets hexBoard.PlayMove(3, 4, false); Cell[][] neighbours2PlayedCell = hexBoard.EmptyNeighbours2(focus); Assert.AreEqual(4, neighbours2PlayedCell.Length); }
public void BoardNeighboursTest() { HexBoard hexBoard = new HexBoard(BoardSize); for (int x = 0; x < hexBoard.Size; x++) { for (int y = 0; y < hexBoard.Size; y++) { Cell cell = hexBoard.GetCellAt(x, y); var neigbours = hexBoard.Neighbours(cell); Assert.IsNotNull(neigbours); /* all cells have at least 2 neighbours, and at most 6 */ Assert.GreaterOrEqual(neigbours.Length, 2); Assert.LessOrEqual(neigbours.Length, 6); /* cells not on the edge will have 6 neighbours */ if ((x > 0) && (y > 0) && (x < (hexBoard.Size - 1)) && (y < (hexBoard.Size - 1))) { Assert.AreEqual(neigbours.Length, 6); } NoNullsInCellArray(neigbours); foreach (Cell neibCell in neigbours) { DoTestNeighbour(cell, neibCell, hexBoard); } } } }