如何让Python棋盘在同一网格更新棋子符号而非生成多独立网格?
棋盘无法累积更新棋子状态问题
问题现象
调用set_colour方法时,每次操作都会输出独立的空网格,无法在同一棋盘上累积更新棋子符号。
预期效果
A B C D E 5 . . . . . 4 . . . . . 3 . . . . . 2 . . . . . 1 . O @ @ . A B C D E 5 . . . . . 4 . . . . . 3 . . . . . 2 . . . . . 1 . O . @ .
实际输出
A B C D E 5 . . . . . 4 . . . . . 3 . . . . . 2 . . . . . 1 . O . . . A B C D E 5 . . . . . 4 . . . . . 3 . . . . . 2 . . . . . 1 . . @ . . A B C D E 5 . . . . . 4 . . . . . 3 . . . . . 2 . . . . . 1 . . . @ .
核心问题
set_colour方法每次都会新建空网格arr,没有将网格作为Board类的实例属性维护,导致无法保留之前的修改。__str__方法同样每次生成新的空网格,无法展示已修改的棋盘状态。
修改后的代码
class Board(): # 棋子符号映射字典 points = {'E': '.', 'B': '@', 'W': 'O'} # 构造函数 def __init__(self, size=19, from_strings=None): self.size = size # 初始化棋盘网格为实例属性,默认全为空 self.grid = [[self.points['E'] for _ in range(self.size)] for _ in range(self.size)] # 棋盘尺寸校验 assert 2 <= self.size <= 26, "Illegal board size: must be between 2 and 26." # 处理从字符串初始化棋盘的逻辑 if from_strings is not None: assert isinstance(from_strings, list), "input is not a list" assert len(from_strings) == self.size, "length of input list does not match size" for idx, row in enumerate(from_strings): assert isinstance(row, str), f"row {idx+1} is not a string" assert len(row) == self.size, f"length of row {idx+1} does not match size" for col_idx, char in enumerate(row): # 校验字符是否合法 assert char in self.points.values(), f"invalid character '{char}' in row {idx+1}" # 反向映射找到对应的colour_name,比如'.'对应'E' for key, val in self.points.items(): if val == char: self.grid[idx][col_idx] = val break # 重写__str__方法,展示当前棋盘状态 def __str__(self): from string import ascii_uppercase as letters a_letters = list(letters[:self.size]) # 构建输出字符串 output = [' ' + ' '.join(a_letters)] # 行号从size到1倒序 for row_num, row in zip(range(self.size, 0, -1), self.grid): output.append(f"{row_num:2d} {' '.join(row)}") return '\n'.join(output) def get_size(self): return self.size def set_colour(self, coords, colour_name): # 参数校验:colour_name必须是合法的键 assert colour_name in self.points, f"Invalid colour name: {colour_name}" # 解析坐标 alphabetical_coord = coords[0].upper() numerical_coord = coords[1:] # 坐标合法性校验 assert 65 <= ord(alphabetical_coord) <= 90, "column out of range" col_idx = ord(alphabetical_coord) - ord('A') assert 0 <= col_idx < self.size, "column out of range" assert numerical_coord.isdigit(), "invalid numerical coordinate" row_num = int(numerical_coord) assert 1 <= row_num <= self.size, "row out of range" # 转换为网格索引:行号1对应最后一行,所以索引是size - row_num row_idx = self.size - row_num # 更新网格对应位置的符号 self.grid[row_idx][col_idx] = self.points[colour_name] def get_colour(self, coords): # 解析坐标 alphabetical_coord = coords[0].upper() numerical_coord = coords[1:] # 坐标合法性校验 assert 65 <= ord(alphabetical_coord) <= 90, "column out of range" col_idx = ord(alphabetical_coord) - ord('A') assert 0 <= col_idx < self.size, "column out of range" assert numerical_coord.isdigit(), "invalid numerical coordinate" row_num = int(numerical_coord) assert 1 <= row_num <= self.size, "row out of range" row_idx = self.size - row_num # 获取当前符号,反向映射回colour_name current_symbol = self.grid[row_idx][col_idx] for key, val in self.points.items(): if val == current_symbol: return key return None def to_strings(self): # 将网格转换为字符串列表,每行一个字符串 return [''.join(row) for row in self.grid] # 测试代码 print("初始5x5棋盘:") b = Board(5) print(b) print("\n设置B1为W,C1为B,D1为B后:") b.set_colour("B1", "W") b.set_colour("C1", "B") b.set_colour("D1", "B") print(b) print("\n获取C1的颜色:", b.get_colour("C1")) print("\n将C1重置为E后:") b.set_colour("C1", "E") print(b) print("\n从字符串初始化3x3棋盘:") b = Board(3, ["O.O", ".@.", "@O."]) print(b) # 测试to_strings方法 print("\nto_strings结果:", b.to_strings())
关键修改说明
- 在
__init__中新增实例属性self.grid,用于持久化存储棋盘状态,彻底解决无法累积修改的问题。 - 重写
__str__方法,基于self.grid生成当前棋盘的输出,确保打印时展示最新状态。 - 重构
set_colour方法:移除冗余的网格创建和打印代码,只负责参数校验与self.grid的更新;修正坐标到网格索引的转换逻辑。 - 修复
get_colour方法:根据self.grid的实际值反向映射回对应的colour_name,不再返回错误的最后一次设置值。 - 完善
from_strings初始化逻辑,支持从字符串列表创建预设棋盘。
内容的提问来源于stack exchange,提问作者Anne_Music
相关产品推荐
相关产品推荐

