Example #1
0
        // [2016.12.01]
        // [SC] place active player's tile on a board
        public void placePlayerTileOnBoard(int playerIndex)
        {
            if (!activeGameFlag)
            {
                return;
            }

            if (playerIndex != activePlayerIndex)
            {
                Cfg.log("It is not your turn!");
                return;
            }

            Player activePlayer = players[activePlayerIndex];

            // [SC] check if player can put tiles on a board
            if (!activePlayer.getCanMove())
            {
                Cfg.log("Cannot move a tile after dropping a tile!"); // [TODO]
                return;
            }

            // [SC] check if board position is selected
            if (!isSelected())
            {
                Cfg.log("Select a board position at first!"); // [TODO]
                return;
            }

            // [SC] check if player tile is selected
            if (!activePlayer.isTileSelected())
            {
                Cfg.log("Select a tile at first!"); // [TODO]
                return;
            }

            TileZeroTile tile   = activePlayer.getSelectedTile();
            int          result = putTileOnBoard(selectedRowIndex, selectedColIndex, tile, true);

            if (result != Cfg.NONE)
            {
                Cfg.log(String.Format("    Put tile {0} at position {1}-{2} for {3} points.", tile.ToString(), selectedRowIndex, selectedColIndex, result));

                // [SC] increase player's score
                activePlayer.increaseScore(result);

                // [SC] remove the tile from the player and reset player selection
                activePlayer.removeSelectedTile();

                // [SC] disable mismatching tiles
                activePlayer.disableMismatchedTiles(tile.getColorIndex(), tile.getShapeIndex());

                // [SC] prevent the player from dropping tiles in the same turn
                activePlayer.setCanDrop(false);

                // [SC] reset board selection
                resetSelected();
            }
        }
Example #2
0
        // [2016.12.01]
        // [TODO] end the game
        protected bool verifyPlayableTileCount(int tileCount, int aiPlayerCount)
        {
            int minTileCount = Cfg.START_TILE_COUNT + (aiPlayerCount + 1) * Cfg.MAX_PLAYER_TILE_COUNT;

            if (tileCount < minTileCount)
            {
                Cfg.log(String.Format("The minimum umber of playable tiles should be {0}. Using default bag size.", minTileCount));
                return(false);
            }
            return(true);
        }
Example #3
0
        ////// END: generic functions for manipulating tiles
        /////////////////////////////////////////////////////////////////

        /////////////////////////////////////////////////////////////////
        ////// START: functions for manipulating a selected tile

        private bool setSelectedTile(TileZeroTile tile)
        {
            // [TODO] make sure the tile is one of the player's tiles
            if (!tile.getPlayable())
            {
                Cfg.log(String.Format("The tile {0}{1} is not playable.", tile.getColorIndex(), tile.getShapeIndex()));
            }
            else
            {
                selectedTile = tile;
                return(true);
            }

            return(false);
        }
Example #4
0
 // [2016.12.01]
 public void endTurn(int playerIndex)
 {
     if (!activeGameFlag)
     {
         Cfg.log("No active game.");
     }
     else if (playerIndex != activePlayerIndex)
     {
         Cfg.log("Not your turn!" + playerIndex);
     }
     else
     {
         endTurnFlag = true;
     }
 }
Example #5
0
        // [2016.12.01]
        protected void startTurn()
        {
            if (!activeGameFlag)
            {
                return;
            }

            Player activePlayer = players[activePlayerIndex];

            Cfg.log(String.Format("{0}'s turn. Score: {1}. Tiles: {2}"
                                  , activePlayer.getPlayerName()
                                  , activePlayer.getPlayerScore()
                                  , activePlayer.PlayerTilesToString()));

            activePlayer.invokeAI();
            endTurn(activePlayerIndex);
        }
Example #6
0
        /////////////////////////////////////////////////////////////////
        ////// START: board cell selection

        // [2016.12.01]
        public bool setSelectedCell(int rowIndex, int colIndex, int playerIndex)
        {
            if (playerIndex >= players.Count)
            {
                Cfg.log(String.Format("Unknown player with an index {0}.", playerIndex));
            }
            else if (activePlayerIndex != playerIndex)
            {
                Cfg.log(String.Format("It is not your turn, {0}!", players[playerIndex].getPlayerName()));
            }
            else
            {
                selectedRowIndex = rowIndex;
                selectedColIndex = colIndex;
                return(true);
            }

            return(false);
        }
Example #7
0
        // [2016.12.01]
        public void endGame()
        {
            if (!activeGameFlag)
            {
                return;
            }

            Player activePlayer = players[activePlayerIndex];

            activePlayer.increaseScore(Cfg.LAST_PLAYER_REWARD);

            int           maxScore        = Cfg.NONE;
            List <Player> maxScorePlayers = new List <Player>();

            foreach (Player player in players)
            {
                int playerScore = player.getPlayerScore();
                if (maxScore == Cfg.NONE || maxScore == playerScore)
                {
                    maxScorePlayers.Add(player);
                    maxScore = playerScore;
                }
                else if (maxScore < playerScore)
                {
                    maxScorePlayers.Clear();
                    maxScorePlayers.Add(player);
                    maxScore = playerScore;
                }
            }

            if (maxScorePlayers.Count > 1)
            {
                Cfg.log("It is a draw!");
            }
            else
            {
                Cfg.log(String.Format("Player {0} won the game!", maxScorePlayers[0].getPlayerName()));
                maxScorePlayers[0].WinFlag = true;
            }

            activeGameFlag = false;
        }
Example #8
0
        // [2016.12.01]
        protected void putStartingTiles()
        {
            int startCol = virtualBoard.getColCount() / 2 - Cfg.START_TILE_COUNT / 2;
            int startRow = virtualBoard.getRowCount() / 2;

            for (int counter = 0; counter < Cfg.START_TILE_COUNT; counter++)
            {
                int          currCol = startCol + counter;
                TileZeroTile tile    = (TileZeroTile)tileBag.ElementAt(0);

                int result = putTileOnBoard(startRow, currCol, tile, false);

                // [TODO] need to terminate the game
                if (result == Cfg.NONE)
                {
                    Cfg.log("Error putting starting tiles");
                    break;
                }

                tileBag.Remove(tile);
                ++playedTileCount;
            }
        }
Example #9
0
        // [2016.12.01]
        // [SC] a function for dropping a tile
        public void dropPlayerTile(int playerIndex)
        {
            if (!activeGameFlag)
            {
                return;
            }

            if (playerIndex != activePlayerIndex)
            {
                Cfg.log("It is not your turn!");
                return;
            }

            Player activePlayer = players[activePlayerIndex];

            // [SC] check if player drop tiles
            if (!activePlayer.getCanDrop())
            {
                Cfg.log("Cannot drop a tile after putting a tile on a board!"); // [TODO]
                return;
            }

            // [SC] check if bag has tiles
            if (tileBag.Count == 0)
            {
                Cfg.log("Cannot drop a tile! The bag is empty."); // [TODO]
                return;
            }

            // [SC] check if player tile is selected
            if (!activePlayer.isTileSelected())
            {
                Cfg.log("Select a tile at first!"); // [TODO]
                return;
            }

            TileZeroTile tile = activePlayer.getSelectedTile();

            // [SC] make sure that the tile being dropped is not a replacement tile of previously dropped tile
            if (!tile.getCanDrop())
            {
                Cfg.log("Cannot drop a replacement tile!");
                return;
            }

            foreach (TileZeroTile newTile in tileBag)
            {
                // [SC] make sure that the new tile does not have the same features as the dropped tile
                if (newTile.getColorIndex() == tile.getColorIndex() && newTile.getShapeIndex() == tile.getShapeIndex())
                {
                    continue;
                }

                Cfg.log(String.Format("    Dropped tile {0}. Replaced with tile {1}.", tile.ToString(), newTile.ToString()));

                // [SC] remove the dropped tile from player's stack
                activePlayer.removeTile(tile);
                // [SC] add the dropped tile into the bag
                tileBag.Add(tile);

                // [SC] remove the new tile from the bag
                tileBag.Remove(newTile);
                // [SC] add the new tile to player's stack
                activePlayer.addTile(newTile);
                // [SC] make sure that the new tile cannot be dropped in the same turn
                newTile.setCanDrop(false);

                // [SC] shuffle the bag
                tileBag.Shuffle();

                // [SC] prevent the player from moving tiles into the board
                activePlayer.setCanMove(false);

                break;
            }
        }
 public TileZeroTile[,] getBoardCopy()
 {
     return(Cfg.createBoardCopy(tileArray));
 }
        private int isValidSequence(int rowIndex, int colIndex, int orientation, TileZeroTile[,] tileArrayP, bool showMsg)
        {
            int[] uniqueColors     = new int[Cfg.MAX_VAL_INDEX];
            int   uniqueColorCount = 0;

            int[] uniqueShapes     = new int[Cfg.MAX_VAL_INDEX];
            int   uniqueShapeCount = 0;

            int sequenceLength = 0;

            int currRow = rowIndex;
            int currCol = colIndex;

            for (int currIndex = 0; currIndex < Cfg.MAX_VAL_INDEX; currIndex++)
            {
                uniqueColors[currIndex] = Cfg.NONE;
                uniqueShapes[currIndex] = Cfg.NONE;
            }

            // [SC] start with the left-most or top-most tile in the sequence
            if (orientation == Cfg.HORIZONTAL)
            {
                while (currCol > 0 && tileArrayP[currRow, currCol - 1] != null)
                {
                    currCol--;
                }
            }
            else
            {
                while (currRow > 0 && tileArrayP[currRow - 1, currCol] != null)
                {
                    currRow--;
                }
            }

            // [SC] checking the validity of colors and shapes, and color-shape combination of the sequence
            while (currRow < rowCount && currCol < colCount)
            {
                TileZeroTile currTile = tileArrayP[currRow, currCol];

                if (currTile == null)
                {
                    break;
                }

                // [SC] checking the validity of colors
                int currColorIndex = currTile.getColorIndex();
                if (uniqueColors[currColorIndex] == Cfg.NONE)
                {
                    uniqueColors[currColorIndex] = currColorIndex;
                    uniqueColorCount++;
                }
                else if (uniqueColorCount == 1)
                {
                }
                else
                {
                    if (showMsg)
                    {
                        Cfg.log("Invalid color sequence.");
                    }
                    return(Cfg.NONE);
                }

                // [SC] checking the validity of shapes
                int currShapeIndex = currTile.getShapeIndex();
                if (uniqueShapes[currShapeIndex] == Cfg.NONE)
                {
                    uniqueShapes[currShapeIndex] = currShapeIndex;
                    uniqueShapeCount++;
                }
                else if (uniqueShapeCount == 1)
                {
                }
                else
                {
                    if (showMsg)
                    {
                        Cfg.log("Invalid shape sequence.");
                    }
                    return(Cfg.NONE);
                }

                sequenceLength++;

                if (sequenceLength > 1)
                {
                    if ((uniqueColorCount == 1 && uniqueShapeCount == 1) || // [SC] both shape and color are same
                        (uniqueColorCount > 1 && uniqueShapeCount > 1)      // both shape and color are different
                        )
                    {
                        if (showMsg)
                        {
                            Cfg.log("Invalid combination of color and shape.");
                        }
                        return(Cfg.NONE);
                    }
                }

                // [TODO] update row
                if (orientation == Cfg.HORIZONTAL)
                {
                    currCol++;
                }
                else
                {
                    currRow++;
                }
            }

            return(sequenceLength);
        }
        public int isValidMove(int rowIndex, int colIndex, TileZeroTile tile, bool validCheck, TileZeroTile[,] tileArrayP, bool showMsg)
        {
            if (tileArrayP == null)
            {
                tileArrayP = tileArray;
            }

            int horizScore = 0;
            int vertScore  = 0;

            if (rowIndex < 0 || rowIndex >= rowCount)
            {
                if (showMsg)
                {
                    Cfg.log("Invalid row index: " + rowIndex + ".");
                }
                return(Cfg.NONE);
            }

            if (colIndex < 0 || colIndex >= colCount)
            {
                if (showMsg)
                {
                    Cfg.log("Invalid column index: " + colIndex + ".");
                }
                return(Cfg.NONE);
            }

            if (hasTile(rowIndex, colIndex, tileArrayP))
            {
                if (showMsg)
                {
                    Cfg.log("The cell already has a tile.");
                }
                return(Cfg.NONE);
            }

            if (validCheck)
            {
                // [SC] check if there is any tile adjacent to the destinatio position
                if (!hasLeftTile(rowIndex, colIndex, tileArrayP) && !hasRightTile(rowIndex, colIndex, tileArrayP) &&
                    !hasBottomTile(rowIndex, colIndex, tileArrayP) && !hasTopTile(rowIndex, colIndex, tileArrayP)
                    )
                {
                    if (showMsg)
                    {
                        Cfg.log("A new tile should be placed next to the existing one.");
                    }
                    return(Cfg.NONE);
                }

                // [SC] temporarily put the tile
                tileArrayP[rowIndex, colIndex] = tile;

                // [SC] check validity of the horizontal sequence of tiles
                if (hasLeftTile(rowIndex, colIndex, tileArrayP) || hasRightTile(rowIndex, colIndex, tileArrayP))
                {
                    horizScore = isValidSequence(rowIndex, colIndex, Cfg.HORIZONTAL, tileArrayP, showMsg);
                    if (horizScore == Cfg.NONE)
                    {
                        tileArrayP[rowIndex, colIndex] = null;
                        return(Cfg.NONE);
                    }
                    else if (horizScore == Cfg.MAX_SEQ_SCORE)
                    {
                        // [SC] reward for completing a TileZero
                        horizScore = Cfg.TILEZERO_REWARD;
                    }
                }

                // [SC] check validity of the vertical sequence of tiles
                if (hasTopTile(rowIndex, colIndex, tileArrayP) || hasBottomTile(rowIndex, colIndex, tileArrayP))
                {
                    vertScore = isValidSequence(rowIndex, colIndex, Cfg.VERTICAL, tileArrayP, showMsg);
                    if (vertScore == Cfg.NONE)
                    {
                        tileArrayP[rowIndex, colIndex] = null;
                        return(Cfg.NONE);
                    }
                    else if (vertScore == Cfg.MAX_SEQ_SCORE)
                    {
                        // [SC] reward for completing a TileZero
                        vertScore = Cfg.TILEZERO_REWARD;
                    }
                }

                // [SC] remove the temporary tile
                tileArrayP[rowIndex, colIndex] = null;
            }

            return(horizScore + vertScore);
        }