public void AllocateGivenArea(BoardPoint head, BoardPoint tail, int allocationId) { var allocationArea = this.Slice((head.X, head.Y), (tail.X, tail.Y)); foreach (var c in allocationArea) { _board[c.x, c.y] = allocationId; } }
public bool IsPointInRange(BoardPoint point) { if (point.X < 0 || point.Y < 0) { return(false); } if (point.X < _boardSize && point.Y < _boardSize) { return(true); } return(false); }
public bool IsOccupied(BoardPoint point) { if (!IsPointInRange(point)) { throw new ArgumentException($"{nameof(point)} is not in range."); } var objectId = _board[point.X, point.Y]; if (objectId == null) { return(false); } return(true); }
public (int allocationId, BoardPoint head, BoardPoint tail)? AllocateRandomAvailableArea(int size, int objectId) { var rand = new Random(DateTime.UtcNow.Millisecond); Dictionary <(int x, int y), bool> scannedSoFar = new Dictionary <(int x, int y), bool>(); int maxSpotsOnBoard = (this._boardSize * this._boardSize); lock (_randomAreaAllocationLock) { //First available random area that can house as much as {size} either at X or Y axis, forward or backward //As Non-Deterministic as possible, starts the search from a random point, //axis and back-forward search direction are determined at run-tim randomly. while (scannedSoFar.Count != (maxSpotsOnBoard)) { int x = rand.Next(0, _boardSize); int y = rand.Next(0, _boardSize); if (IsPointAvailable(x, y) && !scannedSoFar.ContainsKey((x, y))) { //Prioritize vertical search? bool colFirst = GetRandomBool(rand); //Prioritize going forward first? bool forwardDirectionFirst = GetRandomBool(rand); var tail = FindRandomTail(x, y, size, colFirst, forwardDirectionFirst, 0); if (tail.HasValue)//random area found { //Allocate the area var allocationId = -(objectId); var head = new BoardPoint(x, y); AllocateGivenArea(head, tail.Value, allocationId); //Return allocation Key, head and tail return(allocationId, new BoardPoint(x, y), tail.Value); } } scannedSoFar.TryAdd((x, y), true); } } return(null); //No available place for allocation with given size }
public void Shoot(BoardPoint target) { //Validate target if (!_board.IsPointInRange(target)) { ApplyChange(new BattleShipOperationFailed(Id, "Target is out of the Board Range")); return; } if (_shotsTaken.Any(s => s.Equals(target))) { ApplyChange(new BattleShipOperationFailed(Id, "Target already Shot")); return; } if (IsHit(target)) { var shipId = _board.GetObjectIdOnBoard(target.X, target.Y); var ship = this._ships[shipId.Value]; ApplyChange(new ShipHit(Id, target, ship.Name)); if (ship.IsSunk()) { ApplyChange(new ShipSunk(Id, ship.Name)); if (HasPlayerWon()) { ApplyChange(new AllShipsSunk(Id)); } } } else { ApplyChange(new ShotMissed(Id, target)); } }
private bool IsHit(BoardPoint target) { return(_board.IsOccupied(target)); }