more concise way to make this?

I’m unsure of how to create a certain section of my code without it being excessively long and tedious. Is there perhaps a way of utilizing a range function where I need my elif statements? Any help shortening this would be more than appreciated!

#just some sample lists
Player.PlayerList[1].carrier_row = [0,1,2,3,4]
Player.PlayerList[1].carrier_col = [5,5,5,5,5]

Player.PlayerList[1].battleship_row = [10,11,12,13]
Player.PlayerList[1].battleship_col = [15,15,15,15]

if Player.PlayerList[1].carrier_row[0] == column:
    if Player.PlayerList[1].carrier_col[0] == row:
        print('hit')
elif Player.PlayerList[1].carrier_row[1] == column:
    if Player.PlayerList[1].carrier_col[1] == row:
        print('hit')
elif Player.PlayerList[1].carrier_row[2] == column:
    if Player.PlayerList[1].carrier_col[2] == row:
        print('hit')
elif Player.PlayerList[1].carrier_row[3] == column:
    if Player.PlayerList[1].carrier_col[3] == row:
        print('hit')
elif Player.PlayerList[1].carrier_row[4] == column:
    if Player.PlayerList[1].carrier_col[4] == row:
        print('hit')

elif Player.PlayerList[1].battleship_row[0] == column:
    if Player.PlayerList[1].battleship_col[0] == row:
        print('hit')
elif Player.PlayerList[1].battleship_row[1] == column:
    if Player.PlayerList[1].battleship_col[1] == row:
        print('hit')
elif Player.PlayerList[1].battleship_row[2] == column:
    if Player.PlayerList[1].battleship_col[2] == row:
        print('hit')
elif Player.PlayerList[1].battleship_row[3] == column:
    if Player.PlayerList[1].battleship_col[3] == row:
        print('hit')

else:
print('miss')

>Solution :

To be honest, I think the data format is inappropriate. If you have the ability to change it, I would suggest redesigning your data model to deal with points instead of individual point coordinates (x, y), e.g.:

Player.PlayerList[1].carrier = [(0, 5), (1, 5), (2, 5), (3, 5), (4,5)]

Then your check on a hit can be as simple as:

def is_hit(row: int, column: int) -> bool:
    point = (row, column)
    return (point in Player.PlayerList[1].carrier 
            or point in Player.PlayerList[1].battleship)

EDIT: Assuming you’re trying to build a battleship game, I would probably write a class Ship which manages one ship, and then use multiple of these, so something like:

class Point(NamedTuple):
    x: int
    y: int

class Ship(object):
    def __init__(self, points: List[Point]):
        self.points = points

    def check_hit(self, point: Point) -> bool:
        return point in self.points

The benefit of that is that you can now start adding logic to the Ship easily, for example by adding a .hits attribute as well that allows you to keep track of the ship health.

A player could then simply have a list of ships:

Player.PlayerList[1].ships = [
    Ship([Point(0, 5), Point(1, 5), Point(2, 5), Point(3, 5), Point(4,5)],
    Ship(...),
    ...
]

Leave a Reply