0

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)

2 Answers 2

1

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)
Sign up to request clarification or add additional context in comments.

8 Comments

thank you--this works perfectly as to solving the problem of it printing the erroneous grid--but it's continuing on to the new ship instead of asking again for the player to re-enter the ship coordinates--any idea how to fix that?
@JohnRogerson added to answer. See if that works - the point is to keep asking until a good set of coordinates is provided. To do that, instead of checking if the coordinates provided are good as an after-thought, ask as though they are not, and break once they are good. AKA - assume they will be bad, and loop using while until they are good.
hmm that makes a lot of sense--i tried the code--i edited OP to show the updated code--(and note i had to add a loop in order to create that 'coord' variable...but unfortunately it is not identifying the overlapping ships now ..UGH.
actually i had an error in the grid1.play_one_board---it is actually picking up the error but still printing the error ship and continuing on to the next ship...
ah ok-- i see it now...and seems to be working just fine. thanks for sticking with me! much appreciated.
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.