擲骰子是經典的隨機數應用場景。本文循序漸進實現:控制台版核心邏輯、Swing 圖形界面版、多骰子統計分析,並探討隨機數種子、線程安全等進階主題。
import java.util.Random;
public class Dice {
private final int faces; // 面數(標準 6 面)
private final Random random; // 隨機數生成器
public Dice(int faces) {
if (faces < 2) throw new IllegalArgumentException("面數至少為 2");
this.faces = faces;
this.random = new Random(); // 生產環境建議 ThreadLocalRandom
}
/** 擲一次,返回 1~faces */
public int roll() {
return random.nextInt(faces) + 1;
}
/** 擲多次並返回結果列表 */
public List<Integer> rollMultiple(int times) {
List<Integer> results = new ArrayList<>(times);
for (int i = 0; i < times; i++) results.add(roll());
return results;
}
public int getFaces() { return faces; }
}
import java.util.Scanner;
public class DiceGameConsole {
public static void main(String[] args) {
Dice dice = new Dice(6);
Scanner sc = new Scanner(System.in);
System.out.println("=== 擲骰子遊戲 ===");
while (true) {
System.out.print("按 Enter 擲骰子,輸入 q 退出:");
String input = sc.nextLine().trim().toLowerCase();
if ("q".equals(input)) break;
int result = dice.roll();
System.out.printf("🎲 結果:%d%n", result);
// 簡單規則示例
if (result == 6) System.out.println("🎉 擲中最大值!");
}
sc.close();
System.out.println("遊戲結束,再見!");
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DiceGameGUI extends JFrame {
private final Dice dice = new Dice(6);
private final JLabel resultLabel = new JLabel("?", SwingConstants.CENTER);
private final JLabel statsLabel = new JLabel("統計:未開始");
private int count = 0, sum = 0;
public DiceGameGUI() {
setTitle("擲骰子遊戲");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 300);
setLocationRelativeTo(null);
setLayout(new BorderLayout(10, 10));
// 結果顯示區
resultLabel.setFont(new Font("微軟雅黑", Font.BOLD, 120));
resultLabel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
add(resultLabel, BorderLayout.CENTER);
// 底部控制區
JPanel bottom = new JPanel(new BorderLayout(5, 5));
JButton rollBtn = new JButton("擲骰子 (Space)");
rollBtn.setFont(new Font("微軟雅黑", Font.PLAIN, 18));
rollBtn.addActionListener(e -> rollDice());
bottom.add(rollBtn, BorderLayout.CENTER);
bottom.add(statsLabel, BorderLayout.SOUTH);
add(bottom, BorderLayout.SOUTH);
// 鍵盤快捷鍵
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke("SPACE"), "roll");
getRootPane().getActionMap().put("roll", new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) { rollDice(); }
});
}
private void rollDice() {
int result = dice.roll();
resultLabel.setText(String.valueOf(result));
count++;
sum += result;
statsLabel.setText(String.format("統計:共擲 %d 次,總和 %d,平均 %.2f", count, sum, (double) sum / count));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new DiceGameGUI().setVisible(true));
}
}
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
public class DiceStatistics {
public static void main(String[] args) {
int diceCount = 2; // 兩顆骰子
int faces = 6;
int trials = 1_000_000; // 一百萬次模擬
// 使用線程安全的 ThreadLocalRandom
int[] freq = new int[diceCount * faces + 1]; // 索引為點數和
for (int i = 0; i < trials; i++) {
int sum = 0;
for (int d = 0; d < diceCount; d++) {
sum += ThreadLocalRandom.current().nextInt(faces) + 1;
}
freq[sum]++;
}
// 輸出分布
System.out.println("點數和分布(百萬次模擬):");
for (int s = diceCount; s <= diceCount * faces; s++) {
double prob = (double) freq[s] / trials;
String bar = "*".repeat((int) (prob * 200));
System.out.printf("%2d: %6.4f%% %s%n", s, prob * 100, bar);
}
// 理論值對比(兩顆六面骰)
System.out.println("\n理論概率:");
Map<Integer, Double> theory = Map.of(
2, 1/36.0, 3, 2/36.0, 4, 3/36.0, 5, 4/36.0, 6, 5/36.0,
7, 6/36.0, 8, 5/36.0, 9, 4/36.0, 10, 3/36.0, 11, 2/36.0, 12, 1/36.0
);
theory.forEach((k, v) -> System.out.printf("%2d: %.4f%%%n", k, v * 100));
}
}
| 主題 | 要點 |
|---|---|
| 隨機數選擇 | 單線程 Random、多線程 ThreadLocalRandom、安全需求 SecureRandom |
| 種子控制 | new Random(seed) 可復現序列,測試/調試必備 |
| 均勻分布 | nextInt(n) 返回 [0, n-1],骰子需 +1 |
| GUI 線程 | Swing 操作必須在 EDT 中,使用 SwingUtilities.invokeLater |
| 大數據統計 | 基本類型數組 int[] 比 Map 快 10 倍以上 |
Collections.shuffle 洗牌,模擬德州撲克擲骰子遊戲看似簡單,實則涵蓋隨機數、統計學、GUI 事件循環、多線程並發等核心知識。從控制台到 Swing 再到百萬次模擬對比理論分布,層層遞進掌握 Java 隨機應用精髓。