← Java tutorials

LESSON 16 / 40 · FREE TUTORIAL

Project: The Inventory Manager

Comprehensive basic grammar project

110–120 minutesThis chapter uses JDK 21 and does not require the preview function.Basic synthesis

WHAT YOU WILL MAKE

Making an interactive backpack administrator

Can assemble variables, conditions, loops, methods and data into a runnable project; can design menu loops and safe inputs; can complete the four functions of viewing, adding, deleting and searching; can use the test form to accept the backpack administrator. Prerequisites: variables, inputs, conditions, loops, methods and arrays from Lessons 1 to 15. Today is not about learning a new brick, but about building the old brick into a habitable process.

Before you start: It is recommended to complete Lessons 1–15 first

Two sets of arrays, one backpack record
gridItemQuantity
0Wood12
1Cobblestone32
2null0

01 / 16

Before you begin: Put the examples in the right place

This chapter uses JDK 21 and does not require the preview function. A complete program is given for each common example, saved with annotated file names. Multiple examples are placed in their own folders to avoid auxiliary classes with the same name.

Terminal command: Replace the Chinese placeholder with the actual name

javac -encoding UTF-8 ExampleFile.java
java ExampleClass

Class names are case-sensitive. If the complete challenge code is divided into multiple sections, please connect them in the same file in order. Do not create separate classes for the continued sections. Run verification only lists the program output; additional input sequences are provided where input is required.

02 / 16

Project Map and Acceptance Conditions

The knowledge of the first fifteen lessons will be challenged in a team today. The challenge is not the ender dragon, but a console program that keeps asking "please select a menu".

The final program can view, add, delete, and find items, and will not explode in place when encountering incorrect input.

The backpack administrator draws a map before starting work
  1. MenuRepeat receive operation
  2. logarithmic arraySave name and quantity in the same format
  3. Rule methodView, add, delete, search
  4. AcceptanceThree class: normal, boundary and error

Completion standard

  • The menu will be displayed repeatedly, select 0 to exit.
  • The item name and quantity are saved using the same index.
  • Both addition and deletion check the quantity and knapsack bounds.
  • Prepare at least three types of tests: normal, boundary, and error.

03 / 16

Backpack data model

A grid should store the item name and quantity. We haven’t learned about custom item classes at this stage, so we first use two equal-length arrays to pair them.

The same index is a pair of data
Indexitems[i]counts[i]
0Wood12
1Cobblestone32
2null0

L16Example02.java · Complete independent example

public class L16Example02 {
    public static void main(String[] args) {
        String[] items = {"Wood", "Cobblestone", null};
        int[] counts = {12, 32, 0};
        int slot = 1;
        System.out.println(items[slot] + " x" + counts[slot]);
    }
}

Output

Cobblestone x32

04 / 16

Menu cycle control program

Menu-type programs usually do not know how many times the player will operate, so they use while. Each round displays the menu, reads the selection, executes the function, and returns to the entrance.

Menu loop: 0 is the exit
StepAction
1 · Oncerunning = true
2 · Checkrunning is true
3 · If trueDisplay and process
4 · Update; return to step 2Enter the next round

Exit the loop when the condition is false.

The menu is displayed in each round; the exit setting is running = false, and the input is completed and the user exits safely.

L16Example03.java · Complete independent example

public class L16Example03 {
    public static void main(String[] args) {
        java.util.Scanner scanner = new java.util.Scanner(System.in);
        boolean running = true;
        while (running && scanner.hasNextLine()) {
            String choice = scanner.nextLine().trim();
            switch (choice) {
                case "1" -> System.out.println("Open backpack");
                case "0" -> running = false;
                default -> System.out.println("This button does not exist");
            }
        }
        System.out.println("Exited");
    }
}

Output

Open backpack
This button does not exist
Exited

05 / 16

Safe reading of integers

Scanner's nextLine first gets the text and then tries to convert it to an integer. When entering "diamond", the program should give a prompt instead of kicking the player out of the world with an exception.

Enter to pass the checkpoint before entering the backpack
  1. TextRead and remove edge margins
  2. parseIntTry to convert to int
  3. Positive integerAccept only if successful and greater than 0
  4. Illegal-1 Report failure

L16Example04.java · Complete independent example

public class L16Example04 {
    static int positive(String text) {
        try {
            int n = Integer.parseInt(text.trim());
            return n > 0 ? n : -1;
        } catch (NumberFormatException ex) { return -1; }
    }
    public static void main(String[] args) {
        System.out.println(positive(" 12 "));
        System.out.println(positive("diamond"));
        System.out.println(positive("0"));
        System.out.println(positive("999999999999"));
    }
}

Output

12
-1
-1
-1

06 / 16

View backpack

The viewing function requires printing of the index, so ordinary for is more appropriate than enhanced for. Spaces are uniformly displayed as "empty spaces".

Ordinary for gets the grid number and content at the same time
  1. There are itemsPrint name and quantity
  2. VacancyUniform display of vacancies
  3. IndexDisplay 0 to length minus 1
  4. ArrayMust be of equal length and legal pairing

L16Example05.java · Complete independent example

public class L16Example05 {
    static void show(String[] items, int[] counts) {
        for (int i = 0; i < items.length; i++) {
            String text = items[i] == null ? "Vacancy" : items[i] + " x" + counts[i];
            System.out.println(i + ": " + text);
        }
    }
    public static void main(String[] args) {
        String[] items = {"Wood", null};
        int[] counts = {12, 0};
        show(items, counts);
    }
}

Output

0: Wood x12
1: Vacancy

07 / 16

Find items

The search method returns the index, allowing the add, delete and query functions to be reused. Target name checks for null first.

When the search loop encounters the target, it returns to the index
  1. targetExclude null first
  2. equalsCompare by text content
  3. FoundReturn to the first index
  4. Not foundReturn -1

L16Example06.java · Complete independent example

public class L16Example06 {
    static final int MAX_STACK = 64;
    static int find(String[] items, String target) {
        if (target == null) return -1;
        for (int i = 0; i < items.length; i++)
            if (target.equals(items[i])) return i;
        return -1;
    }
    public static void main(String[] args) {
        String[] items = {"Wood", "Cobblestone", null};
        System.out.println(find(items, "Cobblestone"));
        System.out.println(find(items, "diamond"));
        System.out.println(find(items, null));
    }
}

Output

1
-1
-1

08 / 16

Adding and stacking

There are two routes for adding items: when the item already exists in the backpack, increase the quantity; when it does not exist, put it into the first space. Maximum 64 per grid.

First find similar items and then find spaces
  1. Already existsUse existing grid
  2. New itemsFind the first space
  3. remainderFirst check 64 minus the current quantity
  4. SuccessSynchronously write name and quantity

L16Example07.java · Complete independent example

public class L16Example07 {
    static final int MAX_STACK = 64;
    static int find(String[] items, String target) {
        if (target == null) return -1;
        for (int i = 0; i < items.length; i++)
            if (target.equals(items[i])) return i;
        return -1;
    }
    static int empty(String[] items) {
        for (int i = 0; i < items.length; i++)
            if (items[i] == null) return i;
        return -1;
    }
    static boolean add(String[] items, int[] counts, String item, int n) {
        if (item == null || item.isBlank() || n <= 0) return false;
        int slot = find(items, item);
        if (slot < 0) slot = empty(items);
        if (slot < 0 || n > MAX_STACK - counts[slot]) return false;
        items[slot] = item;
        counts[slot] += n;
        return true;
    }
    public static void main(String[] args) {
        String[] items = {"Wood", null};
        int[] counts = {12, 0};
        System.out.println(add(items, counts, "Wood", 5));
        System.out.println(add(items, counts, "Wood", Integer.MAX_VALUE));
        System.out.println(counts[0]);
    }
}

Output

true
false
17

09 / 16

Delete and clear grid

The deletion method first finds the item, and then confirms that the requested quantity is legal. When reduced to 0, the item name must be cleared at the same time.

When the quantity returns to zero, the name and quantity are cleared together.
  1. SearchReject if not found
  2. QuantityGreater than 0 and not exceeding inventory
  3. DeductionModify after passing the inspection
  4. ClearWhen returning to zero, the name also becomes null.

L16Example08.java · Complete independent example

public class L16Example08 {
    static final int MAX_STACK = 64;
    static int find(String[] items, String target) {
        if (target == null) return -1;
        for (int i = 0; i < items.length; i++)
            if (target.equals(items[i])) return i;
        return -1;
    }
    static boolean remove(String[] items, int[] counts, String item, int n) {
        int slot = find(items, item);
        if (slot < 0 || n <= 0 || n > counts[slot]) return false;
        counts[slot] -= n;
        if (counts[slot] == 0) items[slot] = null;
        return true;
    }
    public static void main(String[] args) {
        String[] items = {"Wood"};
        int[] counts = {12};
        System.out.println(remove(items, counts, "Wood", 13));
        System.out.println(counts[0]);
        System.out.println(remove(items, counts, "Wood", 12));
        System.out.println(items[0] + ":" + counts[0]);
    }
}

Output

false
12
true
null:0

10 / 16

Method Division of Labor

main is responsible for menus and processes, and functional methods are responsible for data rules. In this way, when an error occurs, it can be quickly determined which "villager" has delivered the wrong goods.

main works as a dispatcher and method works as a professional villager
  1. Displayshow is responsible for output
  2. Searchfind returns index
  3. Modificationadd and remove maintenance rules
  4. Entermain reads and arranges operations
Acceptance and inspection forms
MethodEnterReturn or effect
showTwo arraysPrint the status of each grid
findItem array, nameIndex or -1
addArray, name, quantitySuccess or failure
removeArray, name, quantitySuccess or failure
positiveA line of textPositive integer or -1

11 / 16

Three types of tests

The project cannot be cleared just by "running it once". Prepare at least one normal test, one boundary test and one error test for each feature.

Test Bench Illustrates Normal Boundaries and Errors
  1. NormalFunction can be completed
  2. BorderJust full, just empty
  3. ErrorIllegal quantity and unknown command
  4. ReturnRerun the original test after repair
Acceptance and inspection forms
FunctionEnterExpected
AddWood 5The quantity increases by 5
AddCobblestone 40 to 32 alreadyReject more than 64
DeleteWood 0Reject data unchanged
SearchDiamonds that do not existReturn -1
MenuxPrompt no button

12 / 16

Project Failure Clinic

When the project becomes larger, don't make random changes based on your feelings. Record the input and phenomenon first, then locate the method responsible for the rule.

From phenomenon to responsible method
  1. Infinite loopExit unchanged condition
  2. Wrong pairingName and quantity are out of sync
  3. Crossing the lineIndex is illegal
  4. ExcessIf the check fails, the data must not be changed

L16Example11.java · Complete independent example

public class L16Example11 {
    public static void main(String[] args) {
        String[] items = {"Wood"};
        int[] counts = {12};
        counts[0] = 0;
        System.out.println(items[0] + " x" + counts[0]);
    }
}

Output

Wood x0

13 / 16

Challenge Blueprint

Challenge The program is called InventoryManager. The full version includes a console menu with repeatable operations, with real implementations of viewing, adding, deleting, and searching. Complete the data method first, and then access the menu.

Four core functions of backpack administrator
  1. Realize firstView and search
  2. ReimplementationAdd and delete
  3. Take menuCommand calls real function
  4. AcceptanceThe two arrays remain unchanged on failure

Acceptance sequence

  • Display initial backpack.
  • Add 5 pieces of wood and confirm the quantity.
  • Add 3 diamonds and confirm that they occupy the space.
  • Delete all cobblestones and confirm that the grid is clear.
  • Attempts to add that result in a quantity exceeding 64 must fail.
Acceptance and inspection forms
RulesLegal rangeFailure performance
Index0 to length-1Do not access array
QuantityGreater than 0Return false
StackingMaximum 64Data remains unchanged
SlotAt least one nullReturn false

14 / 16

Challenge Implementation

Create new InventoryManager.java. The program does not rely on the real Minecraft interface and can be compiled and run directly on the Java 21 console.

The complete program connects five basic grammars into a chain
  1. BasicsArray and search
  2. RulesBalance check and clearing
  3. Menuwhile and switch
  4. EnterException handling and end check

InventoryManager.java · Section 1/3, sequentially connected to the same file

public class InventoryManager {
    static final int MAX_STACK = 64;
    static int find(String[] items, String target) {
        if (target == null) return -1;
        for (int i = 0; i < items.length; i++)
            if (target.equals(items[i])) return i;
        return -1;
    }
    static int empty(String[] items) {
        for (int i = 0; i < items.length; i++)
            if (items[i] == null) return i;
        return -1;
    }
    static boolean add(String[] items, int[] counts, String item, int n) {
        if (item == null || item.isBlank() || n <= 0) return false;
        int slot = find(items, item);
        if (slot < 0) slot = empty(items);
        if (slot < 0 || n > MAX_STACK - counts[slot]) return false;
        items[slot] = item;
        counts[slot] += n;
        return true;
    }
    static boolean remove(String[] items, int[] counts, String item, int n) {
        int slot = find(items, item);
        if (slot < 0 || n <= 0 || n > counts[slot]) return false;
        counts[slot] -= n;
        if (counts[slot] == 0) items[slot] = null;
        return true;

InventoryManager.java · Section 2/3, sequentially connected to the same file

    }
    static void show(String[] items, int[] counts) {
        for (int i = 0; i < items.length; i++) {
            String text = items[i] == null ? "Vacancy" : items[i] + " x" + counts[i];
            System.out.println(i + ": " + text);
        }
    }
    static int positive(String text) {
        try {
            int n = Integer.parseInt(text.trim());
            return n > 0 ? n : -1;
        } catch (NumberFormatException ex) { return -1; }
    }
    public static void main(String[] args) {
        String[] items = {"Wood", "Cobblestone", null, null, null};
        int[] counts = {12, 32, 0, 0, 0};
        java.util.Scanner input = new java.util.Scanner(System.in);
        boolean running = true;
        while (running) {
            System.out.println("1 View 2 Add 3 Delete 4 Search 0 Exit");
            if (!input.hasNextLine()) break;
            String choice = input.nextLine().trim();
            switch (choice) {
                case "0" -> running = false;
                case "1" -> show(items, counts);
                case "2", "3" -> {
                    System.out.println("Item name: ");
                    if (!input.hasNextLine()) { running = false; break; }

InventoryManager.java · Section 3/3, sequentially connected to the same file

                    String item = input.nextLine().trim();
                    System.out.println("Positive integer quantity: ");
                    if (!input.hasNextLine()) { running = false; break; }
                    int n = positive(input.nextLine());
                    boolean ok = choice.equals("2")
                            ? add(items, counts, item, n)
                            : remove(items, counts, item, n);
                    System.out.println(ok ? "Operation successful" : "Operation rejected, backpack unchanged");
                }
                case "4" -> {
                    System.out.println("Item name: ");
                    if (!input.hasNextLine()) { running = false; break; }
                    int slot = find(items, input.nextLine().trim());
                    System.out.println(slot < 0 ? "Not found" : "Index: " + slot);
                }
                default -> System.out.println("This button does not exist");
            }
        }
        System.out.println("Backpack is closed");
    }
}

Output

1 View 2 Add 3 Delete 4 Search 0 Exit
Item name: 
Positive integer quantity: 
Operation successful
1 View 2 Add 3 Delete 4 Search 0 Exit
0: Wood x17
1: Cobblestone x32
2: Vacancy
3: Vacancy
4: Vacancy
1 View 2 Add 3 Delete 4 Search 0 Exit
Backpack is closed

15 / 16

Expansion tasks and stage review

This is the challenge of the basic grammar stage. Submit source code, running results, test tables and a bug record.

The third-level expansion makes the backpack truly look like a project
  1. Wooden PickaxeReproduce basic menu
  2. Iron PickaxeCompletion test and gap statistics
  3. Diamond PickaxeStudying multiple stacks
  4. ReviewRecord data rules

Third gear operation

  • Wooden pickaxe: Press the complete menu to reproduce viewing, adding, and exiting; submit input and output records.
  • Iron Pick: Complete the boundary test of deletion and search, add space statistics, and confirm that incorrect input will not change the data.
  • Diamond Pickaxe: Allows each item to have multiple stacks, automatically looking for grids less than 64.
Acceptance and inspection forms
Self-evaluationCanStill need to practice
I can split project methods□□
I can maintain an array of pairs□□
I can write three types of tests□□

16 / 16

Own acceptance record

Write expectations before running, and record actual results after running. Normal cases show that the program does things; edge cases show that it knows when to stop; error cases show that it rejects unreasonable requests.

Write the evidence into the record
CategoryInput of your choiceExpectation and actual
NormalA common value or a successful operationIs it consistent line by line?
BorderMinimum value, maximum value and adjacent valueIs there one less square and one more step?
ErrorIllegal quantity, missing object or incorrect syntaxExplicitly reject? Is the status maintained?
  • Write a bug as: triggering conditions, phenomena, causes, and minimal repairs.
  • Organize a rule worth remembering and explain it in your own words. Don't just copy the definition.
  • Change an example, keep a record of the test, and let the results prove your understanding.

TAKE IT WITH YOU

Take the lesson offline

The complete lesson, code, diagrams and exercises, in your preferred language.