项目完整代码及运行结果见团队博客:
https://blog.csdn.net/Qiannunu/article/details/135516817?spm=1001.2014.3001.5502
个人负责部分有:
(一)代码部分:包test和包lotterySystem
1.包test
GUI:
该类可以说是整个系统菜单,与各个包都有紧密的联系
创建JFrame 框架类的窗体对象frame变量
使用JButton组件定义并创建按钮:登录、注册、充值、选择号码、查看号码、管理员选项以及指定实例
使用JPanel创建菜单面板buttonPanel,设置面板参数,并将以上按钮放入菜单面板中
对点击后的各个按钮进行动作监听,此时用到JOptionPane类,进行弹窗设置,设置确认型弹窗进行信息的确认,选择型弹窗进行选项的选择
创建2个List,分别用于储存用户已买的号码以及所有用户的购买记录
package test;
import javax.swing.*;
import Admin.Admin;
import Admin.Rolling;
import lotterySystem.Show;
import lotterySystem.Winning;
import record.DataStorage;
import record.NumbersRecord;
import user.NumberSelection;
import user.User;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
public class GUI {
private JFrame frame;
private JButton loginButton;
private JButton registerButton;
private JButton rechargeButton;
private JButton infoButton;
private JButton playButton;
private JButton adminButton;
private JLabel balanceLabel;
private User currentUser;
static List<String> userRecords = DataStorage.readUserRecrods();
static List<String> numbers ;//放已买的号
public GUI() {
frame = new JFrame("彩票抽奖系统");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel buttonPanel = new JPanel();//创建面板
buttonPanel.setLayout(new GridLayout(5, 1));
loginButton = new JButton("登录");
registerButton = new JButton("注册");
rechargeButton = new JButton("充值");
playButton = new JButton("选择号码");
infoButton=new JButton("查看号码");
adminButton = new JButton("管理员");
balanceLabel = new JLabel("余额:0");
buttonPanel.add(loginButton);
buttonPanel.add(registerButton);
buttonPanel.add(rechargeButton);
buttonPanel.add(playButton);
buttonPanel.add(infoButton);
buttonPanel.add(adminButton);
frame.add(buttonPanel, BorderLayout.CENTER);
frame.add(balanceLabel, BorderLayout.SOUTH);
// 登录按钮点击事件
loginButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
userRecords = DataStorage.readUserRecrods();
String username = JOptionPane.showInputDialog("请输入用户名");//确认型对话框
String password = JOptionPane.showInputDialog("请输入密码");
currentUser=DataStorage.loginUser(username, password,userRecords);
if (currentUser != null) {
JOptionPane.showMessageDialog(frame, "登录成功!");
balanceLabel.setText("余额:" + currentUser.getBalance());
numbers = NumbersRecord.fileToList(currentUser.getUsername());
Winning.notifyFirstLogin(numbers, currentUser,userRecords,balanceLabel);
}else {
JOptionPane.showMessageDialog(frame, "登录失败!请检查用户名和密码。");
}
}
});
// 注册按钮点击事件
registerButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String username = JOptionPane.showInputDialog("请输入用户名");
String password = JOptionPane.showInputDialog("请输入密码");
String telnumber = JOptionPane.showInputDialog("请输入电话号码");
int r= DataStorage.register(username, password,telnumber,userRecords);
if (r==0) {
JOptionPane.showMessageDialog(frame, "该用户名已被注册,请选择其他用户名。");
} else if (r==-1) {
JOptionPane.showMessageDialog(frame, "密码必须为6位,请重新输入。");
} else if(r==1){
JOptionPane.showMessageDialog(frame, "注册成功!");
}
}
});
// 充值按钮点击事件
rechargeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (currentUser == null) {
JOptionPane.showMessageDialog(frame, "请先登录");
return;
}
String amountStr = JOptionPane.showInputDialog("请输入充值金额");
double amount = Double.parseDouble(amountStr);
currentUser.recharge(currentUser, amount,userRecords);
balanceLabel.setText("余额:" + currentUser.getBalance());
JOptionPane.showMessageDialog(frame, "充值成功,当前余额为:"+currentUser.getBalance());
}
});
// 选择号码按钮点击事件
playButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 实现选择号码逻辑
if (currentUser == null) {
JOptionPane.showMessageDialog(frame, "请先登录");
return;
}
String numberOfBets = JOptionPane.showInputDialog("投注数:");
int bets = Integer.parseInt(numberOfBets);
List<String> newNumbers=new ArrayList<>();
while(bets!=0) {
String[] options = {"手动选号", "随机选号"};
int choice = JOptionPane.showOptionDialog(null, "请选择选号方式", "选号",
JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE,
null, options, options[0]);//选择型对话框
//进行选择是手动选号还是随机选号
String number =null;
switch (choice) {
case 0: // 手动选号
number= JOptionPane.showInputDialog("请输入号码");
break;
case 1: // 随机选号
number=NumberSelection.selectNumberRandomly();
break;
default:
break;
}
if(NumberSelection.selectNumber(currentUser, number,numbers)!=null) {
newNumbers.add(number);
bets--;
balanceLabel.setText("余额:" + currentUser.getBalance());
if(currentUser.getBalance() < 2.0&&bets!=0) {
JOptionPane.showMessageDialog(null, "余额不足,请先充值");
break;
}
}else{
break;
}
}
//把新买的彩票保存到文件里,并更新numbers列表
NumbersRecord.addNumberstoList(numbers, newNumbers);
NumbersRecord.saveNumbersToFile(currentUser.getUsername(), newNumbers);
DataStorage.updateBalance(currentUser.getUsername(), currentUser.getBalance(),userRecords) ;
}
});
//查看号码按钮点击事件
infoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (currentUser == null) {
JOptionPane.showMessageDialog(frame, "请先登录");
return;
}
Show.displayNumbers(numbers, currentUser);
}
});
// 管理员按钮点击事件
adminButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 弹出输入对话框,让管理员输入和密码
String adminName = JOptionPane.showInputDialog(frame, "请输入管理员用户名:");
String adminPassword = JOptionPane.showInputDialog(frame, "请输入管理员密码:");
// 验证管理员登录
if (Admin.validateAdmin(adminName, adminPassword)) {
JOptionPane.showMessageDialog(frame, "管理员登录成功!");
// 登录成功,弹出选择操作对话框
boolean set=false;
while(!set) {
String[] options = {"手动设置中奖号码", "自动设置中奖号码"};
int selectedOption = JOptionPane.showOptionDialog(frame, "请选择管理员操作:", "管理员操作",
JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
String winningNumber =null;
switch (selectedOption) {
case 0: // 手动设置中奖号码
winningNumber = JOptionPane.showInputDialog(frame, "请输入中奖号码:");
break;
case 1:
//滚动抽奖
Rolling.createJframe(userRecords);
// Rolling.rolling(new Rolling.RollingCallback() {
// @Override
// public void onRollingFinished(String winningNumber) {
// JOptionPane.showMessageDialog(frame, "抽奖结束,中奖号码:"+ winningNumber);
// // 继续执行其他逻辑...
// Show.displayWinnerInfos(Winning.checkWinning(userRecords, winningNumber),winningNumber);
// }
// });
// SwingUtilities.invokeLater(() -> new Lottery());
break;
default:
break;
}
if(winningNumber!=null){
set=Rolling.setWinningNumber(winningNumber);
Show.displayWinnerInfos(Winning.checkWinning(userRecords, winningNumber),winningNumber);
}else{
set=true;
}
}
} else {
JOptionPane.showMessageDialog(frame, "管理员用户名或密码错误!");
}
}
});
frame.setVisible(true);
}
}
2.包lotterySystem
Show:
创建JFrame 框架类的窗体对象frame和dialog变量,窗体对象图形化界面的关闭操作
分别新建面板panel用于显示当前用户的彩票号数和获奖情况和显示当前所有获奖者的获奖信息,均用二维数组储存信息
创建一个图形化表格table,包含相关数据,设置面板的相关信息,并进行可滚动设置
package lotterySystem;
import java.awt.BorderLayout;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import user.User;
public class Show {
//显示当前用户的彩票号数和获奖情况,
public static void displayNumbers(List<String> numbers, User user) {
JFrame frame = new JFrame(user.getUsername() + "'s Numbers and Winning Status");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 设置关闭操作为销毁窗口
JPanel panel = new JPanel(new BorderLayout());
String[] columnNames = {"彩票号码", "获奖情况"};
Object[][] data = new Object[numbers.size()][2];
for (int i=0; i<numbers.size();i++){
String[] numberInfo=numbers.get(i).split(",");
data[i][0] ="【"+ numberInfo[0]+"】";
if(numberInfo.length>1){
if(numberInfo[1].equals("未中奖")){
data[i][1]="未中奖";
}else{
data[i][1]=numberInfo[1];
}
}else{
data[i][1]="未开奖";
}
}
JTable table=new JTable(data,columnNames);//创建可视化表格
JScrollPane scrollPane=new JScrollPane(table);//面板可滚动设置
panel.add(scrollPane,BorderLayout.CENTER);
frame.add(panel);
frame.setSize(400, 300);
frame.setVisible(true);
}
//显示所有获奖者的获奖信息
public static void displayWinnerInfos(List<String> winnerInfos, String winningNumber) {
JFrame dialog = new JFrame("Lottery Winners");
dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 设置关闭操作为销毁窗口
JPanel panel = new JPanel(new BorderLayout());
JLabel winningLabel = new JLabel("中奖号码:" + winningNumber);
panel.add(winningLabel, BorderLayout.NORTH);
String[] columnNames={"用户名","彩票号码","奖项"};
Object[][] data=new Object[winnerInfos.size()][3];
for(int i=0;i<winnerInfos.size();i++) {
String[] minInfo=winnerInfos.get(i).split(",");
data[i][0]=minInfo[0];
data[i][1]=minInfo[1];
data[i][2]=minInfo[2];
}
JTable table=new JTable(data,columnNames);
JScrollPane scrollPane=new JScrollPane(table);
panel.add(scrollPane,BorderLayout.CENTER);
dialog.add(panel);
dialog.setSize(400, 300);
dialog.setVisible(true);
}
}
Winning:
创建ArrayList类winningInfos用于储存用户的中奖号码
使用userInfo变量利用foreach遍历读取用户的抽奖号码,新建List变量numbersOfPerUser将得到的数据与用户名建立联系并写入文件中
使用变量numberInfo,利用foreach遍历读取中奖号码,并储存进combinedNumbers中
使用equal得到中奖号数与奖项、奖项与奖金之间的关系,使用图形化界面,在领取奖金后删除文件中的中奖记录
package lotterySystem;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import record.DataStorage;
import record.NumbersRecord;
import user.User;
public class Winning {
// 比对用户选择的号码是否中奖
public static List<String> checkWinning(List<String> userRecords, String winningNumber) {
List<String> winningInfos = new ArrayList<>();
for (String record : userRecords) {
String[] userInfo = record.split(",");
String perName = userInfo[0];
List<String> numbersOfPerUser = NumbersRecord.fileToList(perName);//遍历读取用户的抽奖号码并写入文件中
List<String> updateNumbers = new ArrayList<>();
for (String perNumber : numbersOfPerUser) {
String[] numberInfo = perNumber.split(",");
StringBuilder combinedNumbers = new StringBuilder();//遍历获取中奖号码
for (int i = 0; i < numberInfo[0].length(); i += 2) {//2个步长
combinedNumbers.append(numberInfo[0], i, i + 2).append(" ");
}
String result = calculateResult(combinedNumbers.toString().trim(), winningNumber);
if (!result.equals("未获奖")) {
String winningInfo = perName + "," + numberInfo[0] + "," + result;
winningInfos.add(winningInfo);
}
updateNumbers.add(numberInfo[0] + "," + result);
}
NumbersRecord.listToFile(updateNumbers, perName);
}
return winningInfos;
}
//计算奖项
private static String calculateResult(String perNumber, String winningNumber) {
int matchedCount = 0;
for (int i = 0; i < perNumber.length(); i += 3) { // 每两位数字之间有一个空格,所以步长为3
if (winningNumber.contains(perNumber.substring(i, i + 2))) {
matchedCount++;
}
}
if (matchedCount == 7) {
return "特等奖";
} else if (matchedCount == 6) {
return "一等奖";
} else if (matchedCount == 5){
return "二等奖";
} else if(matchedCount ==4){
return "三等奖";
} else{
return "未中奖";
}
}
public static void notifyFirstLogin(List<String> numbers, User currentUser,List<String> userRecords,JLabel balanceLabel) {
if(numbers.size()==0){
JOptionPane.showMessageDialog(null, "欢迎来到大乐透抽奖平台,在这里一夜暴富不是梦!!!\n 快去购买你的第一张彩票吧");
return;
}
int totalPrize = 0;
StringBuilder message = new StringBuilder();
boolean flag=true;
for (String number : numbers) {
int price=0;
String[] numberInfo = number.split(",");
if(!numberInfo[1].equals("未中奖")){
message.append(numberInfo[0]).append("\n恭喜用户:").append(currentUser.getUsername()).append(":\n");
message.append("中将号码 ").append(numberInfo[0]).append(" 获得 ").append(numberInfo[1]);
flag=false;
}
if(numberInfo[1].equals("特等奖")){
price=1000;
}else if (numberInfo[1].equals("一等奖")) {
price=500;
} else if (numberInfo[1].equals("二等奖")) {
price=250;
} else if (numberInfo[1].equals("三等奖")){
price=100;
}
// 计算总奖金
totalPrize += price;
}
if(flag){
message.append("很遗憾,您购买的彩票均未获奖!");
}
// 弹出消息框
int option = JOptionPane.showOptionDialog(null, message.toString(), "中将提醒", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
null, new Object[]{"领取奖金"}, "领取");
if (option == 0) { // 如果点击了“领取”按钮
JOptionPane.showMessageDialog(null, "已成功领取总共 " + totalPrize + " 元", "领取成功", JOptionPane.INFORMATION_MESSAGE);
double amount=Double.parseDouble(Integer.toString(totalPrize) );
currentUser.recharge(currentUser, amount,userRecords);
DataStorage.updateBalance(currentUser.getUsername(),currentUser.getBalance(),userRecords);
balanceLabel.setText("余额:" + currentUser.getBalance());// 删除文件里对应号码
File file = new File(currentUser.getUsername()+"_number_records.txt"); // 替换为实际文件路径
try {
List<String> lines = Files.readAllLines(file.toPath());
lines.removeAll(numbers);
Files.write(file.toPath(), lines);
numbers.clear(); // 清空列表里对应号码
} catch (IOException e) {
e.printStackTrace();
}
}
}
// private static boolean isFirstTimeLogin(String username) {
// return true;
// }
}
(二)git代码上传
上传地址为:https://gitee.com/hahaha-hahaha-hahaha-hhh/lotterySystem.git
(三)团队博客的撰写
博客地址:https://blog.csdn.net/Qiannunu/article/details/135516817?spm=1001.2014.3001.5502
个人的反思与总结:
收获:
通过这次彩票抽奖系统的课设,学习了图形化界面,各种弹窗的创建与实现,同时对ArrayList数组有了更加深刻的理解,对Java使用文本文件进行存储数据有了更具体客观的认识。在完成这次课设的过程中,我们碰到了跨包的代码的连接问题,在查csdn和他人博客的过程中该问题得到解决(即使用import关键字,再用调用类的实例化调用里面的方法),提高了我写复杂代码的能力。
不足:
本次课设在测试功能上没有完成,同时对于GUI整体界面来说,还是比较粗糙的,
代码写得比较冗余,可以对分包再进行整改,使其更清楚明白。