user3650751 user3650751 - 19 days ago 5
Python Question

Why is my program matching the wrong values?

I'm making a battleship game. I can't figure why, when you overlap a ship in n different locations, my program will ask you to input a different starting position n times.

def make_ships(name, length, position, orientation):
ships[name] = {"length": length, "Coordinates": {}}
x = ord(position[:1])
y = int(position[1:])
coords = {}
if orientation.lower() == "y":
for i in range(0, length):
place = ''.join([chr(x), str(y)])
coords[place] = "-"
x = x + 1
elif orientation.lower() == "n":
for i in range(0, length):
place = ''.join([chr(x), str(y)])
coords[place] = "|"
y = y + 1
print("Coordinates of incoming ship: {}".format(list(coords.keys())))
names = []
for item in ships:
names.append(item)
# a.append(list(self.ships[item]["Coordinates"].keys()))
for var in names:
for item in coords.keys():
if item in list(ships[var]["Coordinates"].keys()) and ships[name] != ships[var]:
print("Coordinates of {}: {}".format(var, list(ships[var]["Coordinates"].keys())))
new_position = input("There is an overlap at {}. Please enter a different starting position: ".format(item)).replace(" ","")
new_orientation = input("Is it horizontal? (Y/N): ").replace(" ","")
make_ships(name, length, new_position, new_orientation)
ships[name]["Coordinates"] = coords

ships = {}
ships["Aircraft Carrier"] = {}
ships["Aircraft Carrier"] = {"length": 5, "Coordinates": {'a1':'|', 'a2':'|', 'a3':'|', 'a4':'|', 'a5':'|'}}
make_ships("Battleship", 4, 'a1', 'n')


The battleship in the original call overlaps the existing carrier in 4 locations.
The program asks you to enter a new location and orientation.
If you pick, say, b1, the program claims an overlap and shows the coordinates of the carrier, a1-a5, which obviously do not overlap a ship in b1-b4.

Answer

PROBLEM

Your mistake was using a recursive call to make_ships, instead of a simple iteration (while loop). When the first entry fails with a match on space a4, you get the new ship's information and add it nicely. However, you then return from the recursive call to the first call, where you are still in the checking loop. That iterates to the next space in the a-column checking, finds that a1 of your original call also matches (if you're stubborn, you'll get this four times, once for each collision from the original battleship).

REPAIR

The clean way is to replace this process with a "read until good" while loop. The pseudo-code for that is:

Get first input while input is unacceptable get replacement input

The cheap way is to simply put a return after the recursive call. My code for that, including my debugging instrumentation, is below. When I tested this, I put the replacement battleship at square q7 :-) which made it obvious that the problem had nothing to do with the ships touching.

def make_ships(name, length, position, orientation):
    print ("===> ENTER make_ships", name, length, position, orientation)
    ships[name] = {"length": length, "Coordinates": {}}
    x = ord(position[:1])
    y = int(position[1:])
    coords = {}

    if orientation.lower() == "y":
        for i in range(0, length):
            place = ''.join([chr(x), str(y)])
            coords[place] = "-"
            x = x + 1
    elif orientation.lower() == "n":
        for i in range(0, length):
            place = ''.join([chr(x), str(y)])
            coords[place] = "|"
            y = y + 1
    print("Coordinates of incoming ship: {}".format(list(coords.keys())))

    # Validating for ship overlap
    names = []
    for item in ships:
        names.append(item)
        # a.append(list(self.ships[item]["Coordinates"].keys()))
    for var in names:
        # print ("coords.keys=", coords.keys())
        for item in coords.keys():
            print ("\ncoords.keys=", coords.keys())
            print ("var=", var, "\tname=", name, "\titem=", item)
            print (ships[var]["Coordinates"].keys())
            if item in list(ships[var]["Coordinates"].keys()) and ships[name] != ships[var]:
                print("Coordinates of {}: {}".format(var, list(ships[var]["Coordinates"].keys())))
                new_position = input("There is an overlap at {}. Please enter a different starting position: ".format(item)).replace(" ","")
                new_orientation = input("Is it horizontal? (Y/N): ").replace(" ","")
                make_ships(name, length, new_position, new_orientation)
                return

    ships[name]["Coordinates"] = coords

    print ("===> EXIT make_ships", coords)


ships = {}
ships["Aircraft Carrier"] = {}
ships["Aircraft Carrier"] = {"length": 5, "Coordinates": {'a1':'|', 'a2':'|', 'a3':'|', 'a4':'|', 'a5':'|'}}

make_ships("Battleship", 4, 'a1', 'n')
Comments