首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 實現擲骰子遊戲:從基礎邏輯到圖形界面完整教程

     編輯:Java 相關知識

前言

擲骰子是經典的隨機數應用場景。本文循序漸進實現:控制台版核心邏輯、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("遊戲結束,再見!");
    }
}

三、Swing 圖形界面版

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 倍以上

六、擴展練習建議

  1. 撲克牌發牌器:Collections.shuffle 洗牌,模擬德州撲克
  2. 大富翁移動:雙骰子判斷雙倍、進監獄邏輯
  3. Web 版:Spring Boot + WebSocket 實現多人在線擲骰
  4. 物理引擎:引入 JBox2D 模擬真實骰子翻滾動畫

結語

擲骰子遊戲看似簡單,實則涵蓋隨機數、統計學、GUI 事件循環、多線程並發等核心知識。從控制台到 Swing 再到百萬次模擬對比理論分布,層層遞進掌握 Java 隨機應用精髓。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved