要求
- 使用GUI变成完成猜数字游戏的编写
- 页面布局合理
- 页面上要显示“已猜次数”、“太大、太小或猜中”等相关提示
- 根据个人能力编写单关游戏、或者闯关游戏
- 游戏要有时间限制、并在页面上显示倒计时所剩时间
- 如果是闯关游戏、页面上要显示当前所在灌输
实现思路
使用各种变量记录游戏状态,通过 Swing 创建图形用户界面,并根据用户的输入和游戏逻辑来更新界面和游戏状态。
- 游戏状态管理
- 使用变量
currentRound
记录当前所处的关数。 - 使用变量
currentNumber
保存当前关卡的目标数字。 - 使用变量
totalGuessCount
记录总的猜测次数。 - 使用变量
remainingTime
记录当前倒计时的剩余时间。 - 使用变量
gameStarted
标记游戏是否已经开始。
- 使用变量
- 图形用户界面
- 使用 Swing 库创建窗口,并添加各种 GUI 组件:
titleLabel
: 显示游戏标题。roundLabel
: 显示当前所处的关数和数字范围。guessCountLabel
: 显示总的猜测次数。countdownLabel
: 显示当前倒计时的剩余时间。resultLabel
: 显示游戏结果。guessTextField
: 玩家输入猜测数字的文本框。guessButton
: 玩家点击以猜测数字的按钮。startButton
: 玩家点击以开始游戏的按钮。
- 通过布局管理器(BorderLayout和GridBagLayout)合理地将这些组件排列在窗口上。
- 使用 Swing 库创建窗口,并添加各种 GUI 组件:
- 游戏流程控制
- 在"开始游戏"按钮的点击事件处理中,将
gameStarted
标记为true
、禁用"开始游戏"按钮,并调用startNewRound()
方法开始新的一轮游戏。 - 在
startNewRound()
方法中:- 根据当前关数更新
currentRound
。 - 根据当前关数生成随机目标数字
currentNumber
。 - 重置
remainingTime
为COUNTDOWN_TIME
。 - 更新各个 GUI 组件的状态,如关数、已猜次数、倒计时等。
- 调用
startCountdown()
方法启动倒计时。
- 根据当前关数更新
- 在
startCountdown()
方法中:- 创建一个
Timer
对象,每隔 1 秒执行一次任务。 - 在任务中,递减
remainingTime
并更新倒计时标签。 - 当倒计时结束时,取消定时器,禁用"猜数字"按钮和输入框,并根据当前关卡情况决定是否开始新的一轮。
- 创建一个
- 在"开始游戏"按钮的点击事件处理中,将
- 猜测数字处理
- 在"猜数字"按钮的点击事件处理中:
- 获取玩家输入的猜测数字。
- 更新
totalGuessCount
。 - 判断猜测结果,根据结果更新游戏状态和 GUI 组件:
- 如果猜测正确,则取消定时器,禁用"猜数字"按钮和输入框,显示"闯关成功"的结果。如果还没到最大关数,则开始新的一轮游戏。
- 如果猜测错误,则根据猜大或猜小更新结果标签,并在达到最大猜测次数时结束当前关卡。
- 在"猜数字"按钮的点击事件处理中:
代码详解
- 主函数
main(String[] args)
方法是程序的入口点。- 使用
SwingUtilities.invokeLater()
在事件调度线程中创建并显示窗口,确保 Swing 组件的正确初始化和更新。
- 常量定义
MAX_ROUNDS
定义了最大关数。COUNTDOWN_TIME
定义了每关的倒计时时间。NUMBER_RANGES
定义了每关的数字范围。
- 变量定义
currentRound
记录当前所处的关数。currentNumber
保存当前关卡的目标数字。totalGuessCount
记录总的猜测次数。remainingTime
记录当前倒计时的剩余时间。gameStarted
标记游戏是否已经开始。
- GUI 组件定义
titleLabel
: 显示游戏标题。roundLabel
: 显示当前所处的关数和数字范围。guessCountLabel
: 显示总的猜测次数。countdownLabel
: 显示当前倒计时的剩余时间。resultLabel
: 显示游戏结果。guessTextField
: 玩家输入猜测数字的文本框。guessButton
: 玩家点击以猜测数字的按钮。startButton
: 玩家点击以开始游戏的按钮。
- 构造函数
- 设置窗口的标题、大小、布局管理器等基本属性。
- 创建并添加各个 GUI 组件到对应的面板中。
- 将"开始游戏"按钮添加到底部面板。
- 隐藏窗口并设置默认关闭操作。
- 初始化游戏状态,将"猜数字"按钮和输入框设置为不可用。
- startNewRound() 方法
- 根据当前关数更新
currentRound
。 - 根据当前关数从
NUMBER_RANGES
数组中获取对应的数字范围,并生成随机目标数字currentNumber
。 - 重置
remainingTime
为COUNTDOWN_TIME
。 - 更新各个 GUI 组件的状态,如关数、已猜次数、倒计时等。
- 启动倒计时。
- 根据当前关数更新
- startCountdown() 方法
- 创建一个
Timer
对象,每隔 1 秒执行一次任务。 - 在任务中,递减
remainingTime
并更新倒计时标签。 - 当倒计时结束时,取消定时器,禁用"猜数字"按钮和输入框,并根据当前关卡情况决定是否开始新的一轮。
- 创建一个
- actionPerformed(ActionEvent e) 方法
- 当"开始游戏"按钮被点击时,将
gameStarted
设为true
、禁用"开始游戏"按钮,并调用startNewRound()
方法。 - 当"猜数字"按钮被点击时,获取玩家输入的猜测数字,更新
totalGuessCount
、判断猜测结果,并根据结果更新游戏状态和 GUI 组件。
- 当"开始游戏"按钮被点击时,将
运行结果
实现代码
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class GuessingGame extends JFrame implements ActionListener {
public static void main(String[] args) {
// 使用SwingUtilities.invokeLater()方法在事件调度线程中创建并显示窗口
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GuessingGame game = new GuessingGame();
game.setVisible(true);
}
});
}
// 定义常量,分别代表最大关数、最大猜测次数和倒计时时间
private static final int MAX_ROUNDS = 3;
private static final int COUNTDOWN_TIME = 60;
// 定义每关的数字范围
private static final int[] NUMBER_RANGES = {10, 50, 100};
// 定义游戏相关的变量
private int currentRound;
private int currentNumber;
private int totalGuessCount;
private int remainingTime;
private boolean gameStarted;
// 定义GUI组件
private JLabel titleLabel;
private JLabel roundLabel;
private JLabel guessCountLabel;
private JLabel countdownLabel;
private JLabel resultLabel;
private JTextField guessTextField;
private JButton guessButton;
private JButton startButton;
private Timer timer;
public GuessingGame() {
// 设置窗口标题、默认关闭操作、大小和布局管理器
setTitle("猜数字游戏");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setLayout(new BorderLayout());
// 创建并添加"开始游戏"按钮到底部面板
JPanel bottomPanel = new JPanel();
startButton = new JButton("开始游戏");
startButton.addActionListener(this);
bottomPanel.add(startButton);
add(bottomPanel, BorderLayout.SOUTH);
// 隐藏窗口并设置默认关闭操作和大小
setVisible(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 200);
setLocationRelativeTo(null);
// 创建并添加标题、当前关数、已猜次数、倒计时和结果标签到顶部面板
JPanel topPanel = new JPanel();
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
titleLabel = new JLabel("猜数字游戏");
titleLabel.setFont(titleLabel.getFont().deriveFont(24.0f)); // 放大标题字体
roundLabel = new JLabel("当前处于第1关 (数字范围 0-10)");
guessCountLabel = new JLabel("总猜测次数: 0");
countdownLabel = new JLabel("倒计时: 60");
resultLabel = new JLabel("");
topPanel.add(titleLabel);
topPanel.add(roundLabel);
topPanel.add(guessCountLabel);
topPanel.add(countdownLabel);
topPanel.add(resultLabel);
add(topPanel, BorderLayout.WEST);
// 创建并添加输入框和猜测按钮到中间面板
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 0, 10, 0); // 添加上下边距
guessTextField = new JTextField(10);
guessButton = new JButton("猜数字");
guessButton.addActionListener(this);
gbc.gridy = 0;
centerPanel.add(new JLabel("请输入数字:"), gbc);
gbc.gridy = 1;
centerPanel.add(guessTextField, gbc);
gbc.gridy = 2;
centerPanel.add(guessButton, gbc);
add(centerPanel, BorderLayout.CENTER);
// 初始化游戏状态
gameStarted = false;
guessButton.setEnabled(false);
guessTextField.setEnabled(false);
}
// 开始新的一轮游戏
private void startNewRound() {
currentRound++;
int numberRange = NUMBER_RANGES[currentRound - 1];
currentNumber = new Random().nextInt(numberRange) + 1;
remainingTime = COUNTDOWN_TIME;
// 更新GUI组件的状态
roundLabel.setText("当前处于第" + currentRound + "关 (数字范围 0-" + numberRange + ")");
countdownLabel.setText("倒计时: " + remainingTime);
resultLabel.setText("");
guessTextField.setText("");
guessTextField.setEnabled(true);
guessButton.setEnabled(true);
// 开始倒计时
startCountdown();
}
// 开始倒计时
private void startCountdown() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
remainingTime--;
countdownLabel.setText("倒计时: " + remainingTime);
// 如果倒计时结束,则结束游戏
if (remainingTime == 0) {
timer.cancel();
guessButton.setEnabled(false);
guessTextField.setEnabled(false);
resultLabel.setText("闯关失败!当前数字是: " + currentNumber);
// 如果还没到最大关数,则开始新的一轮
if (currentRound < MAX_ROUNDS) {
startNewRound();
} else {
resultLabel.setText("游戏结束!");
}
}
}
}, 0, 1000);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == startButton) {
// 点击"开始游戏"按钮时,开始新的一轮游戏
gameStarted = true;
startButton.setEnabled(false);
startNewRound();
} else if (e.getSource() == guessButton && gameStarted) {
String guessText = guessTextField.getText();
if (!guessText.isEmpty()) {
int guess = Integer.parseInt(guessText);
totalGuessCount++;
guessCountLabel.setText("总猜测次数: " + totalGuessCount);
// 判断猜测结果,并相应地更新游戏状态
if (guess == currentNumber) {
timer.cancel();
guessButton.setEnabled(false);
guessTextField.setEnabled(false);
resultLabel.setText("恭喜你,猜对了! 进入下一关.");
if (currentRound < MAX_ROUNDS) {
startNewRound();
} else {
resultLabel.setText("游戏结束!恭喜你通过了所有关卡!");
}
} else {
if (guess < currentNumber) {
resultLabel.setText("猜小了,请重试!");
} else {
resultLabel.setText("猜大了,请重试!");
}
}
guessTextField.setText("");
}
}
}
}