寻求终端棋盘角色移动代码的更优雅实现方案
Hey Brandon, great start on getting your character moving with WASD! That repetitive if/else chain definitely works, but we can clean it up to make the code more maintainable, scalable, and easy to read. Let's break down a couple of elegant approaches:
The Core Problem with Your Current Code
Right now, you’re repeating almost identical logic for each direction—only the coordinate offsets and direction symbol change. This means if you ever want to add new movement directions (like diagonal movement) or tweak the swap logic, you’d have to update four separate blocks of code, which is error-prone.
Optimized Approach 1: Use an Enum (Type-Safe & Clean)
Enums are perfect here because they let you bundle together all related data for each direction (key, X/Y offsets, direction symbol) in one place.
First, define a Direction enum outside your class:
enum Direction { UP("w", -1, 0, "[ ^ ]"), DOWN("s", 1, 0, "[ v ]"), LEFT("a", 0, -1, "[ < ]"), RIGHT("d", 0, 1, "[ > ]"); private final String inputKey; private final int xOffset; private final int yOffset; private final String displaySymbol; Direction(String inputKey, int xOffset, int yOffset, String displaySymbol) { this.inputKey = inputKey; this.xOffset = xOffset; this.yOffset = yOffset; this.displaySymbol = displaySymbol; } // Helper to find the Direction matching the input key public static Direction fromInput(String input) { for (Direction dir : values()) { if (dir.inputKey.equals(input)) { return dir; } } return null; // Handle invalid input } // Getters for our direction data public int getXOffset() { return xOffset; } public int getYOffset() { return yOffset; } public String getDisplaySymbol() { return displaySymbol; } }
Now rewrite your moveYou method to use this enum—all the repeated logic gets condensed into a single block:
public void moveYou(String wasd, You person) { Direction direction = Direction.fromInput(wasd); if (direction == null) { // Optional: Handle invalid input (e.g., print a message) return; } int currentX = person.getX(); int currentY = person.getY(); int newX = currentX + direction.getXOffset(); int newY = currentY + direction.getYOffset(); // Critical: Add boundary check to avoid array index out-of-bounds errors if (newX < 0 || newX >= ground.length || newY < 0 || newY >= ground[0].length) { System.out.println("Oops, can't move there—you're at the edge of the map!"); return; } // Perform the swap logic once, no repetition! ground[currentX][currentY] = ground[newX][newY]; ground[newX][newY] = person; person.setXandY(newX, newY); person.setDir(direction.getDisplaySymbol()); printMap(); }
Optimized Approach 2: Use HashMaps (Simpler, No Enum)
If you don’t want to use enums, you can store direction data in HashMaps to centralize the configuration:
// Define these as class-level constants private static final Map<String, int[]> OFFSET_MAP = new HashMap<>(); private static final Map<String, String> SYMBOL_MAP = new HashMap<>(); // Initialize the maps once when the class loads static { OFFSET_MAP.put("w", new int[]{-1, 0}); OFFSET_MAP.put("s", new int[]{1, 0}); OFFSET_MAP.put("a", new int[]{0, -1}); OFFSET_MAP.put("d", new int[]{0, 1}); SYMBOL_MAP.put("w", "[ ^ ]"); SYMBOL_MAP.put("s", "[ v ]"); SYMBOL_MAP.put("a", "[ < ]"); SYMBOL_MAP.put("d", "[ > ]"); } public void moveYou(String wasd, You person) { if (!OFFSET_MAP.containsKey(wasd)) { return; // Invalid input } int[] offset = OFFSET_MAP.get(wasd); String dirSymbol = SYMBOL_MAP.get(wasd); int currentX = person.getX(); int currentY = person.getY(); int newX = currentX + offset[0]; int newY = currentY + offset[1]; // Same boundary check as before if (newX < 0 || newX >= ground.length || newY < 0 || newY >= ground[0].length) { System.out.println("Can't move out of bounds!"); return; } // Swap logic (only written once) ground[currentX][currentY] = ground[newX][newY]; ground[newX][newY] = person; person.setXandY(newX, newY); person.setDir(dirSymbol); printMap(); }
Why These Improvements Matter
- Less repetition: All movement logic lives in one place, so you only ever need to fix or update it once.
- Scalability: Adding a new direction (like diagonal
qfor up-left) just requires adding a new enum entry or map entry—no changes to the core movement code. - Readability: Anyone looking at the code can instantly see what each direction does, without digging through four
if/elseblocks. - Safety: The boundary check prevents crashes from moving outside the map, which your original code doesn’t handle.
内容的提问来源于stack exchange,提问作者Brandon Finley

