面向对象封装网格画布需分三步:Canvas类封装二维数据与安全操作,formatGrid()统一列宽对齐,BorderRenderer后置添加边框;主流程严格分离输入解析、状态更新、格式化输出三阶段。

用面向对象封装配合流程控制打印标准网格画布,关键在于把“画布”当作一个可管理的对象,把“打印”拆成清晰的职责步骤——不是堆代码,而是让每个类各司其职、每步操作有边界、每次输出可预期。
画布类要封装数据结构与基础行为
定义一个 Canvas 类,内部用二维数组或嵌套 List 存储单元格内容,所有字段设为 private;提供初始化、坐标写入、行列获取等方法,不暴露底层结构。例如:
- 构造器接收宽高,自动用空格初始化整个网格
- setCell(row, col, ch) 方法校验索引范围,防止越界写入
- getRows() / getCols() 返回尺寸,供后续对齐计算使用
- toString() 不直接拼接输出,只返回完整字符串(含换行符),为统一输出留接口
列宽对齐必须前置计算、全局统一
网格变形常因数字/字符位数不一导致,不能靠空格硬分隔。应在打印前完成列宽统计:
- 遍历 Canvas 所有单元格,按列索引统计每列最大字符宽度
- 将对齐逻辑封装进 Canvas 的 formatGrid() 方法:对每行每个单元格调用右对齐格式化(如 Python 的
rjust,Java 的String.format("%" + width + "s", val)) - 确保换行符
\n是每行字符串的结尾部分,而非由 print 自动添加
主流程要分离输入、计算、输出三阶段
避免在循环里混写读取、修改、打印——用分层调度代替大 while 块:
- 第一阶段:接收用户指令(如“画点”“填区域”),解析为坐标和符号
- 第二阶段:调用 Canvas 实例的方法更新状态(如 canvas.setCell(2, 3, 'X'))
- 第三阶段:调用 canvas.formatGrid() 获取格式化后的完整字符串,再由单一主线程执行 print 或 System.out.println
- 不允许多线程直接调用输出语句,否则字符会错位粘连
边框与装饰应后处理、不参与单元格逻辑
真实网格需外框、分隔线,但这些不属于数据单元格本身:
- 在 formatGrid() 返回纯内容字符串后,再由专门的 BorderRenderer 类包裹:加顶行、底行、列间竖线
- 边框字符(如 ┌─┬┐)用 Unicode 或 ASCII 组合,宽度严格匹配内容列宽总和
- 这样改边框样式不影响 Canvas 数据逻辑,也不干扰对齐计算


















