WHAT YOU WILL MAKE
Make a loot simulator LootSimulator
Why don’t the diamonds in the treasure chest appear on time every twenty times? Divide the probability into one hundred grids, fix the random seed and replay the experiment, the prior boundary, and then look at the number and proportion. Prerequisites: if branch, loop, ArrayList and HashMap. Today, the treasure chest will no longer open seven sticks in a row.
Before you start: It is recommended to complete Lessons 25–26 first
- SetSave unique member
- First addChange the collection and return true
- Repeat addNo change, return false
01 / 13
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 / 13
Set only retains non-repeating elements
Set is like an achievement wall. It cares whether there is a certain record, does not care about the number, and does not allow the same content to occupy the position repeatedly.
- SetSave unique member
- First addChange the collection and return true
- Repeat addNo change, return false
L27Example01.java · Complete independent example
import java.util.*;
public class L27Example01 {
public static void main(String[] args) {
Set<String> achievements = new HashSet<>();
System.out.println(achievements.add("First mining"));
System.out.println(achievements.add("First mining"));
System.out.println(achievements.size());
}
}Output
true
false
103 / 13
Add query and delete
Common operations on HashSet revolve around membership. It doesn't have get(0) because collections don't commit to positions.
- containsCheck membership
- removeRemove specified member
- No indexNo get(0)
L27Example02.java · Complete independent example
import java.util.*;
public class L27Example02 {
public static void main(String[] args) {
Set<String> loot = new HashSet<>(Set.of("diamond", "Bread."));
System.out.println(loot.contains("diamond"));
System.out.println(loot.remove("diamond"));
System.out.println(loot.contains("diamond"));
}
}Output
true
true
falseBadSetIndex.java · Intentional error example
import java.util.*;
public class BadSetIndex {
public static void main(String[] args) {
Set<String> loot = new HashSet<>();
System.out.println(loot.get(0));
}
}04 / 13
Set operation is copied first
Set can compare two teams of players or two drop tables. Note that these methods directly modify the collection on which they are called.
- Intersection retainAllOnly keep those on both sides
- Union addAllIncluding any side
- Difference set removeAllLeave only those in the original set
L27Example03.java · Complete independent example
import java.util.*;
public class L27Example03 {
public static void main(String[] args) {
Set<String> a = new HashSet<>(Set.of("diamond", "Bread."));
Set<String> b = Set.of("Bread.", "Iron Ingot");
Set<String> both = new HashSet<>(a); both.retainAll(b);
Set<String> either = new HashSet<>(a); either.addAll(b);
Set<String> onlyA = new HashSet<>(a); onlyA.removeAll(b);
System.out.println(both.equals(Set.of("Bread.")));
System.out.println(either.size());
System.out.println(onlyA.equals(Set.of("diamond")));
System.out.println(a.size());
}
}Output
true
3
true
205 / 13
The upper bound of Random does not include
random.nextInt(100) may get 0 to 99, a total of 100 integers, and will never get 100.
- nextInt(100)Get 0 to 99
- nextInt(6)+1Get 1 to 6
- Upper boundDoes not contain and must be a positive number
L27Example04.java · Complete independent example
import java.util.*;
public class L27Example04 {
public static void main(String[] args) {
Random random = new Random(2026);
boolean inRange = true;
for (int i = 0; i < 100; i++) {
int dice = random.nextInt(6) + 1;
inRange &= dice >= 1 && dice <= 6;
}
System.out.println(inRange);
}
}Output
true06 / 13
The probability interval must be continuous
Arrange 0 to 99 into 100 grids. Each grid can only belong to one reward, and all grids must be assigned.
| Item | Roll range | Chance |
|---|---|---|
| Diamond | 0–4 | 5% |
| Iron | 5–24 | 20% |
| Bread | 25–99 | 75% |
100 possible values: 0 ≤ roll < 100. The value 100 is excluded.
L27Example05.java · Complete independent example
public class L27Example05 {
static String pickRoll(int roll) {
if (roll < 0 || roll >= 100)
throw new IllegalArgumentException("roll should be 0 to 99");
if (roll < 5) return "diamond";
if (roll < 25) return "Iron Ingot";
return "Bread.";
}
public static void main(String[] args) {
for (int roll : new int[]{0, 4, 5, 24, 25, 99})
System.out.println(roll + ": " + pickRoll(roll));
}
}Output
0: diamond
4: diamond
5: Iron Ingot
24: Iron Ingot
25: Bread.
99: Bread.07 / 13
Fixed seed recurrence random test
If the random program is different every time, the bug may teleport like the Enderman. By passing in a fixed seed during testing, the failed process can be replayed.
- Same seedProvide the same starting point
- Same calling sequenceEnsure that the random sequence can be replayed
- Change callSubsequent sequences will be misaligned
L27Example06.java · Complete independent example
import java.util.*;
public class L27Example06 {
public static void main(String[] args) {
Random a = new Random(2026), b = new Random(2026);
boolean same = true;
for (int i = 0; i < 20; i++) same &= a.nextInt(100) == b.nextInt(100);
System.out.println(same);
}
}Output
true08 / 13
Simulate 1000 observation frequencies
5% does not mean that a diamond will come out every 20 times. It means that among a large number of independent attempts, the long-term proportion is usually close to 5%.
- Sum of timesMust be equal to the number of simulations
- Long-term ratioUsually close to the design probability
- An experimentThe quantity does not have to be exactly 50
L27Example07.java · Complete independent example
import java.util.*;
public class L27Example07 {
static String pickRoll(int roll) {
if (roll < 0 || roll >= 100)
throw new IllegalArgumentException("roll should be 0 to 99");
if (roll < 5) return "diamond";
if (roll < 25) return "Iron Ingot";
return "Bread.";
}
static String pickLoot(Random random) {
return pickRoll(java.util.Objects.requireNonNull(random).nextInt(100));
}
static Map<String, Integer> simulate(int trials, long seed) {
if (trials < 0 || trials > 1_000_000)
throw new IllegalArgumentException("The number of simulations should be 0 to 100 Ten thousand");
Random random = new Random(seed);
Map<String, Integer> counts = new HashMap<>();
for (int i = 0; i < trials; i++)
counts.merge(pickLoot(random), 1, Integer::sum);
return counts;
}
public static void main(String[] args) {
Map<String, Integer> counts = simulate(1000, 2026);
int total = counts.values().stream().mapToInt(Integer::intValue).sum();
System.out.println(total);
System.out.println(counts.values().stream().allMatch(n -> n >= 0));
}
}Output
1000
true09 / 13
Use Set to ensure that rewards are not repeated
When three different rewards are drawn continuously, Set can automatically reject repetitions. But if there are only two candidates, requiring three will lead to an infinite loop.
- Target quantityCannot exceed candidate class
- Try upper limitAvoid long cycles
- Number of resultsThe upper limit may not be collected yet
L27Example08.java · Complete independent example
import java.util.*;
public class L27Example08 {
static String pickRoll(int roll) {
if (roll < 0 || roll >= 100)
throw new IllegalArgumentException("roll should be 0 to 99");
if (roll < 5) return "diamond";
if (roll < 25) return "Iron Ingot";
return "Bread.";
}
static String pickLoot(Random random) {
return pickRoll(java.util.Objects.requireNonNull(random).nextInt(100));
}
static Set<String> collectUnique(Random random, int wanted, int limit) {
if (random == null || wanted < 0 || wanted > 3 || limit < 0)
throw new IllegalArgumentException("Check target number and attempt upper limit");
Set<String> result = new HashSet<>();
for (int attempt = 0; result.size() < wanted && attempt < limit; attempt++)
result.add(pickLoot(random));
return result;
}
public static void main(String[] args) {
Set<String> loot = collectUnique(new Random(2026), 3, 100);
System.out.println(loot.size());
System.out.println(collectUnique(new Random(2026), 3, 0).size());
}
}Output
3
010 / 13
Challenge Blueprint Loot Simulator
The challenge program is called LootSimulator. It repeats the simulation with seed 2026 and outputs the three reward quantities, the total number and the number of discovered species.
- Priori boundary0、4、5、24、25、99
- ReseedReplayable in 2026
- Post-check total numberDoes not depend on Set order
Acceptance conditions
- roll can only be 0 to 99.
- There are 5 spaces for diamonds, 20 spaces for iron ingots, and 75 spaces for bread.
- The sum of the three quantities must equal 1000.
- The output of repeated runs with the same seed is consistent.
- There are at most three rewards in a Set.
| Boundary point | Reward |
|---|---|
| 0 | diamond |
| 4 | diamond |
| 5 | Iron Ingot |
| 24 | Iron Ingot |
| 25 | Bread. |
| 99 | Bread. |
11 / 13
loot simulation program
Create a new LootSimulator.java, compile and run using Java 21.
- simulateRepeat the test by seed
- countsCount by reward name
- Stable printingClear diamonds, iron ingots, bread
LootSimulator.java · Section 1/2, sequentially connected to the same file
import java.util.*;
public class LootSimulator {
static String pickRoll(int roll) {
if (roll < 0 || roll >= 100)
throw new IllegalArgumentException("roll should be 0 to 99");
if (roll < 5) return "diamond";
if (roll < 25) return "Iron Ingot";
return "Bread.";
}
static String pickLoot(Random random) {
return pickRoll(java.util.Objects.requireNonNull(random).nextInt(100));
}
static Map<String, Integer> simulate(int trials, long seed) {
if (trials < 0 || trials > 1_000_000)
throw new IllegalArgumentException("The number of simulations should be 0 to 100 Ten thousand");
Random random = new Random(seed);
Map<String, Integer> counts = new HashMap<>();
for (int i = 0; i < trials; i++)
counts.merge(pickLoot(random), 1, Integer::sum);
return counts;
}
static Set<String> collectUnique(Random random, int wanted, int limit) {
if (random == null || wanted < 0 || wanted > 3 || limit < 0)
throw new IllegalArgumentException("Check target number and attempt upper limit");
Set<String> result = new HashSet<>();
for (int attempt = 0; result.size() < wanted && attempt < limit; attempt++)
result.add(pickLoot(random));
return result;LootSimulator.java · Section 2/2, sequentially connected to the same file
}
public static void main(String[] args) {
Map<String, Integer> counts = simulate(1000, 2026);
for (String item : List.of("diamond", "Iron Ingot", "Bread."))
System.out.println(item + "=" + counts.getOrDefault(item, 0));
System.out.println("Total number=" + counts.values().stream()
.mapToInt(Integer::intValue).sum());
System.out.println("Discovery type=" + counts.size());
}
}Output
diamond=43
Iron Ingot=166
Bread.=791
Total number=1000
Discovery type=312 / 13
Expansion tasks and clearance review
The assignment must be accompanied by a probability interval table and boundary test. It is not acceptable to just look random to the naked eye.
- Probability tableEach grid belongs to exactly one kind of reward
- Boundary tableVerify adjacent dividing points
- Analog tableRecording times and frequency
Third gear operation
- Wooden Pickaxe: Make dice from 1 to 6, run 60 times and count each point.
- Iron Pickaxe: Draw three non-duplicate items from the reward pool, and give a prompt when there are insufficient candidates.
- Diamond Pickaxe: Add a guarantee mechanism. If a diamond is not produced for 20 consecutive times, it will be produced next time.
| Self-evaluation | Can | Still need to practice |
|---|---|---|
| I will use Set to remove duplicates | □ | □ |
| I can write down the probability interval | □ | □ |
| I will fix the seed test | □ | □ |
13 / 13
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.