Ejemplo n.º 1
0
        public int[] PlaceShipsRandomly()
        {
            int cellCount = rules.areaSize.x * rules.areaSize.y;
            var cells     = new int[cellCount];

            for (var i = 0; i < cellCount; i++)
            {
                cells[i] = EmptyCell;
            }
            foreach (var kvp in _pool)
            {
                var from = new List <int>();
                for (var i = 0; i < cellCount; i++)
                {
                    from.Add(i);
                }
                var isPlaced = false;
                while (!isPlaced)
                {
                    if (from.Count == 0)
                    {
                        break;
                    }
                    int cell = from[Random.Range(0, from.Count)];
                    from.Remove(cell);
                    isPlaced = PlaceShip(kvp.Key, kvp.Value, GridUtils.CellIndexToCoordinate(cell, rules.areaSize.x));
                }
            }

            return(cells);

            bool PlaceShip(int shipId, Ship ship, Vector3Int pivot)
            {
                (int shipWidth, int shipHeight) = ship.GetShipSize();
                if (!GridUtils.IsInsideBoundaries(shipWidth, shipHeight, pivot, rules.areaSize))
                {
                    return(false);
                }
                if (DoesCollideWithOtherShip(shipId, pivot, shipWidth, shipHeight))
                {
                    return(false);
                }
                RegisterShipToCells(shipId, ship, pivot);
                return(true);
            }

            bool DoesCollideWithOtherShip(int shipId, Vector3Int pivot, int shipWidth, int shipHeight)
            {
                // Create a frame of one cell thickness
                int xMin = pivot.x - 1;
                int xMax = pivot.x + shipWidth;
                int yMin = pivot.y - shipHeight;
                int yMax = pivot.y + 1;

                for (int y = yMin; y <= yMax; y++)
                {
                    if (y < 0 || y > rules.areaSize.y - 1)
                    {
                        continue;                                    // Avoid this row if it is out of the map
                    }
                    for (int x = xMin; x <= xMax; x++)
                    {
                        if (x < 0 || x > rules.areaSize.x - 1)
                        {
                            continue;                                    // Avoid this column if it is out of the map
                        }
                        int cellIndex = GridUtils.CoordinateToCellIndex(new Vector3Int(x, y, 0), rules.areaSize);
                        if (cellIndex != OutOfMap &&
                            (cells[cellIndex] == EmptyCell || cells[cellIndex] == shipId))
                        {
                            continue;
                        }

                        return(true);
                    }
                }

                return(false);
            }

            void RegisterShipToCells(int shipId, Ship ship, Vector3Int pivot)
            {
                // Clear the previous placement of this ship
                for (var i = 0; i < cellCount; i++)
                {
                    if (cells[i] == shipId)
                    {
                        cells[i] = EmptyCell;
                    }
                }

                // Find each cell the ship covers and register the ship on them
                foreach (int cellIndex in ship.partCoordinates
                         .Select(part => new Vector3Int(pivot.x + part.x, pivot.y + part.y, 0))
                         .Select(coordinate => GridUtils.CoordinateToCellIndex(coordinate, rules.areaSize)))
                {
                    if (cellIndex != OutOfMap)
                    {
                        cells[cellIndex] = shipId;
                    }
                }
            }
        }