3、有一个饮料自动售货机(处理单价为5角钱)的控制处理软件,它的软件规格说明如下:
若投入5角钱的硬币,按下“橙汁”或“啤酒”的按钮,则相应的饮料就送出来。若投入1元钱的硬币,同样也是按“橙汁”或“啤酒”的按钮,则自动售货机在送出相应饮料的同时退回5角钱的硬币。
模拟程序如下:
用因果图法测试该程序,并撰写实验报告。
实验步骤:
①编写程序
package org.example.test1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
public class VendingMachineGUI extends JFrame {
// 组件声明
private JLabel stateLabel = new JLabel("当前状态:");
private JLabel balanceLabel = new JLabel("剩余零钱:5.0元");
private JTextField coinField = new JTextField(10);
private JButton orangeBtn = new JButton("橙汁");
private JButton beerBtn = new JButton("啤酒");
private JButton confirmBtn = new JButton("确定");
private JButton resetBtn = new JButton("复位");
private JTextArea outputArea = new JTextArea(5, 20);
// 状态变量
private double currentCoin = 0;
private String selectedDrink = "";
private double changeAvailable = 5.0; // 初始5元零钱(10个5角)
private boolean canAcceptYuan = true;
public VendingMachineGUI() {
setTitle("自动售货机");
setSize(400, 350);
setDefaultCloseOperation(EXIT_ON_CLOSE);
initComponents();
updateStateDisplay();
}
private void initComponents() {
// 布局设置
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
JPanel inputPanel = new JPanel(new GridLayout(4, 2, 5, 5));
// 状态显示
inputPanel.add(new JLabel("机器状态:"));
inputPanel.add(stateLabel);
inputPanel.add(new JLabel("剩余零钱:"));
inputPanel.add(balanceLabel);
// 投币输入
inputPanel.add(new JLabel("投入金额(0.5/1元):"));
inputPanel.add(coinField);
// 按钮面板
JPanel btnPanel = new JPanel(new GridLayout(1, 2, 5, 5));
btnPanel.add(orangeBtn);
btnPanel.add(beerBtn);
// 操作按钮
JPanel controlPanel = new JPanel(new GridLayout(1, 2, 5, 5));
controlPanel.add(confirmBtn);
controlPanel.add(resetBtn);
// 输出区域
outputArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(outputArea);
// 组装主界面
mainPanel.add(inputPanel, BorderLayout.NORTH);
mainPanel.add(btnPanel, BorderLayout.CENTER);
mainPanel.add(controlPanel, BorderLayout.SOUTH);
add(mainPanel, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
// 事件监听
orangeBtn.addActionListener(e -> selectDrink("橙汁"));
beerBtn.addActionListener(e -> selectDrink("啤酒"));
confirmBtn.addActionListener(e -> processTransaction());
resetBtn.addActionListener(e -> resetTransaction());
coinField.addActionListener(e -> insertCoin());
}
private void updateStateDisplay() {
balanceLabel.setText(String.format("剩余零钱:%.1f元", changeAvailable));
stateLabel.setText(canAcceptYuan ? "【正常运营】" : "【零钱找完】");
coinField.setEnabled(canAcceptYuan);
}
private void insertCoin() {
try {
double coin = Double.parseDouble(coinField.getText());
if (coin == 0.5 || coin == 1.0) {
currentCoin += coin;
outputArea.append("已投入:" + coin + "元\n");
} else {
JOptionPane.showMessageDialog(this, "只接受0.5元或1元硬币");
}
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "请输入有效数字");
}
coinField.setText("");
}
private void selectDrink(String drink) {
selectedDrink = drink;
outputArea.append("已选择:" + drink + "\n");
}
private void processTransaction() {
if (currentCoin < 0.5) {
JOptionPane.showMessageDialog(this, "请至少投入0.5元");
return;
}
if (selectedDrink.isEmpty()) {
JOptionPane.showMessageDialog(this, "请选择饮料");
return;
}
double price = 0.5;
double change = currentCoin - price;
if (change < 0) {
JOptionPane.showMessageDialog(this, "金额不足,还需投入" + (-change) + "元");
return;
}
// 处理找零
if (change > 0) {
if (changeAvailable >= 0.5) {
outputArea.append("找零:" + change + "元\n");
changeAvailable -= change;
} else {
outputArea.append("零钱不足,退还:" + currentCoin + "元\n");
resetTransaction();
return;
}
}
outputArea.append("已发放:" + selectedDrink + "\n");
outputArea.append("交易完成!\n\n");
// 更新状态
if (changeAvailable < 0.5) {
canAcceptYuan = false;
}
resetTransaction();
updateStateDisplay();
}
private void resetTransaction() {
currentCoin = 0;
selectedDrink = "";
coinField.setText("");
updateStateDisplay();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
VendingMachineGUI vm = new VendingMachineGUI();
vm.setVisible(true);
});
}
}
②分析原因与结果
原因:
C1:售货机有零钱找
C2:投入1元硬币
C3:投入5角硬币
C4:押下橙汁按钮
C5:押下啤酒按钮
结果:
E1:售货机”零钱找完”灯亮
E2:退还1元硬币
E3:退还5角硬币
E4:送出橙汁饮料
E5:送出啤酒饮料
中间结点:
11. 投入1元硬币且押下饮料按钮
12. 押下”橙汁”或”啤酒”的按钮
13. 应当找5角零钱并且售货机有零钱找
14. 钱已付清
③画出因果图

④转化为决策表
|
条件与中间节点 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
C1: 有零钱找 |
Y |
Y |
Y |
N |
Y |
N |
Y |
N |
|
C2: 投入1元 |
Y |
Y |
N |
Y |
N |
Y |
N |
N |
|
C3: 投入5角 |
N |
N |
Y |
N |
Y |
N |
N |
N |
|
C4: 按橙汁按钮 |
Y |
N |
Y |
Y |
N |
N |
N |
N |
|
C5: 按啤酒按钮 |
N |
Y |
N |
N |
Y |
N |
N |
N |
|
中间节点11 |
Y |
Y |
N |
N |
N |
N |
N |
N |
|
中间节点12 |
Y |
Y |
Y |
Y |
Y |
Y |
N |
N |
|
中间节点13 |
Y |
N |
Y |
N |
N |
N |
N |
N |
|
中间节点14 |
Y |
Y |
Y |
N |
N |
N |
N |
N |
|
结果 |
|
|
|
|
|
|
|
|
|
E1: 零钱找完灯亮 |
N |
N |
N |
Y |
N |
Y |
N |
N |
|
E2: 退还1元 |
N |
N |
N |
Y |
N |
Y |
N |
N |
|
E3: 退还5角 |
Y |
N |
Y |
N |
N |
N |
N |
N |
|
E4: 送出橙汁 |
Y |
N |
Y |
N |
N |
N |
N |
N |
|
E5: 送出啤酒 |
N |
Y |
N |
N |
Y |
N |
N |
N |
⑤根据决策表设计测试用例,得到测试用例表
|
用例编号 |
输入条件 |
预期结果 |
|
TC-01 |
C1=Y(有零钱),C2=Y(投入1元),C4=Y(按橙汁按钮) |
E3=Y(退5角),E4=Y(送出橙汁) |
|
TC-02 |
C1=Y(有零钱),C2=Y(投入1元),C5=Y(按啤酒按钮) |
E5=Y(送出啤酒) |
|
TC-03 |
C1=Y(有零钱),C3=Y(投入5角),C4=Y(按橙汁按钮) |
E3=Y(退5角无效,需补投),E4=Y(送出橙汁) |
|
TC-04 |
C1=N(无零钱),C2=Y(投入1元),C4=Y(按橙汁按钮) |
E1=Y(零钱找完灯亮),E2=Y(退1元) |
|
TC-05 |
C1=Y(有零钱),C3=Y(投入5角),C5=Y(按啤酒按钮) |
E3=Y(退5角,因金额不足) |
|
TC-06 |
C1=N(无零钱),C2=Y(投入1元),C5=Y(按啤酒按钮) |
E1=Y(零钱找完灯亮),E2=Y(退1元) |
|
TC-07 |
C1=Y(有零钱),C2=N(未投1元),C3=N(未投5角) |
无操作(未投币) |
|
TC-08 |
C1=N(无零钱),C2=N(未投1元),C3=N(未投5角) |
无操作(未投币) |

浙公网安备 33010602011771号