Java 基于枚举命令的2D字符串地图机器人移动功能实现咨询
实现思路推荐
优先采用枚举内置行为+策略模式的实现方案,完全规避冗余分支判断,可维护性是所有方案里最高的,具体落地逻辑如下:
1. 改造FacingDirection枚举内置朝向逻辑
把每个朝向对应的坐标偏移量、左转/右转后的目标朝向直接内置在枚举值里,伪代码示例:
enum FacingDirection { NORTH(0, 1), EAST(1, 0), SOUTH(0, -1), WEST(-1, 0); // 每个朝向对应x轴、y轴的前进偏移量 public final int dx; public final int dy; FacingDirection(int dx, int dy) { this.dx = dx; this.dy = dy; } // 内置左转逻辑 public FacingDirection turnLeft() { return switch(this) { case NORTH -> WEST; case EAST -> NORTH; case SOUTH -> EAST; case WEST -> SOUTH; }; } // 内置右转逻辑 public FacingDirection turnRight() { return switch(this) { case NORTH -> EAST; case EAST -> SOUTH; case SOUTH -> WEST; case WEST -> NORTH; }; } }
后续处理前进时不需要判断当前朝向,直接拿当前朝向的偏移量计算目标坐标即可:Point nextLoc = new Point(currentLocate.x + directionFacing.dx, currentLocate.y + directionFacing.dy)
转向时也不需要分支判断,直接调用对应方法更新朝向:directionFacing = directionFacing.turnLeft()
2. 改造RoboCommand枚举内置指令逻辑
用策略模式把每个指令对应的操作封装在枚举值内,伪代码示例:
enum RoboCommand { FORWARD(robo -> { Point nextLoc = new Point(robo.currentLocate.x + robo.directionFacing.dx, robo.currentLocate.y + robo.directionFacing.dy); // 校验坐标合法性后再更新位置 if(robo.map.isValidLocation(nextLoc)) { robo.currentLocate = nextLoc; } }), LEFT(robo -> robo.directionFacing = robo.directionFacing.turnLeft()), RIGHT(robo -> robo.directionFacing = robo.directionFacing.turnRight()), PICKUP(robo -> { // 未携带物品、当前坐标有可拾取物品时才允许拾取 if(!robo.carryingThing && robo.map.getObject(robo.currentLocate) == MapObject.PICKABLE) { robo.carryingThing = true; robo.map.removeObject(robo.currentLocate); } }), DROP(robo -> { robo.successfullyDropped = false; // 已携带物品、当前坐标允许放置时才允许放下 if(robo.carryingThing && robo.map.canDrop(robo.currentLocate)) { robo.carryingThing = false; robo.map.putObject(robo.currentLocate, MapObject.PICKABLE); robo.successfullyDropped = true; } }); public final Consumer<Robo> action; RoboCommand(Consumer<Robo> action) { this.action = action; } }
最终move方法不需要写任何分支判断,一行代码即可实现:
public void move(RoboCommand command) { command.action.accept(this); }
这个方案完全符合开闭原则,后续新增指令不需要修改现有move方法的代码,只需要新增RoboCommand的枚举实现对应逻辑即可,排查问题也可以直接定位到对应枚举的逻辑,维护成本极低。
备选方案:映射表
如果所用编程语言不支持枚举携带方法,可以用HashMap存储映射关系替代内置逻辑:
- 存储朝向与偏移量的映射:
Map<FacingDirection, int[]> facingOffset - 存储朝向与转向后目标朝向的映射:
Map<FacingDirection, FacingDirection> turnMap - 存储指令与处理逻辑的映射:
Map<RoboCommand, Consumer<Robo>> commandHandler
逻辑和枚举方案一致,仅把内置逻辑改为查表,可维护性远高于分支判断。
不推荐方案
不要使用多层else if堆砌逻辑,后期新增指令或者扩展朝向时需要修改大量分支,容易漏判断触发bug,可维护性极差。
内容的提问来源于stack exchange,提问作者LillyDragon
相关产品推荐
相关产品推荐

