John Rogerson
John Rogerson

Reputation: 1183

Python Validation Check Messing Up My Loop

I'm creating a Python 2-Player battleship game and all is almost done, except for a few small issues. In the stage where the player places all the ships on the board--I'm having trouble with validation to check for duplicate ships. Here is my code for loop of ship placement:

 while True:
        for ship_name, ship_size in Game.SHIP_INFO:
            # create ship instance
            ship1 = Ship(player1, ship_name, ship_size)
            # ask user for starting coordinate for ship in form "A1" and split into x,y variables
            x, y = ship1.split_coordinates(ship_name,player1.player)
            # ask user for ship's position --horizontal or vertical
            direction = ship1.ask_ship_location()
            # create all coordinates for ship based on size of ship and location
            created_coords = ship1.create_ship_coordinates(x, y, ship_size,direction)
            # check to see if ship already on board
            for coord in created_coords:
                if any(coord in ship for ship in grid1.play_one_board):
                    print("Sorry you already have a ship in that location")
                    continue
                else:
                    break
            # add coordinates to player's grid
            grid1.play_one_board.append(created_coords)
            # loop through coords for ship to print out on displayed grid
            grid1.print_ship_coordinates(created_coords,direction)

it's this validation part here which i just tried to implement which is causing problems.

for coord in created_coords:
                if any(coord in ship for ship in grid1.play_one_board):
                    print("Sorry you already have a ship in that location")
                    continue
                else:
                    break

it is correctly identifying if an existing coordinate has allready been placed --BUT it is continuing on to the next two steps in the loop which print the board and then moving on to the next ship placement without asking again for a corrected version of the overlapped ship placement. Just need to figure out best way for the loop to go back to the beginning if there is an error in ship overlap. Any ideas? Thanks.

EDIT --changed code to this per suggestions but not getting any validation errors.

 while True:
        for ship_name, ship_size in Game.SHIP_INFO:
            # create ship instance
            ship1 = Ship(player1, ship_name, ship_size)
            ship_exists = True
            while ship_exists:
                # ask user for starting coordinate for ship in form "A1" and split into x,y variables
                x, y = ship1.split_coordinates(ship_name,player1.player)
                # ask user for ship's position --horizontal or vertical
                direction = ship1.ask_ship_location()
                # create all coordinates for ship based on size of ship and location
                created_coords = ship1.create_ship_coordinates(x, y, ship_size,direction)
                # check to see if ship already on board
                for coord in created_coords:
                    ship_exists = any(coord in ship for ship in grid1.play_board)
                    if ship_exists:
                        print("sorry")
                    else:
                        break
                # function to check for overlapped ships
                # ship1.check_overlap(created_coords, grid1.play_one_board)
                # add coordinates to player's grid
            grid1.play_one_board.append(created_coords)
            # loop through coords for ship to print out on displayed grid
            grid1.print_ship_coordinates(created_coords, direction)

Upvotes: 0

Views: 133

Answers (2)

Sagar
Sagar

Reputation: 9503

I believe your problem is here:

for coord in created_coords:
    if any(coord in ship for ship in grid1.play_one_board):
        print("Sorry you already have a ship in that location")
        continue
    else:
        break

If a ship is found in the existing location, you want to continue to ask for new coordinates. In this case, your continue actually continues the inner loop, not the outer loop.

This means your loop checks all coords, and breaks when it finds one without an existing ship, causing the next two steps after the for loop to be executed. I'd add a check variable instead of just continuing:

ship_exists = False
for coord in created_coords:
    if any(coord in ship for ship in grid1.play_one_board):
        print("Sorry you already have a ship in that location")
        ship_exists = True
        break
if ship_exists:
    continue

This will ensure that, if a ship already exists, the first step in the outer loop is re-executed.

=============

Final answer, based on comments

def _are_valid_coordinates(created_coords, play_one_board):
    for ship in play_one_board:
        for coord in created_coords:
            if created_coords in ship:
                return False
    return True


while True:
    for ship_name, ship_size in Game.SHIP_INFO:
        # create ship instance
        ship1 = Ship(player1, ship_name, ship_size)

        valid_coords = False
        # ask user for starting coordinate for ship in form "A1" and split into x,y variables
        while not valid_coords:
            x, y = ship1.split_coordinates(ship_name,player1.player)
            # ask user for ship's position --horizontal or vertical
            direction = ship1.ask_ship_location()
            # create all coordinates for ship based on size of ship and location
            created_coords = ship1.create_ship_coordinates(x, y, ship_size,direction)
            # check to see if ship already on board
            valid_coords = _are_valid_coordinates(created_coords, ship1.play_one_board)
            if not valid_coords:
                print("Sorry you already have a ship in that location")
            else:
                break
    # add coordinates to player's grid
    grid1.play_one_board.append(created_coords)
    # loop through coords for ship to print out on displayed grid
    grid1.print_ship_coordinates(created_coords,direction)

Upvotes: 1

Bemmu
Bemmu

Reputation: 18247

When you do the continue, it just /continues from that "for coord in created_coords" inner loop.

To continue the outer loop, you could do so based on a flag. Something along the lines of:

already_had_ship = False
for coord in created_coords:
    if any(coord in ship for ship in grid1.play_one_board):
        already_had_ship = True
        print("Sorry you already have a ship in that location")
        break

if already_had_ship:
    continue

Upvotes: 0

Related Questions