一.小组成员及分工
成员名 | 完成部分 | 备注 |
苏晨茜 | 图形化界面,统计并显示获奖情况,测试代码,git上传,团队博客撰写 | 组长 |
刘倩 | 管理员登录及管理员抽奖功能,彩票信息记录 | 组员 |
陈俐文 | 用户注册登录,用户名、密码余额等信息管理,用户抽奖功能 | 组员 |
二.题目及要求
功能要求:模拟福利彩票36选7,实现彩票抽奖与中奖通知功能,需完成如下功能:
1.允许注册用户
用户信息包括用户名,密码,账户金额,电话号码等信息
2.允许注册用户购买彩票
用户能进行手动选号、随机选号,并允许设置投掷数
3.抽奖功能
(1)屏幕上显示抽奖号码的滚动过程,当按”停止“时产生抽奖结果
(2)特等奖:7个号码全中
一等奖:中6个号码
(3)抽出号码后,显示用户名和中奖信息
4.彩票通知功能
抽出号码后用户登录系统,系统显示是否中奖
5.测试功能
(1)设计一自动注册用户(10w个),能够自动买彩票
(2)模拟抽奖,测试抽奖程序的正确性
三.前期调查
四.设计思路
1.功能流程图
2.系统结构图
3.包结构图
五.代码及成果展示
代码已上传git仓库
网址为:https://gitee.com/hahaha-hahaha-hahaha-hhh/lotterySystem.git
(一)代码展示
1.Admin包
该包用于管理员储存信息的管理,及管理员的抽号功能
1)Admin类
储存管理员名及密码,用于管理员登录
package Admin;
public class Admin {
private String adminName;
private String adminPassword;
public Admin(String adminName, String adminPassword) {
this.adminName = adminName;
this.adminPassword = adminPassword;
}
public String getAdminName() {
return adminName;
}
public void setAdminName(String adminName) {
this.adminName = adminName;
}
public String getAdminPassword() {
return adminPassword;
}
public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}
// 验证管理员登录
public static boolean validateAdmin(String adminName, String adminPassword) {
return adminName.equals("admin") && adminPassword.equals("123456");
}
}
2)Rolling类
a. Rolling 模拟滚动并显示滚动号码
b. displayResult 屏幕上显示中奖结果
c. displayRollingNumber 自动生成中奖号码
d. setWinningNumber 判断抽中的号码是否合法
e. createJframe 图形化界面设置
package Admin;
import java.util.Random;
import javax.swing.*;
import lotterySystem.Show;
import lotterySystem.Winning;
import java.awt.BorderLayout;
import java.util.List;
//负责实现彩票抽奖的逻辑,包括生成中奖号码、比对用户选择的号码等
public class Rolling {
//自动生成中奖号码
public interface RollingCallback {
void onRollingFinished(String winningNumber);
}
private static Thread rollingThread;
private static JLabel numberLabel;
private static String winningNumber;
private static volatile boolean rolling = true; // 用于控制是否滚动
public static String rolling(RollingCallback callback) {
JFrame frame = new JFrame("抽奖游戏");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton startButton = new JButton("开始");
JButton stopButton = new JButton("停止");
numberLabel = new JLabel("", SwingConstants.CENTER);
startButton.addActionListener(e -> {
rolling = true;
Thread rollingThread = new Thread(() -> {
while (rolling) {
String number = generateWinningNumber();
displayRollingNumber(number); // 在屏幕上显示滚动中的号码
try {
Thread.sleep(100); // 模拟滚动速度
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});
rollingThread.start();
});
stopButton.addActionListener(e -> {
rolling = false; // 停止滚动
winningNumber = generateWinningNumber(); // 生成中奖号码
displayResult(winningNumber);
if (callback != null) {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
callback.onRollingFinished(winningNumber); // 调用回调函数通知抽奖结束
}
});
if (rollingThread != null && rollingThread.isAlive()) {
try {
rollingThread.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
numberLabel.setText(""); // 清空号码显示
}
JPanel panel=new JPanel();
panel.add(startButton);
panel.add(stopButton);
frame.add(panel, BorderLayout.SOUTH);
frame.add(numberLabel, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setVisible(true);
return winningNumber;
}
public static void displayResult(String winningNumber) {
SwingUtilities.invokeLater(() -> numberLabel.setText("\n中奖号码是:【" + winningNumber.replaceAll("(\\d{2})", "$1,") + "】"));
}// 在屏幕上展示中奖结果
public static void displayRollingNumber(String number) {
SwingUtilities.invokeLater(() -> numberLabel.setText("抽奖中:【" + number.replaceAll("(\\d{2})", "$1,")+ "】"));
}
// 自动生成中奖号码
public static String generateWinningNumber() {
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 7; i++) {
int number = random.nextInt(36) + 1;
sb.append(String.format("%02d", number)); // 使用两位宽度格式化数字,并在前面补0
}
return sb.toString();
}
//判断中将号码是否合法
public static boolean setWinningNumber(String number) {
if(!number.matches("\\d{14}")) {
JOptionPane.showMessageDialog(null, "号码不合法,请重新选择");
return false;}
for (int i = 0; i < number.length(); i += 2) {
String subNum = number.substring(i, i + 2);
int numValue = Integer.parseInt(subNum);
if (numValue < 1 || numValue > 36) {
JOptionPane.showMessageDialog(null, "号码不合法,请重新选择");
return false;
}
}
winningNumber = number;
JOptionPane.showMessageDialog(null, "设置成功,中将号码为:【"+winningNumber.replaceAll("(\\d{2})", "$1,")+ "】");
return true;
}
public static void createJframe(List<String> userRecords){
JFrame frame = new JFrame("抽奖游戏");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton startButton = new JButton("开始");
JButton stopButton = new JButton("停止");
numberLabel = new JLabel("", SwingConstants.CENTER);
startButton.addActionListener(e -> {
rolling = true;
Thread rollingThread = new Thread(() -> {
while (rolling) {
String number = generateWinningNumber();
displayRollingNumber(number); // 在屏幕上显示滚动中的号码
try {
Thread.sleep(100); // 模拟滚动速度
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});
rollingThread.start();
});
stopButton.addActionListener(e -> {
rolling = false; // 停止滚动
winningNumber = generateWinningNumber(); // 生成中奖号码
displayResult(winningNumber);
// if (callback != null) {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JOptionPane.showMessageDialog(frame, "抽奖结束,中奖号码:"+ winningNumber);
Show.displayWinnerInfos(Winning.checkWinning(userRecords, winningNumber),winningNumber);
// 继续执行其他逻辑...
// callback.onRollingFinished(winningNumber); // 调用回调函数通知抽奖结束
// }
if (rollingThread != null && rollingThread.isAlive()) {
try {
rollingThread.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
numberLabel.setText(""); // 清空号码显示
}
});
JPanel panel=new JPanel();
panel.add(startButton);
panel.add(stopButton);
frame.add(panel, BorderLayout.SOUTH);
frame.add(numberLabel, BorderLayout.CENTER);
frame.setSize(300, 200);
frame.setVisible(true);
return;
}
}
2.lotterySystem包
该包用于显示用户的获奖信息,包括当前用户和所有用户,并对比用户号码是否中奖及计算奖项
1)Show类
a. displayNumbers 显示该用户获奖信息
b.displayWinnerInfos 显示所有中奖者的用户信息
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);
}
}
2)Winning类
a. checkWinning 对比用户选择的号码是否中奖
b. calculateResult 计算奖项
c. notifyFirstLogin 图形化界面并计算奖金
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) {
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;
// }
}
3.record包
该包将注册的用户名及用户信息放入文件中,管理并读取用户的信息。同时通过文件记录彩票并管理彩票信息
1)DataStorage类
a. checkCredentials 判断输入的用户名是否符合要求
b. register 进行注册用户
c. saveUser 将用户信息保存到文件
d. loginUser 登录
e. updateBalance 更新用户余额
f. readUserRecrods 读取全部用户信息
g. formatRecord 生成用户信息的字符串
package record;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import user.User;
public class DataStorage {
private static final String USERS_FILE = "users.txt";
public static boolean checkCredentials(String username,List<String> userRecords) {
for (String record : userRecords) {
String[] userInfo = record.split(",");
if (userInfo[0].equals(username)) {
return true;
}
}
return false;
}
//注册
public static int register(String username, String password,String telnumber,List<String> userRecords) {
if (checkCredentials(username,userRecords)) {
System.out.println("该用户名已被注册,请选择其他用户名。");
return 0;
}
if (password.length() != 6) {
System.out.println("密码必须为6位,请重新输入。");
return -1;
}
User newUser = new User(username, password, telnumber);
userRecords.add(formatRecord(newUser));
saveUser(newUser);
String path = username+"_number_records.txt";
File file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
System.out.println("系统错误");
} // 如果文件不存在,则创建新文件
System.out.println("File created successfully.");
}
return 1;
}
// 将新用户信息保存到文件中
public static void saveUser(User user) {
try {
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(USERS_FILE),"UTF-8"));
writer.write(user.getUsername() + "," + user.getPassword() + "," + user.getBalance()+"," + user.getTelnumber());
writer.newLine();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//登录
public static User loginUser(String username,String password,List<String> userRecords){
for(String record:userRecords){
String[] userInfo=record.split(",");
if(userInfo[0].equals(username)&&userInfo[1].equals(password)){
return new User(userInfo[0], userInfo[1], Double.parseDouble(userInfo[2]),userInfo[3]);
}
}
return null;
}
//更新余额
public static void updateBalance(String username, double newBalance,List<String> userRecords) {
List<String> updatedRecords = new ArrayList<>();
for (String record : userRecords) {
String[] userInfo = record.split(",");
if (userInfo[0].equals(username)) {
// 更新特定用户的余额
String updatedRecord = formatRecord(username, userInfo[1], newBalance,userInfo[3]);
updatedRecords.add(updatedRecord);
} else {
updatedRecords.add(record);
}
}
userRecords=updatedRecords;
try (BufferedWriter writer = new BufferedWriter(new FileWriter(USERS_FILE))) {
for (String userRecord : userRecords) {
writer.write(userRecord);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//读取全部用户信息
public static List<String> readUserRecrods(){
List<String> records=new ArrayList<>();
try{
BufferedReader reader=new BufferedReader(
new InputStreamReader(
new FileInputStream(USERS_FILE),"UTF-8"));
String line;
while((line=reader.readLine())!=null){
records.add(line);
}
reader.close();
}catch(IOException e){
e.printStackTrace();
}
return records;
}
//生成某用户信息字符串
private static String formatRecord(String username,String password,double balance,String telnumber){
return username+","+password+","+balance+","+telnumber;
}
private static String formatRecord(User user){
return user.getUsername()+","+user.getPassword()+","+user.getBalance()+","+user.getTelnumber();
}
2)NumbersRecord类
a. addNumberstoList 将新彩票加入number的List容器中
b. saveNumbersToFile 将用户选择的彩票号保存到对应用户的彩票文件中
c. fileToList 将彩票信息从文件中读到List中
d.listToFile 将彩票信息从List中读到文件中,并覆盖原有内容
package record;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
//彩票记录类
//保存彩票号码和中将信息
public class NumbersRecord {
private static final String NUMBER_RECORDS_FILE = "_number_records.txt";
// private static final String WINNING_RECORDS_FILE = "winning_records.txt";
// 将新彩票加入List<String> numbers
public static void addNumberstoList(List<String> numbers, List<String> newNumbers) {
for (String newNumber : newNumbers) {
numbers.add(newNumber + "," + "未获奖");
}
}
// 将新彩票保存到对应用户的彩票文件中
public static void saveNumbersToFile(String username, List<String> newNumbers) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(username + NUMBER_RECORDS_FILE, true))) {
for (String newNumber : newNumbers) {
writer.write(newNumber + "," + "未获奖");
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 将彩票信息从文件中读到List
public static List<String> fileToList(String username){
List<String> numbers = new ArrayList<>();
try{
String path =username+NUMBER_RECORDS_FILE;
BufferedReader reader=new BufferedReader(
new InputStreamReader(
new FileInputStream(path),"UTF-8"));
String line;
while((line=reader.readLine())!=null){
System.out.println(line);
numbers.add(line);
}
reader.close();
}catch(IOException e){
e.printStackTrace();
}
return numbers;
}
// 将彩票信息从List中读到文件,并覆盖原有内容
public static void listToFile(List<String> numbers, String username) {
try {
BufferedWriter writer=new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(username+NUMBER_RECORDS_FILE),"UTF-8"));
for (String number : numbers) {
writer.write(number);
writer.newLine();
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.test包
该包完成菜单及图形化界面的建设以及测试类
1)GUI
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)Test
package test;
public class Test {
public static void main(String[] args) {
new GUI();
}
}
5.User包
该包用于用户选号及用户信息的管理
1)NumberSelection类
a. selectNumberRandomly 用户随机选数
b. selectNumber 用户手动选数
package user;
import java.util.List;
import java.util.Random;
import javax.swing.JOptionPane;
public class NumberSelection {
public static String selectNumberRandomly() {
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 7; i++) {
int number = random.nextInt(36) + 1;
sb.append(String.format("%02d", number)); // 使用两位宽度格式化数字,并在前面补0
}
return sb.toString();
}
public static String selectNumber(User user, String number, List<String> numbers) {
double price = 2.0; // 彩票价格
if (user.getBalance() < price) {
JOptionPane.showMessageDialog(null, "余额不足,请先充值");
return null;
}
if (!isValidNumber(number)) {
JOptionPane.showMessageDialog(null, "号码不合法,请重新选择");
return null;
}
if (numbers.contains(number)) {
JOptionPane.showMessageDialog(null, "号码重复,请重新选择");
return null;
}
user.setBalance(user.getBalance() - price); // 扣除购买彩票的金额
JOptionPane.showMessageDialog(null, "选择号码成功,号码为:" + number);
return number;
}
public static boolean isValidNumber(String number) {
if(!number.matches("\\d{14}"))
return false;
for (int i = 0; i < number.length(); i += 2) {
String subNum = number.substring(i, i + 2);
int numValue = Integer.parseInt(subNum);
if (numValue < 1 || numValue > 36) {
return false;
}
}
return true;
}
}
2)User类
package user;
import java.util.List;
import record.DataStorage;
public class User {
private String username;
private String password;
private double balance;
private String telnumber;
public User(String username, String password,String telnumber) {
this.username=username;
this.password=password;
this.telnumber=telnumber;
this.balance=0.0;
}
public User(String username, String password,double balance,String telnumber) {
this.username=username;
this.password=password;
this.telnumber=telnumber;
this.balance=balance;
}
public User(String username, String password,double balance) {
this.username=username;
this.password=password;
this.balance=balance;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTelnumber() {
return telnumber;
}
public void setTelnumber(String telnumber) {
this.telnumber = telnumber;
}
public void recharge(User user, double amount,List<String> userRecords) {
user.setBalance(user.getBalance() + amount);
DataStorage.updateBalance(user.getUsername(), user.getBalance(),userRecords);
System.out.println("充值成功!当前余额为:" + user.getBalance());
}
}
(二)代码运行结果展示
1.菜单显示:
2.用户注册:
用户登录:
充值:
再充值5元:
选择号码:
手动选号:(选中的号码分别为:22 02 23 25 21 10 21)
随机选号:(选中的号码分别为:29 21 02 06 05 14 04)
3.管理员登录:
手动设置中奖号码:
自动设置中奖号码:
4.获奖:
未获奖:
六.反思与总结
收获:
1.这次课程设计最大的感触就是GUI图形界面的编写,基本上所有的代码语句都需要通过图形界面语句相连接,这是一个具有挑战性的作业,但是在不断学习之后成功将本系统的界面能够比较流畅的显示出来;
2.学会了使用git仓库进行代码的管理,将代码上传到码云,方便程序员对代码间的沟通交流,提高代码的利用率;
不足:
1.对于GUI整体界面来说,还是比较粗糙的;
2.代码比较冗余,接下来可以根据事实逻辑等将冗余的代码分包分类进行整改。
3.代码的安全性不足,可通过将密码设置更加复杂,用密文存储在文档中,增加用户数据的保密性。