public void run()
        {
            startTime = DateTime.Now.Ticks; // 1 "Tick" = 100 nanoseconds
            GameState gs = new GameState(5, new Coordinate(3, 2));
            search(gs, new Stack<Move>());
            endTime = DateTime.Now.Ticks;

            Console.WriteLine(String.Format("Games played:    {0,6:d}", gamesPlayed));
            Console.WriteLine(String.Format("Solutions found: {0,6:d}", solutions.Count));
            Console.WriteLine(String.Format("Time elapsed:    {0,6:d}ms", (endTime - startTime) / 10000));
        }
        private void search(GameState gs, Stack<Move> moveStack)
        {
            if (gs.PegsRemaining() == 1)
            {
                //            System.out.println("Found a winning sequence. Final state:");
                //            System.out.println(gs);

                solutions.Add(new List<Move>(moveStack));

                gamesPlayed++;

                return;
            }

            List<Move> legalMoves = gs.LegalMoves();

            if (legalMoves.Count == 0)
            {
                gamesPlayed++;
                return;
            }

            foreach (Move m in legalMoves)
            {
                GameState nextState = gs.Apply(m);
                moveStack.Push(m);
                search(nextState, moveStack);
                moveStack.Pop();
            }
        }
 /// <summary>
 /// Creates a new game state by applying the given move to the given starting
 /// state. Verifies the move's validity, throwing an exception if the move is
 /// illegal.
 /// </summary>
 /// <param name="initialState"></param>
 /// <param name="applyMe"></param>
 private GameState(GameState initialState, Move applyMe)
 {
     rowCount = initialState.rowCount;
     occupiedHoles = new List<Coordinate>(initialState.occupiedHoles);
     if (!occupiedHoles.Remove(applyMe.GetFrom()))
     {
         throw new ArgumentException(
                 "Move is not consistent with game state: 'from' hole was unoccupied.");
     }
     if (!occupiedHoles.Remove(applyMe.GetJumped()))
     {
         throw new ArgumentException(
                 "Move is not consistent with game state: jumped hole was unoccupied.");
     }
     if (occupiedHoles.Contains(applyMe.GetTo()))
     {
         throw new ArgumentException(
                 "Move is not consistent with game state: 'to' hole was occupied.");
     }
     if (applyMe.GetTo().GetRow() > rowCount || applyMe.GetTo().GetRow() < 1)
     {
         throw new ArgumentException(
                 "Move is not legal because the 'to' hole does not exist: " + applyMe.GetTo());
     }
     occupiedHoles.Add(applyMe.GetTo());
 }