返回首页

Python 中的战舰库:Field 和 Ship 类

本文分解了 Python 中战舰游戏逻辑库的创建。描述了 Field 和 Ship 类、坐标验证方法、舰船放置和典型错误。提供了代码示例和优化架构的重构建议。

创建战舰库:Python 中的 Field 和 Ship
Advertisement 728x90

Python开发海战棋游戏逻辑库:架构设计与常见陷阱

该库实现了经典海战棋游戏的逻辑,专注于数学最优算法。主要类包括用于表示游戏棋盘的Field类和用于管理船只的Ship类。棋盘以10x10矩阵形式存储,使用列表的列表,其中符号表示状态:空格表示空单元格,'1'表示完好的船体部分,'.'表示未命中,'X'表示被摧毁的单元格。

Field类处理棋盘创建、坐标验证、船只放置和射击处理。坐标输入格式为'a1',其中字母A-J对应行,数字1-10对应列。规则固定:1艘四格船、2艘三格船、3艘两格船、4艘单格船;船只不得相互接触,即使在角落也不行。

实现Field类

初始化创建空网格:

Google AdInline article slot
class Field:
    def __init__(self):
        height = 10
        weight = 10
        self.grid = [[' ' for i in range(weight)] for i in range(height)]

display()方法将棋盘输出到控制台并附带坐标。初始版本存在错误——方法line.insert(0, letter)在重复调用时通过添加字母改变了原始网格。修复方法:单独打印字母而不改变结构。

def display(self):
    print('  1 2 3 4 5 6 7 8 9 10')
    letters = 'ABCDEFGHIJ'
    count_letters = 0
    for line in self.grid:
        print(letters[count_letters], *line)
        count_letters += 1

坐标验证被提取到私有方法_validation_coordinate()中。它检查字符串长度(2-3个字符)、字母是否在A-J范围内以及数字是否在1-10范围内。方法find_coordinate()确定单元格状态:空、命中、摧毁、未受损、已射击。

用于坐标转换的字典存储为属性self.rows和self.columns:

Google AdInline article slot
  • rows: {'a': 0, 'b': 1, ..., 'j': 9}
  • columns: {'1': 0, '2': 1, ..., '10': 9}

Ship类与船只放置

Ship类将参数存储在字典中:

class Ship:
    def __init__(self):
        self.parameters = {
            'alive coordinates': [],
            'hitted coordinates': [],
            'alive': True
        }
        self.field = None
    def set_field(self, field):
        self.field = field

Field中的方法add_ship(ship, coordinate_line, length)根据类似'a1-a2-a3'的字符串放置船只。首先,进行行验证_ship_line_validation():解析为坐标,检查线性(水平/垂直),并匹配长度。然后,为每个坐标调用ship.set_coordinate_in_ship(coordinate),在网格中设置'1'。

def add_ship(self, ship, coordinate_line, length):   
    ship.set_field(self)
    if not self._ship_line_validation(coordinate_line):
        return False
    coordinates = coordinate_line.split('-')   
    if length != len(coordinates):
        return False
    for coordinate in coordinates:
        result = ship.set_coordinate_in_ship(coordinate)
        if result:
            rows = self.rows[coordinate[0]]
            columns = self.columns[coordinate[1:]]
            self.grid[rows][columns] = '1'
    return True

Field与Ship的关系是双向的:Field调用ship.set_field(self),而Ship使用self.field进行验证。这违反了基础层的封装原则,但简化了API。

Google AdInline article slot

重构见解

该项目揭示了关键的新手陷阱:

  • 方法重载:find_coordinate()结合了验证、搜索和输出——拆分为_validation_coordinate()和get_cell_state()。
  • 数据突变:避免在display()中使用insert();使用副本操作。
  • 硬编码字典:提取为类常量或使用ord()进行转换。
  • 返回值:标准化:True/False表示成功,字符串表示错误。

为优化游戏玩法,集成概率搜索算法:命中后扫描相邻单元格;摧毁后从概率中排除船体部分。

关键要点

  • Field作为列表矩阵,使用符号表示状态;通过字典self.rows/self.columns进行坐标验证。
  • Ship存储完好/命中坐标;通过set_field()与Field建立双向链接。
  • 通过coordinate_line('a1-a2')放置;检查线性和缓冲区。
  • 避免在display()中改变网格;将常见检查提取到私有方法中。
  • 对于高级算法:将射击概率图单独存储于网格之外。

— Editorial Team

Advertisement 728x90

继续阅读