def test_overlapping_ships(): dimensions = (10, 10) with pytest.raises(RuntimeError) as e_info: ships = {Ship(1, 1, 3, "h"), Ship(2, 0, 3, "v")} _ = Board(dimensions, ships) assert str(e_info.value).startswith("overlapping ships at (2, 1)")
def __init__(self): self.ships = [ Ship(ShipType.CARRIER), Ship(ShipType.BATTLESHIP), Ship(ShipType.FRIGATE), Ship(ShipType.SUBMARINE), Ship(ShipType.DESTROYER), ] self.game_board = self._generate_game_board(self.ships)
def test_no_winner(): dims = (5, 5) s1 = {Ship(1, 1, 3, "v")} p1 = Player(Board(dims, s1)) s2 = {Ship(1, 1, 3, "v")} p2 = Player(Board(dims, s2)) game = Game(p1, p2, dims) result = game.get_winner() assert result is None
def test_game_text(): dims = (3, 3) s1 = {Ship(0, 0, 3, "v")} p1 = Player(Board(dims, s1)) s2 = {Ship(0, 0, 3, "v")} p2 = Player(Board(dims, s2)) game = Game(p1, p2, dims) p1_lines = game.p1_lines() p2_lines = game.p2_lines() assert list(p1_lines) == [["s", ".", "."], ["s", ".", "."], ["s", ".", "."]] assert list(p2_lines) == [["s", ".", "."], ["s", ".", "."], ["s", ".", "."]]
def example_two_players_users(): # Creating the ships MANUALLY for the 2 players Alice and Bob list_ships_player_alice = [ Ship(coord_start=(3, 1), coord_end=(3, 5)), # length = 5 Ship(coord_start=(9, 7), coord_end=(9, 10)), # length = 4 Ship(coord_start=(1, 9), coord_end=(3, 9)), # length = 3 Ship(coord_start=(5, 2), coord_end=(6, 2)), # length = 2 Ship(coord_start=(8, 3), coord_end=(8, 3)), # length = 1 ] list_ships_player_bob = [ Ship(coord_start=(5, 8), coord_end=(9, 8)), # length = 5 Ship(coord_start=(5, 4), coord_end=(8, 4)), # length = 4 Ship(coord_start=(3, 1), coord_end=(5, 1)), # length = 3 Ship.get_ship_from_str_coordinates( coord_str_start='F10', coord_str_end='G10'), # Another way of creating a Ship Ship.get_ship_from_str_coordinates( coord_str_start='A4', coord_str_end='A4'), # Another way of creating a Ship ] # Creating their boards board_player_alice = Board(list_ships_player_alice) board_player_bob = Board(list_ships_player_bob) # Creating the players player_alice = PlayerUser(board_player_alice, name_player="Alice") player_bob = PlayerUser(board_player_bob, name_player="Bob") # Creating and launching the game game = Game(player_1=player_alice, player_2=player_bob) game.play()
def test_p2_winner(): dims = (5, 5) s1 = {Ship(1, 1, 3, "v")} p1 = Player(Board(dims, s1)) s2 = {Ship(1, 1, 3, "v")} p2 = Player(Board(dims, s2)) game = Game(p1, p2, dims) game.p2_move(1, 1) game.p2_move(1, 2) game.p2_move(1, 3) result = game.get_winner() assert result == 2
def test_misses_ship(): ships = {Ship(1, 1, 2, "v")} record = DamageRecord(ships) ship = record.hit(3, 3) assert ship is None
def test_validate_negative_y_grid(): dimensions = (1, 1) with pytest.raises(RuntimeError) as e_info: ships = {Ship(0, -5, 2, "h")} _ = Board(dimensions, ships) assert "cannot be a negative coordinate" == str(e_info.value)
def test_validate_exceeds_x_grid(): dimensions = (1, 1) with pytest.raises(RuntimeError) as e_info: ships = {Ship(1, 1, 2, "h")} _ = Board(dimensions, ships) assert "exceeds size" == str(e_info.value)
def test_all_hit(): ships = {Ship(1, 1, 2, "v")} record = DamageRecord(ships) record.hit(1, 1) record.hit(1, 2) assert record.is_all_hit()
def test_hitting_ship(): expected = Ship(1, 1, 2, "v") ships = {expected} record = DamageRecord(ships) ship = record.hit(1, 1) assert ship == expected
def test_get_floating_positions(): ship = Ship(1, 1, 2, "v") ships = {ship} record = DamageRecord(ships) positions = record.get_floating_positions(ship) assert positions == {(1, 1), (1, 2)}
def test_opponent_move_guessed(): dims = (5, 5) s1 = {Ship(1, 1, 3, "v")} p1 = Player(Board(dims, s1)) with pytest.raises(RuntimeError, match="already guessed"): p1.opponent_move(1, 1) p1.opponent_move(1, 1)
def generate_ship(self, size, taken_coordinates) -> Ship: # Method that generates a ship of specific size, while making sure it does not conflict # with the coordinates of other ships defined in an array called taken_coordinates. # Loops until it finds a ship that fits all the selection criteria (coordinates in bounds of board, no conflicts) while (1): # seedx and seedy are random coordinates that act as seed from which ship grows either backwards or downwards seedx = random.randint(1, 10) seedy = random.randint(1, 10) # array that stores coordinates of ship so they can be checked against taken_coordinates later ship_coords = [] # offset is the offset from seed representing the size of the ship offset = size - 1 # first randomly selects vertical or horizontal if random.choice([True, False]): # True = Horizontal, False = Vertical if 1 <= seedx - offset <= 9: # checks if ships start position (seed - offset) is on the board # defines start and end coordinates, and adds them to ship_coords xstart = seedx - offset xend = seedx ystart = seedy yend = seedy for coord in range((seedx - offset), seedx + 1): coordinates = (coord, seedy) ship_coords.append(coordinates) else: # start coordinate for ship is outside board, starts loop again continue else: if 1 <= seedy - offset <= 9: # checks if ships start position (seed - offset) is on the board # defines start and end coordinates, and adds them to ship_coords xstart = seedx xend = seedx ystart = seedy - offset yend = seedy for coord in range((seedy - offset), seedy + 1): coordinates = (seedx, coord) ship_coords.append(coordinates) else: # start coordinate for ship is outside board, starts loop again continue # checks if coordinates of ship conflict with other previously created ships coords_taken = False for coord in ship_coords: if coord in taken_coordinates: coords_taken = True if not coords_taken: # if no conflict exists, creates ship and adds coordinates to taken_coordinates for coord in ship_coords: taken_coordinates.add(coord) GeneratedShip = Ship(coord_start=(xstart, ystart), coord_end=(xend, yend)) break # selection criteria met, exits loop else: continue # if conflict exists, starts loop again return GeneratedShip
def test_player_is_defeated(): dims = (5, 5) s1 = {Ship(1, 1, 3, "v")} p1 = Player(Board(dims, s1)) for i in range(3): p1.opponent_move(1, 1 + i) assert p1.is_defeated
def test_player(): dims = (5, 5) s1 = {Ship(1, 1, 3, "v")} p1 = Player(Board(dims, s1)) for i in range(3): p1.opponent_move(1, 1 + i) assert list(p1.text) == [ [".", ".", ".", ".", "."], [".", "h", ".", ".", "."], [".", "h", ".", ".", "."], [".", "h", ".", ".", "."], [".", ".", ".", ".", "."], ]
def example_user_manual_board_vs_full_automatic(): # Creating the ships MANUALLY for the User (Alice) list_ships_player_alice = [ Ship(coord_start=(3, 1), coord_end=(3, 5)), # length = 5 Ship(coord_start=(9, 7), coord_end=(9, 10)), # length = 4 Ship(coord_start=(1, 9), coord_end=(3, 9)), # length = 3 Ship(coord_start=(5, 2), coord_end=(6, 2)), # length = 2 Ship(coord_start=(8, 3), coord_end=(8, 3)), # length = 1 ] # Creating her boards board_player_alice = Board(list_ships_player_alice) # Creating her player player_alice = PlayerUser(board_player_alice, name_player="Alice") # Creating a Random Player Bob, its board is automatically created randomly player_bob = PlayerRandom(name_player="Bob") # Creating and launching the game game = Game(player_1=player_alice, player_2=player_bob) game.play()
def create_ship_of_certain_length(self, length): """Here I create chips depending on the length given. Then I make sure the ships are either horizonal or vertical""" orientation = random.choice(['horizontal', 'vertical']) if orientation == 'horizontal': self.x_random_start = random.randint(1, self.SIZE_X - length + 1) self.y_random_start = random.randint(1, self.SIZE_Y) self.x_random_end = self.x_random_start + length - 1 self.y_random_end = self.y_random_start else: self.x_random_start = random.randint(1, self.SIZE_X) self.y_random_start = random.randint(1, self.SIZE_Y - length + 1) self.x_random_end = self.x_random_start self.y_random_end = self.y_random_start + length - 1 self.coord_start = self.x_random_start, self.y_random_start self.coord_end = self.x_random_end, self.y_random_end self.ship = Ship(coord_start=self.coord_start, coord_end=self.coord_end) return self.ship
coord_random_x = random.randint(1, self.board.SIZE_X) coord_random_y = random.randint(1, self.board.SIZE_Y) coord_random = (coord_random_x, coord_random_y) return coord_random def _is_position_near_previously_sunk_ship(self, coord: tuple) -> bool: for ship_opponent in self.list_ships_opponent_previously_sunk: # type: Ship if ship_opponent.has_sunk() and ship_opponent.is_near_coordinate( *coord): return True return False if __name__ == '__main__': # SANDBOX for you to play and test your functions list_ships = [ Ship(coord_start=(1, 1), coord_end=(1, 1)), Ship(coord_start=(3, 3), coord_end=(3, 4)), Ship(coord_start=(5, 3), coord_end=(5, 5)), Ship(coord_start=(7, 1), coord_end=(7, 4)), Ship(coord_start=(9, 3), coord_end=(9, 7)), ] board = Board(list_ships) player = PlayerUser(board) print(player.is_attacked_at(5, 4)) print(player.has_lost())
def test_hits_still_left(): ships = {Ship(1, 1, 3, "v")} record = DamageRecord(ships) assert not record.is_all_hit()
def test_ships_vertical(): ship = Ship(1, 1, 3, "v") assert ship.positions == {(1, 1), (1, 2), (1, 3)}
def test_invalid_orientation(): with pytest.raises(RuntimeError, match="invalid orientation x"): _ = Ship(1, 1, 3, "x")
def test_get_position(): ship = Ship(1, 1, 3, "h") assert ship.get_position() == (1, 1)
def test_ships_horizontal(): ship = Ship(1, 1, 3, "h") assert ship.positions == {(1, 1), (2, 1), (3, 1)}
from battleship.game import Game, Player from battleship.ship import Ship def print_game(p1_lines, p2_lines): print("Player 1:") for line in p1_lines: print("".join(line)) print("Player 2:") for line in p2_lines: print("".join(line)) if __name__ == "__main__": dimensions = (10, 10) p1_board = Board(dimensions, {Ship(1, 1, 9, "h"), Ship(3, 5, 4, "v")}) p1 = Player(p1_board) p2_board = Board(dimensions, {Ship(1, 2, 2, "v"), Ship(5, 6, 2, "h")}) p2 = Player(p2_board) game = Game(p1, p2, dimensions) game.p1_move(3, 1) game.p1_move(3, 7) # game.p2_move(1, 1) # win game.p1_move(1, 2) game.p1_move(1, 3) game.p1_move(5, 6) game.p1_move(6, 6)