/** constructors **/

        /**
         * @param height,width : the board size nxm
         */
        public JokerGame(int height, int width, JokerPlayer p1, JokerPlayer p2)
        {
            turn                 = 0;
            this.p1              = p1;
            this.p2              = p2;
            this.height          = height;
            this.width           = width;
            this.moves           = new LinkedList <JokerMove>();
            this.seenBoardStates = new HashSet <String>();


            board = new char[height, width];
            for (int i = 0; i < height; i++)
            {
                // The following means: Arrays.fill(board[i], '*');
                for (var j = 0; j < width; j++)
                {
                    board[i, j] = '*';
                }
            }

            // There was a to-do item here: "remove hardcode"
            //this.p1 = new Human('W');
            //this.p2 = new RandomPlayer('B');
        }
        public void playGame()
        {
            JokerPlayer winningPlayer = null;


            while (winningPlayer == null)
            {
                if ((turn & 1) == 0)
                {
                    winningPlayer = takeTurn(p1, p2);
                }
                else
                {
                    winningPlayer = takeTurn(p2, p1);
                }
            }

            String winningMessage = "";

            if (winningPlayer.getColor() == 'W')
            {
                winningMessage = "White wins!";
            }

            else
            {
                winningMessage = "Black wins!";
            }
        }
        private JokerPlayer takeTurn(JokerPlayer activePlayer, JokerPlayer opposingPlayer)
        {
            activePlayer.planMove(this);
            activePlayer.gain(1);


            if (makeCaptures(activePlayer, opposingPlayer))
            {
                return(activePlayer);
            }

            if (makeCaptures(opposingPlayer, activePlayer))
            {
                return(opposingPlayer);
            }

            return(null);
        }
        private bool makeCaptures(JokerPlayer capturingPlayer, JokerPlayer gettingCapturedPlayer)
        {
            LinkedList <JokerPoint> toRemove = Rules.findCaptured(capturingPlayer.getColor(), gettingCapturedPlayer.getColor(), board, height);

            if (toRemove.isEmpty())
            {
                return(false);
            }

            while (!toRemove.isEmpty())
            {
                JokerPoint tmp = toRemove.First.Value;
                toRemove.RemoveFirst();

                board[tmp.x, tmp.y] = '*';
            }

            return(true);
        }