// randomly places all ships on the gameboard public List <Ship> PlaceShips() { List <Ship> tempList = new List <Ship>(); ShipPart sp; int shipLength = 0; Direction d; foreach (Ship s in this.board.Ships) { sp = new ShipPart(GetRandomLegalSquare()); shipLength = s.GetInitialShipLength(); d = (Direction)rand.Next(3); int tries = 0; // try to find a direction that fits the length of the ship // if we haven't found a direction after x tries, get a new square while (!IsLegalDirection(sp, shipLength, d) && tries < 20) { if (IsLegalDirection(sp, shipLength, d)) { break; } else { d = (Direction)rand.Next(3); tries++; if (tries == 19) { sp = new ShipPart(GetRandomLegalSquare(false)); tries = 0; } } } RemoveIllegalSquares(s.PlaceShip(sp, d)); tempList.Add(s); } return(tempList); }
// if the ai has hit a ShipPart in the previous turn, try destroying the ship it belongs to private Square TargetShip() { ShipPart sp = null; Square targetSquare = null; Boolean squareHit = false; Boolean isTargetedShip = false; Direction randomDir = ViableDirections[rand.Next(ViableDirections.Count - 1)]; // loop through all squares we have already hit foreach (Square sq in hitLog) { // check if the square is a shippart and belongs to an undestroyed ship if (sq.IsShipPart()) { sp = new ShipPart(sq); foreach (Ship ship in board.Ships) { if (!ship.isDestroyed()) { // check if that ship contains the current square if (ship.ShipParts.Any(x => x == sp)) { isTargetedShip = true; } } } if (isTargetedShip) { // analyse the next square in a direction until we find a not already hit square // the direction is chosen randomly until we find a viable direction which yields undestroyed shipparts do { // when we aren't sure where the ship actually is if (TargetDirection == Direction.NONE) { targetSquare = GetNextSquareInDirection(sp, randomDir, board.Squares); // while we haven't found a targetable square, try targeting squares in different directions while (ReferenceEquals(targetSquare, null) || (!targetSquare.IsShipPart() && targetSquare.IsHit)) { ViableDirections.Remove(randomDir); randomDir = ViableDirections[rand.Next(ViableDirections.Count - 1)]; targetSquare = GetNextSquareInDirection(sp, randomDir, board.Squares); } } // when we are sure where (at least part of) the ship is else { targetSquare = GetNextSquareInDirection(sp, TargetDirection, board.Squares); // if the targeted square isn't targetable, invert the targetdirection and pursue it if (ReferenceEquals(targetSquare, null) || (!targetSquare.IsShipPart() && targetSquare.IsHit)) { TargetDirection = InvertDirection(TargetDirection); targetSquare = GetNextSquareInDirection(sp, TargetDirection, board.Squares); } } if (targetSquare.IsShipPart()) { sp = new ShipPart(targetSquare); } }while (targetSquare.IsShipPart() && sp.Destroyed); // if we haven't yet figured out where the ship is, target the previously chosen square, which might actually be a miss if (TargetDirection == Direction.NONE) { // if it hit, set the TargetDirection to the current direction if (TargetSquare(targetSquare)) { TargetDirection = randomDir; } // if it was a miss, remove the current direction from the ViableDirections list and get a new random direction from the list else { ViableDirections.Remove(randomDir); randomDir = ViableDirections[rand.Next(ViableDirections.Count - 1)]; } squareHit = true; } // when we have a targetdirection else { // if we've missed, invert the targetdirection if (!TargetSquare(targetSquare)) { TargetDirection = InvertDirection(TargetDirection); } squareHit = true; } if (squareHit) { foreach (Ship ship in this.board.Ships) { // if we destroyed the ship, reset the targetdirection and the viabledirections list if (ship.isDestroyed() && ship.ShipParts.Any(x => x == targetSquare)) { TargetDirection = Direction.NONE; ResetDirections(); break; } } break; } } } } return(targetSquare); }