private BoardCoordinate? FindNextFreeSpace(CellStatus[,] workingSet, BoardCoordinate cellToStartSearch, ShipDirection direction, int shipLength) { // the free space must be a cluster of cells with 'Free' status, such that // they can be contiguous and none of the cells of the new ship lands on // a 'not available for placement' or 'ship part' field. for (var row = cellToStartSearch.Row; row < _gameConfiguration.BoardSize; row++) { for (var column = cellToStartSearch.Column; column < _gameConfiguration.BoardSize; column++) { if (workingSet[row, column] == CellStatus.Free) { if (direction == ShipDirection.Horizontal) { // first - check if there is enough room to place the ship in the current row/column if (column + shipLength > _gameConfiguration.BoardSize - 1) continue; // next, check if the entire span of the next few cells is available var spanAvailable = true; for (var c = column; c < column + shipLength; c++) { if (workingSet[row, c] != CellStatus.Free) { spanAvailable = false; break; } } if (!spanAvailable) continue; } else { if (row + shipLength > _gameConfiguration.BoardSize - 1) continue; var spanAvailable = true; for (var r = row; r < row + shipLength; r++) { if (workingSet[r, column] != CellStatus.Free) { spanAvailable = false; break; } } if (!spanAvailable) continue; } return new BoardCoordinate(row, column); } } } return null; }
private void PlaceShipOnMap(CellStatus[,] workingSet, int lengthOfNextShipToPosition, ShipDirection directionOfPositioning, BoardCoordinate position) { // first mark everything on and around cells where the ship will be as unavailable var startingCoordinateX = Math.Max(position.Column - 1, 0); var startingCoordinateY = Math.Max(position.Row - 1, 0); var endCoordinateX = directionOfPositioning == ShipDirection.Horizontal ? Math.Min(position.Column + lengthOfNextShipToPosition, _gameConfiguration.BoardSize - 1) : Math.Min(position.Column + 1, _gameConfiguration.BoardSize - 1); var endCoordinateY = directionOfPositioning == ShipDirection.Vertical ? Math.Min(position.Row + lengthOfNextShipToPosition, _gameConfiguration.BoardSize - 1) : Math.Min(position.Row + 1, _gameConfiguration.BoardSize - 1); for (var row = startingCoordinateY; row <= endCoordinateY; row++) for (var column = startingCoordinateX; column <= endCoordinateX; column++) workingSet[row, column] = CellStatus.NotAvailableForPlacement; //Debug.WriteLine(RepresentWorkingSet(workingSet)); // next mark where the ship actually is for (int i = 0; i < lengthOfNextShipToPosition; i++) { var row = directionOfPositioning == ShipDirection.Horizontal ? position.Row : Math.Min(position.Row + i, _gameConfiguration.BoardSize - 1); var column = directionOfPositioning == ShipDirection.Vertical ? position.Column : Math.Min(position.Column + i, _gameConfiguration.BoardSize - 1); workingSet[row, column] = CellStatus.ShipPart; } // finally, add the positioned ship to the collection of positioned ships var shipsPositionedSoFar = _shipPositioningParametersPerShipLevel.Count; var currentlyPositionedShipPositioningParameters = new ShipPositioningParameters { ShipCoordinate = position, ShipDirection = directionOfPositioning }; _shipPositioningParametersPerShipLevel.Add(shipsPositionedSoFar, currentlyPositionedShipPositioningParameters); //Debug.WriteLine(RepresentWorkingSet(workingSet)); }
public void Add(BoardCoordinate coordinate) { _coordinates.Add(coordinate); }
public string ValidateShape() { // Skip ships with single mast if (_coordinates.Count == 1) return null; foreach (BoardCoordinate coordinate in _coordinates) { var verticalNeighbours = new BoardCoordinate[2] { // Top new BoardCoordinate(coordinate.Row - 1, coordinate.Column), // Bottom new BoardCoordinate(coordinate.Row + 1, coordinate.Column), }; var horizontalNeighbours = new BoardCoordinate[2] { // Left side new BoardCoordinate(coordinate.Row, coordinate.Column - 1), // Right side new BoardCoordinate(coordinate.Row, coordinate.Column + 1), }; bool vertical = _coordinates.Any(c => verticalNeighbours.Contains(c)); bool horizontal = _coordinates.Any(c => horizontalNeighbours.Contains(c)); if (!vertical && !horizontal) return "Found neighbour in the corner"; if (vertical && horizontal) return "Found both vertical and horizontal neighbour"; // If there is no information wheather the group is horizontal or vertical, just check // one of the neighbours first if (_direction.HasValue == false) _direction = vertical ? ShipDirection.Vertical : ShipDirection.Horizontal; if (_direction == ShipDirection.Vertical && horizontal) return "This coordinate has horizontal neighbours, but the rest of the group is vertical"; if (_direction == ShipDirection.Horizontal && vertical) return "This coordinate has vertical neighbours, but the rest of the group is horizontal"; } return null; }
private void AddCoordinateAndNeighboursToGroup( BoardCoordinate startCoordinate, Dictionary<BoardCoordinate, int> groups, int currentGroup) { groups[startCoordinate] = currentGroup; HashSet<BoardCoordinate> possibleNeighbours = new HashSet<BoardCoordinate>(); for (int i = 0; i < 3; i++) { // Left side possibleNeighbours.Add(new BoardCoordinate(startCoordinate.Row - 1 + i, startCoordinate.Column - 1)); // Right side possibleNeighbours.Add(new BoardCoordinate(startCoordinate.Row - 1 + i, startCoordinate.Column + 1)); // Top side possibleNeighbours.Add(new BoardCoordinate(startCoordinate.Row - 1, startCoordinate.Column - 1 + i)); // Bottom side possibleNeighbours.Add(new BoardCoordinate(startCoordinate.Row + 1, startCoordinate.Column - 1 + i)); } foreach (BoardCoordinate coordinate in possibleNeighbours) { if (BoardRepresentation.Contains(coordinate) && !groups.ContainsKey(coordinate)) { AddCoordinateAndNeighboursToGroup(coordinate, groups, currentGroup); } } }