コード例 #1
0
ファイル: HexGameTest.cs プロジェクト: AnthonySteele/Hex
        public void TestPathLength1()
        {
            HexGame hexGame = new HexGame(7);
            Assert.IsTrue(hexGame.HasWon() == Occupied.Empty);

            int xPathLength = hexGame.PlayerScore(true);
            int yPathLength = hexGame.PlayerScore(false);

            // clean the path, get cells on the path
            List<Location> xPath = hexGame.GetCleanPath(true);
            List<Location> yPath = hexGame.GetCleanPath(false);

            Assert.AreEqual(xPath.Count, yPath.Count);
            Assert.AreEqual(xPath.Count, hexGame.Board.Size * hexGame.Board.Size);

            Assert.AreEqual(xPathLength, yPathLength);

            for (int x = 0; x < hexGame.Board.Size; x++)
            {
                for (int y = 0; y < hexGame.Board.Size; y++)
                {
                    Location loc = new Location(x, y);

                    Assert.IsTrue(xPath.Contains(loc));
                    Assert.IsTrue(yPath.Contains(loc));
                }
            }
        }
コード例 #2
0
ファイル: LocationTest.cs プロジェクト: AnthonySteele/Hex
        public void EquivalentCellsHaveSameHashCodes()
        {
            Location loc1 = new Location(2, 1);
            Location loc2 = new Location(2, 1);

            Assert.AreEqual(loc1.GetHashCode(), loc2.GetHashCode());
        }
コード例 #3
0
ファイル: LocationTest.cs プロジェクト: AnthonySteele/Hex
        public void EqualityTest()
        {
            Location loc1 = new Location(2, 3);
            Location loc2 = new Location(3, 2);
            Location loc1Dup = new Location(2, 3);

            Assert.AreNotEqual(loc1, loc2);

            Assert.AreEqual(loc1, loc1);
            Assert.AreEqual(loc2, loc2);
            Assert.AreEqual(loc1, loc1Dup);

            Assert.IsTrue(loc1 == loc1Dup);
            Assert.IsFalse(loc1 == loc2);

            Assert.IsTrue(loc1.Equals(loc1));
            Assert.IsTrue(loc1.Equals(loc1Dup));
            Assert.IsFalse(loc1.Equals(loc2));

            Assert.IsFalse(loc1.Equals(null));
            Assert.IsFalse(loc1.Equals(3));
            Assert.IsFalse(loc1.Equals("hello"));

            Assert.IsFalse(loc1 != loc1Dup);
            Assert.IsTrue(loc1 != loc2);
        }
コード例 #4
0
ファイル: PathLengthBase.cs プロジェクト: AnthonySteele/Hex
        public bool IsOnPath(Location loc)
        {
            if (this.onPathData != null)
            {
                return this.onPathData[loc.X, loc.Y];
            }

            return true;
        }
コード例 #5
0
ファイル: HexBoard.cs プロジェクト: AnthonySteele/Hex
        public Cell[] BetweenEdge(Location loc, bool playerX)
        {
            if (playerX)
            {
                return this.playerXBetweenEdge[loc.X, loc.Y];
            }

            return this.playerYBetweenEdge[loc.X, loc.Y];
        }
コード例 #6
0
ファイル: LocationTest.cs プロジェクト: AnthonySteele/Hex
        public void CopyMakesEqualObject()
        {
            Location location = new Location(3, 4);
            Location copiedLocation = location;

            Assert.AreEqual(3, copiedLocation.X);
            Assert.AreEqual(4, copiedLocation.Y);
            Assert.AreEqual(location, copiedLocation);
        }
コード例 #7
0
        public void BetweenEdgeTest()
        {
            HexBoard hexBoard = new HexBoard(BoardSize);
            for (int x = 0; x < hexBoard.Size; x++)
            {
                for (int y = 0; y < hexBoard.Size; y++)
                {
                    Location testLoc = new Location(x, y);

                    Cell[] resultX = hexBoard.BetweenEdge(testLoc, true);

                    if (y == 1)
                    {
                        // second or second-last row
                        if (x < hexBoard.Size - 1)
                        {
                            Assert.AreEqual(2, resultX.Length, testLoc.ToString());
                        }
                    }
                    else if (y == hexBoard.Size - 2)
                    {
                        // second or second-last row
                        if (x > 0)
                        {
                            Assert.AreEqual(2, resultX.Length, testLoc.ToString());
                        }
                    }
                    else
                    {
                        Assert.AreEqual(0, resultX.Length, testLoc.ToString());
                    }

                    Cell[] resultY = hexBoard.BetweenEdge(testLoc, false);

                    if (x == 1)
                    {
                        // second or second-last row
                        if (y < hexBoard.Size - 1)
                        {
                            Assert.AreEqual(2, resultY.Length, testLoc.ToString());
                        }
                    }
                    else if (x == hexBoard.Size - 2)
                    {
                        // second or second-last row
                        if (y > 0)
                        {
                            Assert.AreEqual(2, resultY.Length, testLoc.ToString());
                        }
                    }
                    else
                    {
                        Assert.AreEqual(0, resultY.Length, testLoc.ToString());
                    }
                }
            }
        }
コード例 #8
0
ファイル: LocationTest.cs プロジェクト: AnthonySteele/Hex
        public void DifferentCellsHaveDifferentHashCodes()
        {
            Location loc1 = new Location(1, 1);
            Location loc2 = new Location(1, 2);
            Location loc3 = new Location(2, 2);

            Assert.AreNotEqual(loc1.GetHashCode(), loc2.GetHashCode());
            Assert.AreNotEqual(loc1.GetHashCode(), loc3.GetHashCode());
            Assert.AreNotEqual(loc2.GetHashCode(), loc3.GetHashCode());
        }
コード例 #9
0
        public void NeighboursNearOriginTest()
        {
            HexBoardNeighbours testBoard = new HexBoardNeighbours(10);
            Location inValue = new Location(1, 1);

            Location[][] outValue = testBoard.Neighbours2(inValue);

            Assert.IsNotNull(outValue);
            Assert.AreEqual(4, outValue.Length);
            TestNeighbours(testBoard, inValue, outValue);
        }
コード例 #10
0
        public void NeighboursMiddleTest()
        {
            HexBoardNeighbours testBoard = new HexBoardNeighbours(10);
            Location inValue = new Location(5, 5);

            Location[][] outValue = testBoard.Neighbours2(inValue);

            Assert.IsNotNull(outValue);
            Assert.AreEqual(6, outValue.Length);
            TestNeighbours(testBoard, inValue, outValue);
        }
コード例 #11
0
        public void NeighboursFarTest()
        {
            HexBoardNeighbours testBoard = new HexBoardNeighbours(10);
            Location inValue = new Location(9, 9);

            Location[] outValue = testBoard.Neighbours(inValue);

            Assert.IsNotNull(outValue);
            Assert.AreEqual(2, outValue.Length);
            Assert.AreEqual(2, testBoard.NeighbourCount(inValue));
            TestNeighbours(testBoard, inValue, outValue);
        }
コード例 #12
0
ファイル: MinimaxTest.cs プロジェクト: AnthonySteele/Hex
        public void TestCalculateMove3PlayerX()
        {
            HexBoard board = new HexBoard(5);
            PlayFourMoves(board);

            Minimax minimax = MakeMinimaxForBoard(board);

            MinimaxResult firstPlayerResult = minimax.DoMinimax(4, true);

            Location firstPlayerExpectedMove = new Location(2, 1);
            Assert.AreEqual(firstPlayerExpectedMove, firstPlayerResult.Move, "Wrong first player location");
        }
コード例 #13
0
        public void GoodMoveAtLevel3()
        {
            HexBoard board = new HexBoard(6);
            PlayToWinInThreeMoves(board);

            Minimax minimax = MakeMinimaxForBoard(board);

            MinimaxResult bestMove = minimax.DoMinimax(3, true);
            Location win = new Location(1, 3);

            Assert.AreEqual(win, bestMove.Move, "Wrong play location");
        }
コード例 #14
0
ファイル: HexGameTest.cs プロジェクト: AnthonySteele/Hex
        public void TestPathLength2()
        {
            HexGame hexGame = new HexGame(7);
            /* player1 has played at 3, 3
               thier shortest path has narrowed to ones passing through this */
            hexGame.Play(3, 3);

            /* These points are on player X's shortest path */
            Location[] xPath = new Location[19];

            xPath[0] = new Location(0, 6);
            xPath[1] = new Location(1, 5);
            xPath[2] = new Location(1, 6);
            xPath[3] = new Location(2, 4);
            xPath[4] = new Location(2, 5);
            xPath[5] = new Location(2, 6);
            xPath[6] = new Location(3, 0);
            xPath[7] = new Location(3, 1);
            xPath[8] = new Location(3, 2);
            xPath[9] = new Location(3, 3);
            xPath[10] = new Location(3, 4);
            xPath[11] = new Location(3, 5);
            xPath[12] = new Location(3, 6);
            xPath[13] = new Location(4, 0);
            xPath[14] = new Location(4, 1);
            xPath[15] = new Location(4, 2);
            xPath[16] = new Location(5, 0);
            xPath[17] = new Location(5, 1);
            xPath[18] = new Location(6, 0);

            Assert.IsTrue(hexGame.HasWon() == Occupied.Empty);

            int xPathLength = hexGame.PlayerScore(true);
            int yPathLength = hexGame.PlayerScore(false);

            // clean the path, get cells on the path
            List<Location> xPathActual = hexGame.GetCleanPath(true);

            Assert.IsTrue(xPathLength < yPathLength);

            for (int x = 0; x < hexGame.Board.Size; x++)
            {
                for (int y = 0; y < hexGame.Board.Size; y++)
                {
                    Cell cell = hexGame.Board.GetCellAt(x, y);

                    bool xOnPath = cell.Location.IsInList(xPath);
                    bool xOnPathActual = xPathActual.Contains(cell.Location);

                    Assert.AreEqual(xOnPath, xOnPathActual, "X Path at " + cell.Location);
                }
            }
        }
コード例 #15
0
ファイル: Minimax3By3Test.cs プロジェクト: AnthonySteele/Hex
        public void TestCalculateMove2MinimaxPlayerY()
        {
            HexBoard board = new HexBoard(3);
            PlayTwoMoves(board);

            Minimax minimax = MakeMinimaxForBoard(board);
            MinimaxResult secondPlayerResult = minimax.DoMinimax(2, false);

            Location expectedPlay = new Location(0, 2);
            Assert.AreEqual(expectedPlay, secondPlayerResult.Move, "Wrong play location");
            Assert.IsFalse(MoveScoreConverter.IsWin(secondPlayerResult.Score));
        }
コード例 #16
0
        /// <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;
        }
コード例 #17
0
        public void GameLevel5Test()
        {
            HexGame game = new HexGame(6);
            SetupGame(game);

            // get next move for red
            Location expectedBestMove = new Location(2, 5);

            // level 5 failed
            // choses 0,0.
            // proably failing to pick a near win over a distant one
            // a-b cutoff failure?
            TestBestMove(game, 5, expectedBestMove);
        }
コード例 #18
0
        private static void TestBestMove(HexGame game, int level, Location expectedBestMove)
        {
            Minimax hexPlayer = new Minimax(game.Board, game.GoodMoves, new CandidateMovesAll());
            MinimaxResult bestMove = hexPlayer.DoMinimax(level, true);

            // test the location of the move
            Assert.AreEqual(expectedBestMove, bestMove.Move, "Wrong move at level " + level);

            // test the expected score
            if (level >= 3)
            {
                Assert.AreEqual(Occupied.PlayerX,  MoveScoreConverter.Winner(bestMove.Score));
            }
        }
コード例 #19
0
ファイル: HexBoardTest.cs プロジェクト: AnthonySteele/Hex
        public void ClearTest()
        {
            HexBoard hexBoard = new HexBoard(BoardSize);

            // set a cell
            hexBoard.PlayMove(1, 1, true);
            Assert.AreEqual(Occupied.PlayerX, hexBoard.GetCellOccupiedAt(1, 1));

            Location loc11 = new Location(1, 1);
            Assert.AreEqual(Occupied.PlayerX, hexBoard.GetCellOccupiedAt(1, 1));
            Assert.AreEqual(Occupied.PlayerX, hexBoard.GetCellOccupiedAt(loc11));

            // reset it
            hexBoard.Clear();
            Assert.AreEqual(Occupied.Empty, hexBoard.GetCellOccupiedAt(1, 1));
            Assert.AreEqual(Occupied.Empty, hexBoard.GetCellOccupiedAt(loc11));
        }
コード例 #20
0
ファイル: GoodMoves.cs プロジェクト: AnthonySteele/Hex
        /// <summary>
        /// Store a good move at the front of the list for the given depth
        /// Move the rest up
        /// If the good move was in the list but not that the front,
        /// bring it to the front
        /// If there are enough good moves already, one falls off the end
        /// else the count goes up
        /// </summary>
        /// <param name="moveDepth">the depth at which to add</param>
        /// <param name="insertLoc">the locaiton to add</param>
        public void AddGoodMove(int moveDepth, Location insertLoc)
        {
            if (insertLoc.IsNull())
            {
                return;
            }

            if (moveDepth >= this.Depth)
            {
                this.SetDepth(moveDepth + 1);
            }

            Location[] myDepthLocs = this.moves[moveDepth];

            Location currentLoc = insertLoc;

            bool foundInList = false;

            int max = this.count[moveDepth];
            if (max >= GoodMovesCount)
            {
                max = GoodMovesCount - 1;
            }

            for (int index = 0; index <= max; index++)
            {
                Location tempLoc = myDepthLocs[index];

                // insert and move the next move up one
                myDepthLocs[index] = currentLoc;
                currentLoc = tempLoc;

                // if the original inserted loc was in the list, stop moving up
                if ((index < max) && insertLoc.Equals(currentLoc))
                {
                    foundInList = true;
                    break;
                }
            }

            // has the stored move count increased?
            if ((!foundInList) && (this.count[moveDepth] < GoodMovesCount))
            {
                this.count[moveDepth]++;
            }
        }
コード例 #21
0
        public bool AreNeighbours(Location location1, Location location2)
        {
            if (!this.IsOnBoard(location1) || !this.IsOnBoard(location2))
            {
                return false;
            }

            int xDif = location1.X - location2.X;
            int yDif = location1.Y - location2.Y;

            // too far away
            if (Math.Abs(xDif) > 1)
            {
                return false;
            }

            if (Math.Abs(yDif) > 1)
            {
                return false;
            }

            // 9 cells have a diff of 1 or less (3 *3 square)
            // two of these are not hex-neighbours, and one is the same cell
            // the other three are neighbours

            // same cell
            if ((xDif == 0) && (yDif == 0))
            {
                return false;
            }

            // not neighbours
            if ((xDif == 1) && (yDif == 1))
            {
                return false;
            }

            if ((xDif == -1) && (yDif == -1))
            {
                return false;
            }

            return true;
        }
コード例 #22
0
ファイル: GoodMovesTests.cs プロジェクト: AnthonySteele/Hex
        public void TestDataMove()
        {
            for (int i = 0; i < 10; i++)
            {
                var insertLoc = new Location(i, i);
                this.goodMoves.AddGoodMove(0, insertLoc);

                Location[] insertOutMoves = this.goodMoves.GetGoodMoves(0);

                // length should be the same as the number inserted
                Assert.IsTrue(this.goodMoves.GetCount(0) == (i + 1), "Failed count at " + i);
                Assert.IsTrue(insertOutMoves.Length == (i + 1));

                // new element at the start
                Assert.IsTrue(insertLoc.Equals(insertOutMoves[0]));

                // first element at the end
                Assert.IsTrue(insertOutMoves[i].Equals(0, 0));
            }

            Location[] outMoves = this.goodMoves.GetGoodMoves(0);
            Assert.IsTrue(outMoves.Length == 10);
            Assert.IsTrue(outMoves[0].Equals(9, 9));

            // bring to front
            this.goodMoves.AddGoodMove(0, new Location(5, 5));

            outMoves = this.goodMoves.GetGoodMoves(0);
            Assert.IsTrue(outMoves.Length == 10);
            Assert.IsTrue(outMoves[0].Equals(5, 5));

            // bring various to front, test all are still present
            for (int i = 9; i >= 0; i--)
            {
                this.goodMoves.AddGoodMove(0, new Location(i, i));
                outMoves = this.goodMoves.GetGoodMoves(0);

                Assert.IsTrue(outMoves.Length == 10);
                Assert.IsTrue(outMoves[0].Equals(i, i));

                IsAllPresentOnce(outMoves);
            }
        }
コード例 #23
0
ファイル: MinimaxTest.cs プロジェクト: AnthonySteele/Hex
        public void TestCalculateMove3PlayerY()
        {
            HexBoard board = new HexBoard(5);
            PlayFourMoves(board);

            Minimax minimax = MakeMinimaxForBoard(board);

            // test score at this point
            PathLengthLoop pathLength = new PathLengthLoop(board);
            int playerScore = pathLength.PlayerScore(true);
            Assert.AreEqual(3, playerScore);

            playerScore = pathLength.PlayerScore(false);
            Assert.AreEqual(3, playerScore);

            MinimaxResult secondPlayerResult = minimax.DoMinimax(4, false);

            Location secondPlayerExpectedMove = new Location(1, 2);
            Assert.AreEqual(secondPlayerExpectedMove, secondPlayerResult.Move, "Wrong second player location");
        }
コード例 #24
0
        public void GameIterateTest()
        {
            HexGame game = new HexGame(6);
            SetupGame(game);

            // get next move for red
            Location[] expectedBestMove = new Location[7];

            expectedBestMove[1] = new Location(2, 5);
            expectedBestMove[2] = new Location(2, 5);
            expectedBestMove[3] = new Location(2, 5);
            expectedBestMove[4] = new Location(2, 5);
            expectedBestMove[5] = new Location(2, 5);
            expectedBestMove[6] = new Location(2, 5);

            // test levels 1-6
            for (int level = 1; level < 7; level++)
            {
                TestBestMove(game, level, expectedBestMove[level]);
            }
        }
コード例 #25
0
        public void NeighboursOffTest()
        {
            HexBoardNeighbours testBoard = new HexBoardNeighbours(5);
            Location inValue = new Location(5, 0);

            Location[][] outValue = testBoard.Neighbours2(inValue);

            Assert.IsNotNull(outValue);
            Assert.AreEqual(0, outValue.Length);
        }
コード例 #26
0
        private static void TestOnBoard(HexBoardNeighbours testBoard, Location neighbour)
        {
            Assert.IsTrue(testBoard.IsOnBoard(neighbour));

            Assert.GreaterOrEqual(neighbour.X, 0);
            Assert.GreaterOrEqual(neighbour.Y, 0);

            Assert.Less(neighbour.X, testBoard.BoardSize);
            Assert.Less(neighbour.Y, testBoard.BoardSize);
        }
コード例 #27
0
        private static void TestNeighbours(HexBoardNeighbours testBoard, Location testLoc, IEnumerable<Location[]> neighbourGroups)
        {
            TestOnBoard(testBoard, testLoc);

            foreach (Location[] neighbours in neighbourGroups)
            {
                Location neighbour2 = neighbours[0];
                Location between1 = neighbours[1];
                Location between2 = neighbours[2];

                TestOnBoard(testBoard, neighbour2);
                TestOnBoard(testBoard, between1);
                TestOnBoard(testBoard, between2);

                // that the betweens are neighbours of start, end eand each other
                Assert.IsTrue(testBoard.AreNeighbours(between1, between2));

                Assert.IsTrue(testBoard.AreNeighbours(testLoc, between1));
                Assert.IsTrue(testBoard.AreNeighbours(testLoc, between2));

                Assert.IsTrue(testBoard.AreNeighbours(neighbour2, between1));
                Assert.IsTrue(testBoard.AreNeighbours(neighbour2, between2));

                // but not neighbours of each other
                Assert.IsFalse(testBoard.AreNeighbours(testLoc, neighbour2));
            }
        }
コード例 #28
0
ファイル: RandomFirstMove.cs プロジェクト: AnthonySteele/Hex
        private Location RandomMiddle()
        {
            int midPoint = (this.BoardSize / 2) - 1;
            Location midLocation = new Location(midPoint, midPoint);
            if ((this.BoardSize > 6) && this.RandomBool())
            {
                return this.RandomNeighbour(midLocation);
            }

            return midLocation;
        }
コード例 #29
0
ファイル: RandomFirstMove.cs プロジェクト: AnthonySteele/Hex
 private Location RandomElement(Location[] locations)
 {
     int max = locations.Length;
     int selection = this.randomNumbers.Next(max);
     return locations[selection];
 }
コード例 #30
0
ファイル: RandomFirstMove.cs プロジェクト: AnthonySteele/Hex
        private Location RandomNeighbour(Location loc)
        {
            HexBoardNeighbours neighbourFinder = new HexBoardNeighbours(this.BoardSize);
            Location[] neighbours = neighbourFinder.Neighbours(loc);

            return this.RandomElement(neighbours);
        }