18、Python 坦克模拟编程:从基础到高级

Python 坦克模拟编程:从基础到高级

1. 坦克移动方法 move

在坦克模拟编程中, move 方法是一个比较有趣的新方法。它接收方向和距离作为参数,然后根据这些参数更新坦克的 x y 坐标。不过,在移动坦克之前,该方法会检查方向和距离是否有效。如果参数无效,会打印错误信息,并且坦克不会移动。

move 方法遵循面向对象编程的一个原则:尽可能定义方法,并使用这些方法与对象中的数据进行交互。在接受输入之前,要利用输入方法确保输入是有效的。该方法使用 Sage 函数 sin cos 计算坦克的新位置(笛卡尔坐标),并使用 n 函数( numerical_approx 的缩写)确保 x y 值存储为 Sage RealNumber 对象。

以下是 move 方法的示例代码:

def move(self, direction, distance):
    """Move the tank.
        Arguments:
            direction   floating-point number representing 
                the compass angle of movement in degrees. North is 
                0, east is 90, south is 180, and west is 270. 
                0 <= direction < 360
            distance       distance to move (in meters)
    """
    if (direction < 0) or (direction >= 360):
        print("Error: Direction must be greater than or equal \
to zero and less than 360.")
    elif distance < 0:
        print("Error: Negative distance.")
    else:
        self._x += n(distance * cos(direction * pi / 180))
        self._y += n(distance * sin(direction * pi / 180))
2. 检查 __init__ 方法传入的值

__init__ 方法没有检查装甲值、火炮伤害值和初始位置是否有效。例如,可能会意外创建一个装甲值为负数的坦克。为了避免意外结果,检查参数的类型或强制它们具有正确的类型是个好主意。装甲值和火炮伤害值应该是整数,位置应该是实数元组。可以添加代码来验证传递给 __init__ 的值。

3. 创建类模块

随着类的实用性增加,代码也变得越来越长。每次创建新示例时,都会发现自己重复使用了上一个示例中的许多代码。Python 提供了模块来帮助我们重用代码而不重复编写。

3.1 创建第一个模块

创建一个名为 tank.py 的新 Python 文件,包含以下代码:

import sage.all

class Cannon():
    """Model of a large cannon."""
    def __init__(self, damage):
        """Create a Cannon instance
            Arguments:
                damage      Integer that represents
                    the damage inflicted by the cannon
        """
        # _damage   amount of damage inflicted by cannon (integer)
        # _operational  True if operational, False if disabled
        self._damage = damage
        self._operational = True
    def __str__(self):
        return 'Damage value:' + str(self._damage)

class Track():
    """Model of a continuous track."""
    def __init__(self):
        # _operational  True if operational, False if disabled
        self._operational = True

class Turret():
    """Model of a tank turret."""
    def __init__(self, gun):
        """Create a Turret instance
            Arguments:
                gun      instance of Gun class
        """
        # _gun   instance of Gun class
        # _operational  True if operational, False if disabled
        self._gun = gun
        self._operational = True
    def __str__(self):
        return(str(self._gun))

class Tank():
    """Model of an armored fighting vehicle."""
    def __init__(self, armor_values, cannon_damage_value, position):
        """Create a tank instance
            Arguments:
                armor_values    A dictionary of armor values 
                    of the form:
                    {'front' : 100, 'side' : 50, 'rear' : 25, 
                        'turret' : 75}
                cannon_damage_value     Integer that represents
                    the damage inflicted by the main gun
                position    (x,y) tuple of coordinates
        """
        # Initialize armor
        self._frontal_armor = armor_values['front']
        self._left_armor = armor_values['side']
        self._right_armor = armor_values['side']
        self._rear_armor = armor_values['rear']
        self._turret_armor = armor_values['turret']
        # Add tank components
        main_gun = Cannon(cannon_damage_value)
        self._turret = Turret(main_gun)
        self._left_track = Track()
        self._right_track = Track()
        # Intialize position
        self._x = position[0]
        self._y = position[1]
    def __str__(self):
        import os
        ls = os.linesep
        description = 'Tank parameters:' + ls
        description += '  Armor values:' + ls
        description += '    Front:' + str(self._frontal_armor) + ls
        description += '    Left:' + str(self._left_armor) + ls
        description += '    Right:' + str(self._right_armor) + ls
        description += '    Rear:' + str(self._rear_armor) + ls
        description += '    Turret:' + str(self._turret_armor) + ls
        description += '  Weapons:' + ls
        description += '    Main cannon:' + ls
        description += '    ' + str(self._turret) + ls
        return description
    def move(self, direction, distance):
        """Move the tank.
            Arguments:
                direction   floating-point number representing 
                    the compass angle of movement in degrees. North is 
                    0, east is 90, south is 180, and west is 270. 
                    0 <= direction < 360
                distance       distance to move (in meters)
        """
        if (direction < 0) or (direction >= 360):
            print("Error: Direction must be greater than or equal \
to zero and less than 360.")
        elif distance < 0:
            print("Error: Negative distance.")
        else:
            self._x += n(distance * cos(direction * pi / 180))
            self._y += n(distance * sin(direction * pi / 180))
    def get_position(self):
        """Returns a tuple with the (x,y) coordinates of the tank's
        current location.
        """
        return (float(self._x), float(self._y))

在同一目录下,创建另一个 Python 文件,包含以下代码:

import tank

# Define parameters for the tank
armor_values = {'front' : 100, 'side' : 50, 'rear' : 25,
    'turret' : 75}
main_gun_damage = 50
initial_position = (0.0, 0.0)

# Create a tank object
tank_1 = tank.Tank(armor_values, main_gun_damage, initial_position)

pos = tank_1.get_position()
print("Initial position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Move 10m north
tank_1.move(0.0, 10.0)
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Now move 10m east
tank_1.move(90.0, 10.0)
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Move southwest, back to the origin
tank_1.move(225.0, sqrt(10.0**2 + 10.0**2))
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Try a move which doesn't make sense
tank_1.move(-2,-1)

执行上述脚本,会得到以下结果:

Initial position: x = 0.00m  y = 0.00m
Current position: x = 10.00m  y = 0.00m
Current position: x = 10.00m  y = 10.00m
Current position: x = -0.00m  y = 0.00m
Error: Direction must be greater than or equal to zero and less than 360.
3.2 模块创建说明

将之前的代码拆分成两个文件。 tank.py 是一个模块,包含类定义。模块名应遵循 Python 模块命名约定:使用小写字母,必要时使用下划线,名称应尽可能短,同时明确模块包含的内容。

tank 模块中,需要使用 import sage.all 导入 Sage 名称。这是因为 Python 中的命名空间和作用域机制。在 Sage 命令行中,所有内置名称都是可访问的,但模块有自己独立的命名空间,所以需要使用导入语句使标准 Sage 名称在整个模块中可用。为了避免多次导入 Sage,将导入语句放在类定义的开头。

第二个文件是一个脚本,导入模块并使用类创建和移动坦克实例。使用 import tank 导入 tank.py 模块,然后使用 tank.Tank 访问 tank 模块中的 Tank 类。

4. 扩展模拟到其他类型的车辆

目前已经定义了一个坦克战斗模拟的基本框架。如果想在模拟中包含其他类型的军事车辆,如装甲运兵车(APCs)、装甲汽车和补给卡车,为每个车辆定义一个类会导致代码重复。例如,每个车辆类都需要定义获取车辆位置和移动车辆的方法。可以通过应用面向对象编程的继承原则来避免代码重复。

4.1 创建车辆基类

创建一个名为 Ground_Vehicle 的基类,包含所有地面车辆共有的方法和属性。以下是 vehicle.py 文件的代码:

import sage.all

class Cannon():
    """Model of a large cannon."""
    def __init__(self, damage):
        """Create a Cannon instance
            Arguments:
                damage      Integer that represents
                    the damage inflicted by the cannon
        """
        # _damage   amount of damage inflicted by cannon (integer)
        # _operational  True if operational, False if disabled
        self._damage = damage
        self._operational = True
    def __str__(self):
        return 'Damage value:' + str(self._damage)

class Track():
    """Model of a continuous track."""
    def __init__(self):
        # _operational  True if operational, False if disabled
        self._operational = True

class Turret():
    """Model of a tank turret."""
    def __init__(self, gun):
        """Create a Turret instance
            Arguments:
                gun      instance of Gun class
        """
        # _gun   instance of Gun class
        # _operational  True if operational, False if disabled
        self._gun = gun
        self._operational = True
    def __str__(self):
        return(str(self._gun))

class Ground_Vehicle():
    """Base class for all ground vehicles"""
    def __init__(self, position):
        """Create a vehicle instance
                position    (x,y) tuple of coordinates
        """
        # Intialize position
        self._x = position[0]
        self._y = position[1]
    def move(self, direction, distance):
        """Move the tank.
            Arguments:
                direction   floating-point number representing 
                    the compass angle of movement in degrees. North is 
                    0, east is 90, south is 180, and west is 270. 
                    0 <= direction < 360
                distance       distance to move (in meters)
        """
        if (direction < 0) or (direction >= 360):
            print("Error: Direction must be greater than or equal \
to zero and less than 360.")
        elif distance < 0:
            print("Error: Negative distance.")
        else:
            self._x += sage.all.n(distance * sage.all.cos(direction * 
sage.all.pi / 180))
            self._y += sage.all.n(distance * sage.all.sin(direction * 
sage.all.pi / 180))
    def get_position(self):
        """Returns a tuple with the (x,y) coordinates of the tank's
        current location.
        """
        return (float(self._x), float(self._y))

class Tank(Ground_Vehicle):
    """Model of an armored fighting vehicle."""
    def __init__(self, armor_values, cannon_damage_value, position):
        """Constructs a tank instance
            Arguments:
                armor_values    A dictionary of armor values 
                    of the form:
                    {'front' : 100, 'side' : 50, 'rear' : 25, 
                        'turret' : 75}
                cannon_damage_value     Integer that represents
                    the damage inflicted by the main gun
                position    (x,y) tuple of coordinates
        """
        # Initialize armor
        self._frontal_armor = armor_values['front']
        self._left_armor = armor_values['side']
        self._right_armor = armor_values['side']
        self._rear_armor = armor_values['rear']
        self._turret_armor = armor_values['turret']
        # Add tank components
        main_gun = Cannon(cannon_damage_value)
        self._turret = Turret(main_gun)
        self._left_track = Track()
        self._right_track = Track()
        Ground_Vehicle.__init__(self, position)
    def __str__(self):
        import os
        ls = os.linesep
        description = 'Tank parameters:' + ls
        description += '  Armor values:' + ls
        description += '    Front:' + str(self._frontal_armor) + ls
        description += '    Left:' + str(self._left_armor) + ls
        description += '    Right:' + str(self._right_armor) + ls
        description += '    Rear:' + str(self._rear_armor) + ls
        description += '    Turret:' + str(self._turret_armor) + ls
        description += '  Weapons:' + ls
        description += '    Main cannon:' + ls
        description += '    ' + str(self._turret) + ls
        return description

修改创建 Tank 实例的脚本,从 vehicle 模块导入 Tank 类:

import vehicle

# Define parameters for the tank
armor_values = {'front' : 100, 'side' : 50, 'rear' : 25,
    'turret' : 75}
main_gun_damage = 50
initial_position = (0.0, 0.0)

# Create a tank object
tank_1 = vehicle.Tank(armor_values, main_gun_damage, initial_position)

pos = tank_1.get_position()
print("Initial position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Move 10m north
tank_1.move(0.0, 10.0)
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Now move 10m east
tank_1.move(90.0, 10.0)
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Move southwest, back to the origin
tank_1.move(225.0, sqrt(10.0**2 + 10.0**2))
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Try a move which doesn't make sense
tank_1.move(-2,-1)

运行这个脚本,会得到与之前相同的结果:

sage: load("4460_9_4.py")
Initial position: x = 0.00m  y = 0.00m
Current position: x = 10.00m  y = 0.00m
Current position: x = 10.00m  y = 10.00m
Current position: x = -0.00m  y = 0.00m
Error: Direction must be greater than or equal to zero and less than 360.
4.2 继承机制说明

创建了 Ground_Vehicle 基类,包含所有地面车辆共有的属性和方法,如位置、移动方法和获取位置方法。 Tank 类从 Ground_Vehicle 类派生而来,继承了 move get_position 方法。可以通过在派生类中定义同名方法来覆盖继承的方法。

Tank 类的 __init__ 方法中,需要显式调用基类的 __init__ 方法来初始化车辆的初始位置:

Ground_Vehicle.__init__(self, position)

修改类结构对创建和使用 Tank 实例的代码是透明的。一个设计良好的类实现了一个接口,所有与类的交互都通过这个接口进行。如果在不改变类功能的情况下改进类的设计(重构),接口应该保持不变。

5. 创建模拟包

在开发模拟程序时,可以通过创建包来改进代码的组织。包是模块的集合,以目录树的形式组织。

5.1 创建战斗模拟包

创建一个名为 combatsim 的目录,该目录的名称就是包的名称,应遵循 Python 包的命名约定。在该目录中创建一个名为 __init__.py 的空文件,用于告诉 Python 解释器该目录是一个包。

combatsim 目录中,创建 components.py 文件,包含 Cannon Track Turret 类的定义:

class Cannon():
    """Model of a large cannon."""
    def __init__(self, damage):
        """Create a Cannon instance
            Arguments:
                damage      Integer that represents
                    the damage inflicted by the cannon
        """
        # _damage   amount of damage inflicted by cannon (integer)
        # _operational  True if operational, False if disabled
        self._damage = damage
        self._operational = True
    def __str__(self):
        return 'Damage value:' + str(self._damage)

class Track():
    """Model of a continuous track."""
    def __init__(self):
        # _operational  True if operational, False if disabled
        self._operational = True

class Turret():
    """Model of a tank turret."""
    def __init__(self, gun):
        """Create a Turret instance
            Arguments:
                gun      instance of Gun class
        """
        # _gun   instance of Gun class
        # _operational  True if operational, False if disabled
        self._gun = gun
        self._operational = True
    def __str__(self):
        return(str(self._gun))

创建 vehicle.py 文件,定义 Ground_Vehicle 基类:

import sage.all

class Ground_Vehicle():
    """Base class for all ground vehicles"""
    def __init__(self, position):
        """Create a vehicle instance
                position    (x,y) tuple of coordinates
        """
        # Intialize position
        self._x = position[0]
        self._y = position[1]
    def move(self, direction, distance):
        """Move the tank.
            Arguments:
                direction   floating-point number representing 
                    the compass angle of movement in degrees. North is 
                    0, east is 90, south is 180, and west is 270. 
                    0 <= direction < 360
                distance       distance to move (in meters)
        """
        if (direction < 0) or (direction >= 360):
            print("Error: Direction must be greater than or equal \
to zero and less than 360.")
        elif distance < 0:
            print("Error: Negative distance.")
        else:
            self._x += sage.all.n(distance * sage.all.cos(direction * 
sage.all.pi / 180))
            self._y += sage.all.n(distance * sage.all.sin(direction * 
sage.all.pi / 180))
    def get_position(self):
        """Returns a tuple with the (x,y) coordinates of the tank's
        current location.
        """
        return (float(self._x), float(self._y))

创建 tank.py 文件:

import sage.all

class Ground_Vehicle():
    """Base class for all ground vehicles"""
    def __init__(self, position):
        """Create a vehicle instance
                position    (x,y) tuple of coordinates
        """
        # Intialize position
        self._x = position[0]
        self._y = position[1]
    def move(self, direction, distance):
        """Move the vehicle.
            Arguments:
                direction   floating-point number representing 
                    the compass angle of movement in degrees. North
                    is 0, east is 90, south is 180, and west is 270. 
                    0 <= direction < 360
                distance       distance to move (in meters)
        """
        if (direction < 0) or (direction > 360):
            print("Error: Direction must be greater than or equal \
to zero and less than 360.")
        elif distance < 0:
            print("Error: Negative distance.")
        else:
            self._x += sage.all.n(distance * sage.all.cos(direction * 
                sage.all.pi / 180))
            self._y += sage.all.n(distance * sage.all.sin(direction * 
                sage.all.pi / 180))
    def get_position(self):
        """Returns a tuple with the (x,y) coordinates of the tank's
        current location.
        """
        return (float(self._x), float(self._y))

最后,在与 combatsim 目录相同的目录中创建一个文件,包含以下代码:

from combatsim import tank

# Define parameters for the tank
armor_values = {'front' : 100, 'side' : 50, 'rear' : 25,
    'turret' : 75}
main_gun_damage = 50
initial_position = (0.0, 0.0)

# Create a tank object
tank_1 = tank.Tank(armor_values, main_gun_damage, initial_position)

pos = tank_1.get_position()
print("Initial position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Move 10m north
tank_1.move(0.0, 10.0)
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Now move 10m east
tank_1.move(90.0, 10.0)
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Move southwest, back to the origin
tank_1.move(225.0, sqrt(10.0**2 + 10.0**2))
pos = tank_1.get_position()
print("Current position: x = {0:.2f}m  y = {1:.2f}m".format(pos[0], 
pos[1]))

# Try a move which doesn't make sense
tank_1.move(-2,-1)

运行这个代码,如果一切正确,会得到与之前相同的结果:

sage: load("4460_9_5.py")
Initial position: x = 0.00m  y = 0.00m
Current position: x = 10.00m  y = 0.00m
Current position: x = 10.00m  y = 10.00m
Current position: x = -0.00m  y = 0.00m
Error: Direction must be greater than or equal to zero and less than 360.
5.2 包创建说明

将示例代码拆分成四个文件,类定义放在 combatsim 包中,该包包含 components vehicle tank 模块。在 tank.py 文件中,使用 from components import * 导入 components 模块中的所有名称。在同一包中导入自己创建的模块时,可以使用 import * ,但一般情况下应避免在其他情况下使用,因为不同模块可能定义了同名的函数或类,使用 import * 会导致无法确定使用的是哪个函数或类。

通过上述步骤,我们完成了从简单的坦克模拟到包含多类车辆的模拟程序的开发,并通过模块和包的使用,提高了代码的可维护性和可重用性。

Python 坦克模拟编程:从基础到高级

6. 代码结构与模块分析

为了更清晰地理解整个模拟程序的代码结构,我们可以将各个模块的作用和关系整理成表格:
| 模块名 | 作用 | 包含类 |
| ---- | ---- | ---- |
| components.py | 定义坦克的组件类 | Cannon、Track、Turret |
| vehicle.py | 定义地面车辆的基类 | Ground_Vehicle |
| tank.py | 定义坦克类,继承自 Ground_Vehicle | Tank |

下面是代码结构的 mermaid 流程图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(combatsim 包):::process --> B(components.py):::process
    A --> C(vehicle.py):::process
    A --> D(tank.py):::process
    B --> E(Cannon 类):::process
    B --> F(Track 类):::process
    B --> G(Turret 类):::process
    C --> H(Ground_Vehicle 类):::process
    D --> I(Tank 类):::process
    I --> H
    I --> E
    I --> F
    I --> G

    J(主脚本):::process --> D

从这个流程图可以看出, combatsim 包包含了三个主要模块, tank.py 中的 Tank 类继承自 vehicle.py 中的 Ground_Vehicle 类,并且使用了 components.py 中的组件类。主脚本则导入 tank.py 中的 Tank 类来创建和操作坦克对象。

7. 代码优化建议

虽然我们已经完成了基本的模拟程序,但还有一些可以优化的地方。以下是一些优化建议和具体操作步骤:

7.1 参数验证优化

__init__ 方法中添加更完善的参数验证,确保传入的参数符合要求。例如,对于装甲值和火炮伤害值,确保它们是正整数;对于位置,确保是有效的实数元组。

class Tank(Ground_Vehicle):
    def __init__(self, armor_values, cannon_damage_value, position):
        # 验证装甲值
        if not isinstance(armor_values, dict):
            raise ValueError("armor_values 必须是字典类型")
        for key, value in armor_values.items():
            if not isinstance(value, int) or value < 0:
                raise ValueError("装甲值必须是正整数")

        # 验证火炮伤害值
        if not isinstance(cannon_damage_value, int) or cannon_damage_value < 0:
            raise ValueError("火炮伤害值必须是正整数")

        # 验证位置
        if not isinstance(position, tuple) or len(position) != 2:
            raise ValueError("位置必须是包含两个实数的元组")
        for coord in position:
            if not isinstance(coord, (int, float)):
                raise ValueError("位置坐标必须是实数")

        # 初始化装甲
        self._frontal_armor = armor_values['front']
        self._left_armor = armor_values['side']
        self._right_armor = armor_values['side']
        self._rear_armor = armor_values['rear']
        self._turret_armor = armor_values['turret']

        # 添加坦克组件
        main_gun = Cannon(cannon_damage_value)
        self._turret = Turret(main_gun)
        self._left_track = Track()
        self._right_track = Track()

        Ground_Vehicle.__init__(self, position)
7.2 代码复用优化

将一些重复的逻辑提取到单独的函数中,提高代码的复用性。例如,将移动计算的逻辑提取到一个单独的函数中。

import sage.all

def calculate_new_position(x, y, direction, distance):
    if (direction < 0) or (direction >= 360):
        print("Error: Direction must be greater than or equal to zero and less than 360.")
        return x, y
    elif distance < 0:
        print("Error: Negative distance.")
        return x, y
    else:
        new_x = x + sage.all.n(distance * sage.all.cos(direction * sage.all.pi / 180))
        new_y = y + sage.all.n(distance * sage.all.sin(direction * sage.all.pi / 180))
        return new_x, new_y

class Ground_Vehicle():
    def __init__(self, position):
        self._x = position[0]
        self._y = position[1]

    def move(self, direction, distance):
        self._x, self._y = calculate_new_position(self._x, self._y, direction, distance)

    def get_position(self):
        return (float(self._x), float(self._y))
7.3 异常处理优化

在代码中添加适当的异常处理,增强程序的健壮性。例如,在导入模块时,如果模块不存在或出现其他错误,能够捕获异常并给出友好的提示。

try:
    from combatsim import tank
except ImportError:
    print("无法导入 combatsim.tank 模块,请检查包路径和模块是否存在。")
else:
    # 定义坦克参数
    armor_values = {'front': 100, 'side': 50, 'rear': 25, 'turret': 75}
    main_gun_damage = 50
    initial_position = (0.0, 0.0)

    # 创建坦克对象
    try:
        tank_1 = tank.Tank(armor_values, main_gun_damage, initial_position)
    except ValueError as e:
        print(f"创建坦克对象时出错: {e}")
    else:
        pos = tank_1.get_position()
        print(f"Initial position: x = {pos[0]:.2f}m  y = {pos[1]:.2f}m")

        # 移动坦克
        try:
            tank_1.move(0.0, 10.0)
            pos = tank_1.get_position()
            print(f"Current position: x = {pos[0]:.2f}m  y = {pos[1]:.2f}m")

            tank_1.move(90.0, 10.0)
            pos = tank_1.get_position()
            print(f"Current position: x = {pos[0]:.2f}m  y = {pos[1]:.2f}m")

            tank_1.move(225.0, sage.all.sqrt(10.0**2 + 10.0**2))
            pos = tank_1.get_position()
            print(f"Current position: x = {pos[0]:.2f}m  y = {pos[1]:.2f}m")

            tank_1.move(-2, -1)
        except Exception as e:
            print(f"移动坦克时出错: {e}")
8. 扩展功能设想

除了现有的功能,我们还可以设想一些扩展功能,进一步完善这个模拟程序。以下是一些扩展功能的建议和实现思路:

8.1 车辆状态管理

为车辆添加更多的状态信息,如是否被击中、部件是否损坏等。可以在 Ground_Vehicle 类中添加相应的属性,并在 move 方法或其他方法中根据状态进行不同的处理。

class Ground_Vehicle():
    def __init__(self, position):
        self._x = position[0]
        self._y = position[1]
        self._is_hit = False
        self._is_moving = False

    def move(self, direction, distance):
        if self._is_hit:
            print("车辆已被击中,无法移动。")
            return
        self._is_moving = True
        self._x, self._y = calculate_new_position(self._x, self._y, direction, distance)
        self._is_moving = False

    def get_position(self):
        return (float(self._x), float(self._y))

    def hit(self):
        self._is_hit = True
8.2 战斗模拟

添加战斗模拟功能,让不同的车辆之间可以进行战斗。可以在车辆类中添加攻击和被攻击的方法,根据车辆的属性计算伤害和判断胜负。

class Tank(Ground_Vehicle):
    def __init__(self, armor_values, cannon_damage_value, position):
        # 初始化代码...
        self._cannon_damage = cannon_damage_value

    def attack(self, target):
        if isinstance(target, Ground_Vehicle):
            # 简单的伤害计算,可根据实际情况调整
            damage = self._cannon_damage
            target.take_damage(damage)
            print(f"坦克攻击目标,造成 {damage} 点伤害。")
        else:
            print("目标不是有效的车辆对象。")

    def take_damage(self, damage):
        # 根据装甲值计算实际受到的伤害,可根据实际情况调整
        effective_damage = damage - self._frontal_armor
        if effective_damage > 0:
            # 这里可以添加更多的逻辑,如部件损坏等
            print(f"坦克受到 {effective_damage} 点伤害。")
        else:
            print("坦克的装甲抵挡住了攻击,未受到伤害。")
8.3 地图和障碍物

引入地图和障碍物的概念,让车辆在移动时需要考虑地图的边界和障碍物。可以创建一个地图类,包含地图的大小、障碍物的位置等信息,并在 move 方法中添加相应的检查。

class Map():
    def __init__(self, width, height, obstacles):
        self._width = width
        self._height = height
        self._obstacles = obstacles

    def is_valid_position(self, x, y):
        if x < 0 or x >= self._width or y < 0 or y >= self._height:
            return False
        for obstacle in self._obstacles:
            if (x, y) == obstacle:
                return False
        return True

class Ground_Vehicle():
    def __init__(self, position, map):
        self._x = position[0]
        self._y = position[1]
        self._map = map

    def move(self, direction, distance):
        new_x, new_y = calculate_new_position(self._x, self._y, direction, distance)
        if self._map.is_valid_position(new_x, new_y):
            self._x = new_x
            self._y = new_y
            print("车辆成功移动到新位置。")
        else:
            print("目标位置无效,无法移动。")

通过以上的优化和扩展,我们可以让这个坦克模拟程序更加完善和强大,同时也能更好地理解 Python 面向对象编程和模块、包的使用。希望这些内容能对你有所帮助,让你在编程的道路上不断进步!

源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值