36选7福利彩票抽奖系统

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

36选7福利彩票抽奖系统

运行说明

一、环境

  1. jar包运行:电脑安装JDK8及以上,配置好环境变量

二、启动方法

  1. jar启动:在此文件夹打开CMD,输入 java -jar Lottery.jar 回车

三、功能说明

  1. 用户注册:填写用户名、密码、手机号、账户余额注册

  2. 用户登录:登录时自动检测当期开奖,弹窗提示是否中奖

  3. 购彩:支持机选随机号码、手动自选,自定义投注注数,自动扣余额(单注2元)

  4. 抽奖动画:点击开始滚动数字,停止后生成开奖号码;7码全中特等奖,命中6码一等奖

  5. 批量测试:一键生成10万测试用户并自动购彩,控制台输出全部中奖用户ID及中奖等级 四、备注 程序数据存内存,关闭程序所有数据清空;批量生成10万用户会短暂卡顿,属于正常现象。


一、entity/User.java 用户实体

package entity;

import java.util.ArrayList;
import java.util.Set;

public class User {
    private int userId;
    private String username;
    private String password;
    private double balance;
    private String phone;
    // 用户所有彩票订单,每注为7个号码集合
    private ArrayList<Set<Integer>> tickets;

    public User(int userId, String username, String password, double balance, String phone) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.balance = balance;
        this.phone = phone;
        this.tickets = new ArrayList<>();
    }

    // getter & setter
    public int getUserId() { return userId; }
    public void setUserId(int userId) { this.userId = userId; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
    public String getPhone() { return phone; }
    public void setPhone(String phone) { this.phone = phone; }
    public ArrayList<Set<Integer>> getTickets() { return tickets; }
    public void setTickets(ArrayList<Set<Integer>> tickets) { this.tickets = tickets; }
}

二、dao/DataStore.java 全局内存数据库

package dao;

import entity.User;
import java.util.HashMap;
import java.util.Set;

public class DataStore {
    // 单例全局存储
    private static DataStore instance = new DataStore();
    private DataStore(){}
    public static DataStore getInstance(){return instance;}

    // 用户库 key=userId
    public HashMap<Integer, User> userMap = new HashMap<>();
    // 当前开奖号码
    public Set<Integer> drawResult = null;
    // 自增用户ID
    public int nextUserId = 1;
    // 单注彩票价格
    public final int TICKET_PRICE = 2;
}

三util/LotteryUtil.java 号码、中奖工具类

package util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class LotteryUtil {
    private static Random random = new Random();

    /**
     * 生成一注36选7不重复号码
     */
    public static Set<Integer> createRandomTicket(){
        Set<Integer> nums = new HashSet<>();
        while(nums.size() < 7){
            int num = random.nextInt(36)+1;
            nums.add(num);
        }
        return nums;
    }

    /**
     * 排序号码转字符串展示
     */
    public static String sortNumToString(Set<Integer> set){
        ArrayList<Integer> list = new ArrayList<>(set);
        Collections.sort(list);
        StringBuilder sb = new StringBuilder();
        for(int n : list){
            sb.append(String.format("%02d ",n));
        }
        return sb.toString().trim();
    }

    /**
     * 判断一注彩票中奖档位
     * 返回值:0未中奖 1一等奖(6中) 2特等奖(7中)
     */
    public static int checkWinLevel(Set<Integer> ticket, Set<Integer> draw){
        int hit = 0;
        for(int n : ticket){
            if(draw.contains(n)) hit++;
        }
        if(hit ==7) return 2;
        if(hit ==6) return 1;
        return 0;
    }
}

四util/BatchTest.java 批量 10 万用户自动注册购彩测试工具

package util;

import dao.DataStore;
import entity.User;
import java.util.Set;

public class BatchTest {
    private DataStore store = DataStore.getInstance();

    /**
     * 批量注册count个用户,自动为每个用户随机购买3注彩票
     */
    public void batchRegisterAndBuy(int count){
        System.out.println("开始批量生成"+count+"个用户...");
        long start = System.currentTimeMillis();
        for(int i=0;i<count;i++){
            int uid = store.nextUserId++;
            String name = "autoUser_"+uid;
            String pwd = "123456";
            String phone = "138"+String.format("%08d",uid);
            User user = new User(uid,name,pwd,200,phone);
            // 自动买3注机选
            for(int j=0;j<3;j++){
                Set<Integer> ticket = LotteryUtil.createRandomTicket();
                user.getTickets().add(ticket);
            }
            // 扣款3*2=6元
            user.setBalance(user.getBalance()-6);
            store.userMap.put(uid,user);
        }
        long cost = System.currentTimeMillis()-start;
        System.out.println("批量生成完成!耗时"+cost+"ms");
    }

    /**
     * 遍历全部用户,统计所有中奖用户
     */
    public void scanAllWinner(){
        Set<Integer> draw = store.drawResult;
        if(draw == null){
            System.out.println("暂无开奖结果!");
            return;
        }
        System.out.println("===== 全部中奖用户汇总 =====");
        for(User u : store.userMap.values()){
            boolean hasWin = false;
            for(Set<Integer> t : u.getTickets()){
                int level = LotteryUtil.checkWinLevel(t,draw);
                if(level !=0){
                    hasWin = true;
                    String levelStr = level==2 ? "特等奖(7全中)" : "一等奖(6中)";
                    System.out.println("用户ID:"+u.getUserId()+" 用户名:"+u.getUsername()+" 中奖档位:"+levelStr);
                }
            }
        }
    }
}

五view/RegisterFrame.java 注册窗口

package view;

import dao.DataStore;
import entity.User;

import javax.swing.*;
import java.awt.*;

public class RegisterFrame extends JFrame {
    private JTextField tfUser,tfPhone,tfBalance;
    private JPasswordField tfPwd;
    private DataStore store = DataStore.getInstance();

    public RegisterFrame(){
        setTitle("用户注册");
        setSize(320,260);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLayout(new GridLayout(5,2,8,8));
        setResizable(false);

        add(new JLabel("用户名:"));
        tfUser = new JTextField();
        add(tfUser);

        add(new JLabel("密码:"));
        tfPwd = new JPasswordField();
        add(tfPwd);

        add(new JLabel("手机号:"));
        tfPhone = new JTextField();
        add(tfPhone);

        add(new JLabel("初始余额:"));
        tfBalance = new JTextField("100");
        add(tfBalance);

        JButton btnReg = new JButton("注册");
        JButton btnBack = new JButton("返回登录");
        add(btnReg);
        add(btnBack);

        // 注册按钮事件
        btnReg.addActionListener(e->{
            String name = tfUser.getText().trim();
            String pwd = new String(tfPwd.getPassword()).trim();
            String phone = tfPhone.getText().trim();
            double bal;
            try{
                bal = Double.parseDouble(tfBalance.getText().trim());
            }catch (Exception ex){
                JOptionPane.showMessageDialog(this,"余额输入非法!");
                return;
            }
            if(name.isEmpty()||pwd.isEmpty()||phone.isEmpty()){
                JOptionPane.showMessageDialog(this,"信息不能为空!");
                return;
            }
            // 创建用户
            int uid = store.nextUserId++;
            User user = new User(uid,name,pwd,bal,phone);
            store.userMap.put(uid,user);
            JOptionPane.showMessageDialog(this,"注册成功!你的用户ID:"+uid);
            this.dispose();
            new LoginFrame().setVisible(true);
        });

        // 返回登录
        btnBack.addActionListener(e->{
            this.dispose();
            new LoginFrame().setVisible(true);
        });
    }
}

六view/LoginFrame.java 登录窗口(登录自动检测中奖通知)

package view;

import dao.DataStore;
import entity.User;
import util.LotteryUtil;

import javax.swing.*;
import java.awt.*;
import java.util.Set;

public class LoginFrame extends JFrame {
    private JTextField tfUser;
    private JPasswordField tfPwd;
    private DataStore store = DataStore.getInstance();

    public LoginFrame(){
        setTitle("彩票系统登录");
        setSize(300,200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new GridLayout(4,2,8,8));

        add(new JLabel("用户名:"));
        tfUser = new JTextField();
        add(tfUser);

        add(new JLabel("密码:"));
        tfPwd = new JPasswordField();
        add(tfPwd);

        JButton btnLogin = new JButton("登录");
        JButton btnReg = new JButton("注册账号");
        add(btnLogin);
        add(btnReg);

        // 登录事件
        btnLogin.addActionListener(e->{
            String name = tfUser.getText().trim();
            String pwd = new String(tfPwd.getPassword()).trim();
            User loginUser = null;
            for(User u : store.userMap.values()){
                if(u.getUsername().equals(name) && u.getPassword().equals(pwd)){
                    loginUser = u;
                    break;
                }
            }
            if(loginUser == null){
                JOptionPane.showMessageDialog(this,"用户名或密码错误!");
                return;
            }
            // 登录成功,检测中奖
            if(store.drawResult != null){
                StringBuilder msg = new StringBuilder("【中奖通知】\n");
                boolean winFlag = false;
                for(Set<Integer> t : loginUser.getTickets()){
                    int level = LotteryUtil.checkWinLevel(t,store.drawResult);
                    if(level == 2){
                        msg.append("特等奖:7个号码全中\n");
                        winFlag = true;
                    }else if(level ==1){
                        msg.append("一等奖:命中6个号码\n");
                        winFlag = true;
                    }
                }
                if(winFlag){
                    JOptionPane.showMessageDialog(this,msg.toString());
                }else {
                    JOptionPane.showMessageDialog(this,"本期暂无中奖");
                }
            }
            this.dispose();
            // 打开主界面
            new LotteryFrame(loginUser).setVisible(true);
        });

        // 跳转注册
        btnReg.addActionListener(e->{
            this.dispose();
            new RegisterFrame().setVisible(true);
        });
    }
}

七 view/BuyTicketPanel.java 购彩面板(手动 / 机选、多注投注)

package view;

import dao.DataStore;
import entity.User;
import util.LotteryUtil;

import javax.swing.*;
import java.awt.*;
import java.util.HashSet;
import java.util.Set;

public class BuyTicketPanel extends JPanel {
    private User loginUser;
    private DataStore store = DataStore.getInstance();
    private JTextField tfCount;
    private JTextArea taNum;
    private Set<Integer> manualNum = new HashSet<>();

    public BuyTicketPanel(User user){
        this.loginUser = user;
        setLayout(new BorderLayout(10,10));
        setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

        // 顶部信息
        JPanel top = new JPanel();
        top.add(new JLabel("当前账户余额:"+loginUser.getBalance()+"元"));
        add(top,BorderLayout.NORTH);

        // 中部选号区
        JPanel mid = new JPanel(new GridLayout(3,2,5,5));
        mid.add(new JLabel("投注注数:"));
        tfCount = new JTextField("1");
        mid.add(tfCount);

        JButton btnRandom = new JButton("机选号码");
        mid.add(btnRandom);
        JButton btnClear = new JButton("清空手动号码");
        mid.add(btnClear);

        mid.add(new JLabel("当前号码预览:"));
        taNum = new JTextArea(3,20);
        taNum.setEditable(false);
        mid.add(taNum);
        add(mid,BorderLayout.CENTER);

        // 底部按钮
        JPanel bottom = new JPanel();
        JButton btnBuy = new JButton("确认购买");
        bottom.add(btnBuy);
        add(bottom,BorderLayout.SOUTH);

        // 机选按钮
        btnRandom.addActionListener(e->{
            manualNum = LotteryUtil.createRandomTicket();
            taNum.setText(LotteryUtil.sortNumToString(manualNum));
        });

        // 清空号码
        btnClear.addActionListener(e->{
            manualNum.clear();
            taNum.setText("");
        });

        // 购彩按钮
        btnBuy.addActionListener(e->{
            int betNum;
            try{
                betNum = Integer.parseInt(tfCount.getText().trim());
                if(betNum <=0) throw new Exception();
            }catch (Exception ex){
                JOptionPane.showMessageDialog(this,"注数必须为正整数!");
                return;
            }
            int totalCost = betNum * store.TICKET_PRICE;
            if(loginUser.getBalance() < totalCost){
                JOptionPane.showMessageDialog(this,"余额不足!需要"+totalCost+"元");
                return;
            }
            // 扣款
            loginUser.setBalance(loginUser.getBalance()-totalCost);
            // 批量添加彩票
            for(int i=0;i<betNum;i++){
                if(manualNum.size()==7){
                    loginUser.getTickets().add(new HashSet<>(manualNum));
                }else {
                    loginUser.getTickets().add(LotteryUtil.createRandomTicket());
                }
            }
            JOptionPane.showMessageDialog(this,"购买成功!扣除"+totalCost+"元,剩余余额:"+loginUser.getBalance());
        });
    }
}

八view/LotteryFrame.java 主窗口 + 抽奖动画(核心滚动效果)

package view;

import dao.DataStore;
import entity.User;
import util.BatchTest;
import util.LotteryUtil;

import javax.swing.*;
import java.awt.*;
import java.util.Set;

public class LotteryFrame extends JFrame {
    private User loginUser;
    private DataStore store = DataStore.getInstance();
    private JLabel lblRollNum;
    private Thread rollThread;
    private boolean isRolling = false;

    public LotteryFrame(User user){
        this.loginUser = user;
        setTitle("36选7福利彩票系统 | 用户ID:"+user.getUserId());
        setSize(600,400);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // 左侧购彩面板
        BuyTicketPanel buyPanel = new BuyTicketPanel(user);
        add(buyPanel,BorderLayout.WEST);

        // 右侧抽奖面板
        JPanel lotteryPanel = new JPanel(new BorderLayout(10,10));
        lotteryPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

        lblRollNum = new JLabel("等待开奖",SwingConstants.CENTER);
        lblRollNum.setFont(new Font("黑体",Font.BOLD,30));
        lotteryPanel.add(lblRollNum,BorderLayout.CENTER);

        JPanel btnPanel = new JPanel();
        JButton btnStart = new JButton("开始滚动");
        JButton btnStop = new JButton("停止开奖");
        JButton btnBatchTest = new JButton("批量测试(10万用户)");
        JButton btnShowWinner = new JButton("查看全部中奖用户");
        btnPanel.add(btnStart);
        btnPanel.add(btnStop);
        btnPanel.add(btnBatchTest);
        btnPanel.add(btnShowWinner);
        lotteryPanel.add(btnPanel,BorderLayout.SOUTH);

        add(lotteryPanel,BorderLayout.CENTER);

        // 开始滚动
        btnStart.addActionListener(e->{
            if(isRolling) return;
            isRolling = true;
            rollThread = new Thread(()->{
                while(isRolling){
                    Set<Integer> temp = LotteryUtil.createRandomTicket();
                    String numStr = LotteryUtil.sortNumToString(temp);
                    lblRollNum.setText(numStr);
                    try {
                        Thread.sleep(80);
                    } catch (InterruptedException ex) {
                        break;
                    }
                }
            });
            rollThread.start();
        });

        // 停止开奖
        btnStop.addActionListener(e->{
            if(!isRolling) return;
            isRolling = false;
            try {
                rollThread.join();
            } catch (InterruptedException ex) {}
            // 生成正式开奖号码
            Set<Integer> draw = LotteryUtil.createRandomTicket();
            store.drawResult = draw;
            String resStr = LotteryUtil.sortNumToString(draw);
            lblRollNum.setText("本期开奖:"+resStr);
            JOptionPane.showMessageDialog(this,"开奖完成!号码:"+resStr);
        });

        // 批量10万用户测试
        btnBatchTest.addActionListener(e->{
            new Thread(()->{
                BatchTest bt = new BatchTest();
                bt.batchRegisterAndBuy(100000);
                JOptionPane.showMessageDialog(this,"10万用户批量生成完成!");
            }).start();
        });

        // 展示所有中奖用户
        btnShowWinner.addActionListener(e->{
            BatchTest bt = new BatchTest();
            bt.scanAllWinner();
            JOptionPane.showMessageDialog(this,"控制台已输出全部中奖用户ID及档位");
        });
    }
}

九 Main.java 程序入口

import view.LoginFrame;

public class Main {
    public static void main(String[] args) {
        // 启动登录窗口
        new LoginFrame().setVisible(true);
    }
}

总结

本次 Java 课程设计是第一次完整独立开发带图形界面的桌面应用,过程中遇到了不少典型问题。
第一大难题是 Swing 界面卡顿,最开始直接在按钮点击事件里写循环刷新号码,窗口完全卡死,查阅多线程相关知识后,新建子线程单独处理动画循环,才解决界面阻塞问题,也理解了 UI 线程不能执行耗时操作的核心知识点。
第二是号码重复问题,一开始使用 ArrayList 随机添加数字会出现重复号码,改用 HashSet 自动去重,简化了去重逻辑,加深了对 Set 集合特性的理解。
第三是批量生成十万用户时运行缓慢,通过减少 IO 输出、简化对象创建逻辑优化速度,同时学会了使用 System.currentTimeMillis () 统计代码运行耗时。
第四是 Jar 打包失败,最开始未配置主类,打包后无法运行,反复调试 Artifact 配置,最终成功生成可独立运行的 Jar 包,掌握了 Java 项目部署打包流程。
整个开发过程从需求分析、分包设计、编码、调试、打包完整走通,熟练掌握面向对象封装、集合、Swing、多线程等课堂知识点,把书本理论落地成可运行程序,收获很大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值