我在做一个pvz模拟器。我们有一个游戏板,有1=农民和2=僵尸:
[[(1, <__main__.Plant object at 0x0000011F0FDDA4C0>), (2, <__main__.Zombie object at 0x0000011F0F73D100>), 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]当农夫目标射击豌豆十次时,僵尸就会被打败并消失。如果它们不在同一排,或者农民在僵尸前面,豌豆对特定的僵尸没有影响。
我的代码:
class Object:
def __init__(self, objtype, row, column, name=None):
self.pos = self.row, self.column = row, column
self.name = name
self.setup = setup
setup[row][column] = (objtype, self)
class Plant(Object):
def __init__(self,row, column, name=None, aoe=1, damage=1):
super().__init__(1, row, column, name)
self.aoe = aoe
self.damage = damage
def shoot(self):
location = self.setup[self.row][self.column]
curr_column = self.column
while True:
try:
if location[0] == 2: # zombie
location[1].hit(self)
return
except IndexError:
pass
try:
location = self.setup[self.row][curr_column]
except IndexError:
return
curr_column += 1
class PlantTypes:
@staticmethod
def peashooter(row, column, name=None):
return Plant(row, column, name)
class Zombie(Object):
def __init__(self, row, column, name=None, health=10):
super().__init__(2, row, column, name)
self.health = health
def hit(self, plant):
self.health -= plant.damage
if self.health <= 0:
setup[self.row][self.column] = 0
class ZombieTypes:
@staticmethod
def basezombie(row, column, name=None):
return Zombie(row, column, name)
setup = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
p0 = PlantTypes.peashooter(0, 0)
z0 = ZombieTypes.basezombie(0, 1)
print(setup)
for i in range(10):
p0.shoot()
print(setup)对可读性/性能/其他有何建议?
发布于 2022-02-10 19:30:20
shoot目前是Plant上的一种方法,但我认为这是一种错误的责任分配。该功能的大部分工作是在电网上,而不是在工厂上。考虑创建一个网格类,并将其与碰撞(如射击)结合起来。
类似地,让僵尸在死亡时将自己从网格中删除(重死?)是一种错误的责任分配。
objtype整数使用起来不方便,约束也不充分。考虑只保留对对象实例的直接引用,而不是网格中的类型对象元组。
捕获IndexError是一种代码嗅觉,也是不正确算法的指示。这可以通过适当的迭代来避免。
您的工厂和僵尸类型类是多余的,可以删除。
0作为网格中的默认条目没有多大意义,因为您希望所有条目都是类型对象对。如果网格只包含对象引用,那么单个None就更有意义了。
考虑在类中添加漂亮的打印方法。
from numbers import Real
from typing import Optional
class Object:
def __init__(self, row: int, column: int, name: Optional[str] = None) -> None:
self.row, self.column = row, column
self.name = name
class Plant(Object):
def __init__(self, row: int, column: int, name: Optional[str] = None, aoe: Real = 1, damage: Real = 1) -> None:
super().__init__(row, column, name)
self.aoe = aoe
self.damage = damage
def __str__(self) -> str:
return self.name[:3] if self.name else 'pla'
class Zombie(Object):
def __init__(self, row: int, column: int, name: Optional[str] = None, health: Real = 10) -> None:
super().__init__(row, column, name)
self.health = health
def hit(self, damage: Real) -> None:
self.health -= damage
def __str__(self) -> str:
return f'Z{self.health:2d}'
class Grid:
def __init__(self, m: int, n: int) -> None:
self.m, self.n = m, n
self.grid: list[list[Optional[Object]]] = [
[None]*n
for _ in range(m)
]
def add(self, obj: Object) -> None:
self.grid[obj.row][obj.column] = obj
def shoot(self, plant: Plant) -> None:
row = self.grid[plant.row]
for col in range(1+plant.column, self.n):
zombie = row[col]
if isinstance(zombie, Zombie):
zombie.hit(plant.damage)
if zombie.health <= 0:
row[col] = None
break
def describe(self) -> str:
return '\n'.join(
' '.join(
f'{str(o):3s}' if o else ' . '
for o in row
)
for row in self.grid
)
def main() -> None:
grid = Grid(m=3, n=4)
p0 = Plant(row=0, column=0, name='peashooter')
z0 = Zombie(row=0, column=1, name='basezombie')
grid.add(p0)
grid.add(z0)
print(grid.describe())
for _ in range(10):
grid.shoot(p0)
print()
print(grid.describe())
if __name__ == '__main__':
main()pea Z10 . .
. . . .
. . . .
pea . . .
. . . .
. . . . https://codereview.stackexchange.com/questions/273953
复制相似问题