WHAT YOU WILL MAKE
Make block navigator BlockNavigator
If you spell the wrong direction once, the navigation may fail. enum circles the answer, record saves the coordinates as a value; movement returns the new position, and the boundaries are explicitly specified by you. Prerequisites: classes, constructors, methods and interfaces. Today I will install armor on the coordinates to prevent them from being changed by mistake, and I will also close the entrance that spells the wrong direction.
Before you start: It is recommended to complete Lessons 19, 21–23 first
- stringPossible misspellings and inconsistent capitalization
- Enumeration typeDelineate legal constants
- nullStill need special treatment
01 / 12
Before starting: predict first, then let the program answer
This chapter uses JDK 21 and does not require the preview function. The story is borrowed from the block world, and the example runs on the ordinary Java console; if the values and rules are course models, they will be clearly stated.
Each common example is a complete independent file, saved according to the file name marked on the box. Place each example in a different folder to avoid duplicate names of auxiliary classes. When the complete project is divided into sections, they are connected sequentially in the same file.
Terminal command: replace the Chinese placeholder with the actual file name and class name
javac -encoding UTF-8 ExampleFile.java
java ExampleClass- Prediction: Write the expected output first, or draw out the changes in references and data.
- Verification: Check line by line after running, and then only change one condition.
- Explanation: Explain whether the results come from Java rules, course contracts, or input data.
02 / 12
New varieties are easy to grow in the direction of the string
When using String to save directions, capitalization, spaces, and spelling may create illegal states. enum fixes the legal answers in a finite set.
- stringPossible misspellings and inconsistent capitalization
- Enumeration typeDelineate legal constants
- nullStill need special treatment
L24Example01.java · Complete independent example
public class L24Example01 {
public static void main(String[] args) {
String facing = "dongg";
System.out.println(facing);
System.out.println(facing.equals("EAST"));
}
}Output
dongg
false03 / 12
enum circles the legal direction
An enumeration is a type. Direction facing can only hold the value declared in Direction or null.
- NORTH / SOUTHNorth-South axis
- EAST / WESTEast-West axis
- UP / DOWNHeight axis
L24Example02.java · Complete independent example
enum Direction {
NORTH(0, 0, -1), SOUTH(0, 0, 1),
EAST(1, 0, 0), WEST(-1, 0, 0),
UP(0, 1, 0), DOWN(0, -1, 0);
final int dx, dy, dz;
Direction(int dx, int dy, int dz) {
this.dx = dx; this.dy = dy; this.dz = dz;
}
}
public class L24Example02 {
public static void main(String[] args) {
Direction facing = Direction.EAST;
System.out.println(facing);
System.out.println(Direction.values().length);
}
}Output
EAST
6BadDirection.java · Intentional error example
enum Direction {
NORTH(0, 0, -1), SOUTH(0, 0, 1),
EAST(1, 0, 0), WEST(-1, 0, 0),
UP(0, 1, 0), DOWN(0, -1, 0);
final int dx, dy, dz;
Direction(int dx, int dy, int dz) {
this.dx = dx; this.dy = dy; this.dz = dz;
}
}
public class BadDirection {
public static void main(String[] args) { Direction d = Direction.DONGG; }
}04 / 12
switch covers the direction branch
switch directly matches enumeration constants, does not require equals, and will not be affected by spelling strings.
- switchCovering all six directions
- null checkEnter pre-branch processing
- Branch resultsReturn the corresponding Chinese name
L24Example03.java · Complete independent example
enum Direction {
NORTH(0, 0, -1), SOUTH(0, 0, 1),
EAST(1, 0, 0), WEST(-1, 0, 0),
UP(0, 1, 0), DOWN(0, -1, 0);
final int dx, dy, dz;
Direction(int dx, int dy, int dz) {
this.dx = dx; this.dy = dy; this.dz = dz;
}
}
public class L24Example03 {
static String label(Direction d) {
if (d == null) return "Not selected";
return switch (d) {
case NORTH -> "North"; case SOUTH -> "South";
case EAST -> "East"; case WEST -> "West";
case UP -> "on"; case DOWN -> "Next";
};
}
public static void main(String[] args) {
System.out.println(label(Direction.NORTH));
System.out.println(label(null));
}
}Output
North
Not selected05 / 12
Enumeration to save displacement data
Enumerations can have fields and constructors. Each direction constant saves its own three-axis increment when created.
| Direction | dx | dy | dz |
|---|---|---|---|
| NORTH | 0 | 0 | -1 |
| SOUTH | 0 | 0 | 1 |
| EAST | 1 | 0 | 0 |
| WEST | -1 | 0 | 0 |
| UP | 0 | 1 | 0 |
| DOWN | 0 | -1 | 0 |
L24Example04.java · Complete independent example
enum Direction {
NORTH(0, 0, -1), SOUTH(0, 0, 1),
EAST(1, 0, 0), WEST(-1, 0, 0),
UP(0, 1, 0), DOWN(0, -1, 0);
final int dx, dy, dz;
Direction(int dx, int dy, int dz) {
this.dx = dx; this.dy = dy; this.dz = dz;
}
}
public class L24Example04 {
public static void main(String[] args) {
Direction d = Direction.NORTH;
System.out.println(d.dx + "," + d.dy + "," + d.dz);
}
}Output
0,0,-106 / 12
record install three-dimensional coordinates
Coordinates mainly carry three values and are compared by content. record will generate component accessors and equality methods; it is suitable for expressing immutable coordinates when components are immutable values such as int.
- record componentSave x, y, z
- x() / y() / z()Automatic accessor
- equalsComparison by component content
L24Example05.java · Complete independent example
record BlockPos(int x, int y, int z) { }
public class L24Example05 {
public static void main(String[] args) {
BlockPos p = new BlockPos(0, 64, 0);
System.out.println(p.x());
System.out.println(p.y());
System.out.println(p.z());
}
}Output
0
64
007 / 12
Move and return to new coordinates
The record component cannot be reassigned at will. The move method calculates and returns a new BlockPos based on the old value.
- startThe old coordinates remain unchanged
- moveCalculate increment by direction
- nextReceive new coordinate object
L24Example06.java · Complete independent example
enum Direction {
NORTH(0, 0, -1), SOUTH(0, 0, 1),
EAST(1, 0, 0), WEST(-1, 0, 0),
UP(0, 1, 0), DOWN(0, -1, 0);
final int dx, dy, dz;
Direction(int dx, int dy, int dz) {
this.dx = dx; this.dy = dy; this.dz = dz;
}
}
record BlockPos(int x, int y, int z) {
BlockPos {
if (y < -64 || y > 319)
throw new IllegalArgumentException("The height should be-64 to 319");
}
BlockPos move(Direction direction, int steps) {
if (direction == null || steps < 0) return this;
long nx = (long) x + (long) direction.dx * steps;
long ny = (long) y + (long) direction.dy * steps;
long nz = (long) z + (long) direction.dz * steps;
int nextY = (int) Math.max(-64L, Math.min(319L, ny));
return new BlockPos(Math.toIntExact(nx), nextY,
Math.toIntExact(nz));
}
String shortText() { return "(" + x + "," + y + "," + z + ")"; }
}
public class L24Example06 {
public static void main(String[] args) {
BlockPos start = new BlockPos(0, 64, 0);
BlockPos next = start.move(Direction.EAST, 5);
System.out.println(start.shortText());
System.out.println(next.shortText());
}
}Output
(0,64,0)
(5,64,0)08 / 12
Equality and Boundaries of Value Objects
record solves the storage and comparison of values, but does not automatically know the legal height or movement rules in a Minecraft class.
- ==Comparison object identity
- equalsCompare component contents
- Height rangeThe lowest is -64, the highest is 319
L24Example07.java · Complete independent example
enum Direction {
NORTH(0, 0, -1), SOUTH(0, 0, 1),
EAST(1, 0, 0), WEST(-1, 0, 0),
UP(0, 1, 0), DOWN(0, -1, 0);
final int dx, dy, dz;
Direction(int dx, int dy, int dz) {
this.dx = dx; this.dy = dy; this.dz = dz;
}
}
record BlockPos(int x, int y, int z) {
BlockPos {
if (y < -64 || y > 319)
throw new IllegalArgumentException("The height should be-64 to 319");
}
BlockPos move(Direction direction, int steps) {
if (direction == null || steps < 0) return this;
long nx = (long) x + (long) direction.dx * steps;
long ny = (long) y + (long) direction.dy * steps;
long nz = (long) z + (long) direction.dz * steps;
int nextY = (int) Math.max(-64L, Math.min(319L, ny));
return new BlockPos(Math.toIntExact(nx), nextY,
Math.toIntExact(nz));
}
String shortText() { return "(" + x + "," + y + "," + z + ")"; }
}
public class L24Example07 {
public static void main(String[] args) {
BlockPos a = new BlockPos(0, 319, 0);
BlockPos b = new BlockPos(0, 319, 0);
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a.move(Direction.UP, 1).shortText());
System.out.println(a.move(Direction.DOWN, 1000).shortText());
}
}Output
false
true
(0,319,0)
(0,-64,0)09 / 12
Challenge Blueprint Block Navigator
The challenge program is called BlockNavigator. Direction saves the three-axis displacement, and BlockPos provides move and shortText.
- Direction and number of stepsSelected Axis of Change
- High clampingStop within range beyond boundary
- Return new valueThe starting point can still be played back
Acceptance sequence
- From (0,64,0), go 5 blocks east, 300 blocks up, and 2 blocks north.
- After height clamping, the end point should be (5,319,-2).
- 1000 blocks down, the result should be (5,-64,-2).
- The starting point remains (0,64,0).
- Negative steps and null direction return to the original position; equals for two objects with the same coordinate is true.
10 / 12
Challenge Implementing Block Navigation
Create a new BlockNavigator.java and compile it using Java 21.
- Start0、64、0
- End point5、319、-2
- Bottom5、-64、-2
BlockNavigator.java · Section 1/2, sequentially connected to the same file
enum Direction {
NORTH(0, 0, -1), SOUTH(0, 0, 1),
EAST(1, 0, 0), WEST(-1, 0, 0),
UP(0, 1, 0), DOWN(0, -1, 0);
final int dx, dy, dz;
Direction(int dx, int dy, int dz) {
this.dx = dx; this.dy = dy; this.dz = dz;
}
}
record BlockPos(int x, int y, int z) {
BlockPos {
if (y < -64 || y > 319)
throw new IllegalArgumentException("The height should be-64 to 319");
}
BlockPos move(Direction direction, int steps) {
if (direction == null || steps < 0) return this;
long nx = (long) x + (long) direction.dx * steps;
long ny = (long) y + (long) direction.dy * steps;
long nz = (long) z + (long) direction.dz * steps;
int nextY = (int) Math.max(-64L, Math.min(319L, ny));
return new BlockPos(Math.toIntExact(nx), nextY,
Math.toIntExact(nz));
}
String shortText() { return "(" + x + "," + y + "," + z + ")"; }
}
public class BlockNavigator {
public static void main(String[] args) {
BlockPos start = new BlockPos(0, 64, 0);BlockNavigator.java · Paragraph 2/2, sequentially connected to the same file
BlockPos next = start.move(Direction.EAST, 5)
.move(Direction.UP, 300).move(Direction.NORTH, 2);
System.out.println("Start=" + start.shortText());
System.out.println("End point=" + next.shortText());
System.out.println("Bottom=" + next.move(Direction.DOWN, 1000).shortText());
System.out.println("The content is the same=" + start.equals(new BlockPos(0, 64, 0)));
}
}Output
Start=(0,64,0)
End point=(5,319,-2)
Bottom=(5,-64,-2)
The content is the same=true11 / 12
Expansion tasks and clearance review
The job must submit at least four boundary tests at the same time, and indicate whether the old objects have changed.
- Boundary casesTop, bottom and adjacent values
- Illegal inputNegative number of steps, empty direction
- Object inspectionWhether the old value is maintained
Third gear operation
- Wooden Pickaxe: Create a Difficulty enum and switch to return EASY NORMAL HARD's monster multiplier.
- Iron pickaxe: Add dx dy dz to Direction to complete movement in six directions.
- Diamond Pickaxe: Design TeleportPoint record, save name and coordinates, and return the new teleport point after offset.
| Self-evaluation | Can | Still need to practice |
|---|---|---|
| I will declare enum | □ | □ |
| I would use record | □ | □ |
| I understand immutable data | □ | □ |
12 / 12
Own acceptance record
Beautiful output is the starting point, and being able to explain boundaries is considered mastery. Select one case each from normal, borderline and error, write down your expectations before running, and leave evidence after running.
| Category | The operation you selected | Check key points |
|---|---|---|
| Normal | A common input or a successful action | Is the result consistent line by line? |
| Border | Range endpoints and adjacent values | Is there one more step or one less thing? |
| Error | Illegal quantity, missing object or bad data | Whether it is explicitly rejected and whether the status is maintained |
- Bug records: triggering conditions, actual phenomena, causes, and minimum repairs.
- Illustrated record: describe the starting point, end point and meaning of each arrow.
- Adaptation record: only change one rule, and modify expectations and tests at the same time.
TAKE IT WITH YOU
Take the lesson offline
The complete lesson, code, diagrams and exercises, in your preferred language.