'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 1:[1]
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(...),
...
]
Solution 2:[2]
You can do this in a loop to look all the possibility without having to write them all:
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]
hit = False
for i in range(len(Player.PlayerList[1].carrier_row)):
if Player.PlayerList[1].carrier_row[i] == row and Player.PlayerList[1].carrier_col == column:
print("hit")
hit = True
for i in range(len(Player.PlayerList[1].battleship_row)):
if Player.PlayerList[1].battleship_row[i] == row and Player.PlayerList[1].battleship_col == column:
print("hit")
hit = True
if not hit:
print("miss")
Solution 3:[3]
This is more concise but untested as the values for row and column and the class definitions are unknown :
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]
pli = Player.PlayerList[1]
for cr, cc, br, bc in zip(pli.carrier_row, pli.carrier_col, pli.battleship_row, pli.battleship_col):
if row in (cr, br) or column in (cc, bc):
hit = True
break
else:
hit = False
print('hit' if hit else 'miss')
Solution 4:[4]
Each check is done against a fix value, column
& row
, so one can compare them individually and them zip
them. The nested condition is performed with an and
. Used itertools
to keep the code compact
import itertools as it
column = # some number
row = # some number
cc_cols = map(column.__eq__, Player.PlayerList[1].carrier_row)
cc_rows = map(row.__eq__, Player.PlayerList[1].carrier_row)
bship_cols = map(column.__eq__, Player.PlayerList[1].battleship_row)
bship_rows = map(row.__eq__, Player.PlayerList[1].battleship_row)
if any(it.starmap(bool.__and__, it.chain(zip(cc_cols, cc_rows), zip(bship_cols, bship_rows)))):
print('hit')
else:
print('miss')
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Xiidref |
Solution 3 | Albert Winestein |
Solution 4 | cards |