JAVA简单游戏项目--斗地主游戏及登录注册界面 源码经过换皮优化 文章附源码直接拿

斗地主游戏项目文档

本文档介绍斗地主游戏的设计要求、数据模型、简单测试、视图设计、GUI程序、程序发布等方面的内容,以提供一个全面而清晰的说明。以下是各个部分的详细介绍。

设计要求

斗地主游戏的设计要求如下:

1:实现一个登录注册界面,包括点击生成随机验证码 验证账密等功能

 添加更改密码 查看已注册用户功能 

2. 实现一个经典的斗地主游戏,包括发牌、抢地主、出牌、倒计时等功能。

3. 支持单人参与游戏,玩家进行操作与两位人机对战。

数据模型

在斗地主游戏中,需要设计以下数据模型:

一: 玩家:包括玩家的姓名、手牌等信息。

二:牌:包括牌的4种花色、大小王与13种序号等信息,进行权重排序。通过牌型比较判断玩家是否能出牌。

三:地主:表示当前的地主玩家,获得初始的3张手牌,率先出牌。

Common类主要包括对扑克牌进行排序、判断牌型、移动牌等功能;

1. 判断牌型:根据输入的扑克牌列表,判断其牌型,如单牌、对子、三张牌等,并返回对应的牌型。

2. 移动牌:提供了移动扑克牌的方法,可以实现带有动画效果的扑克牌移动,牌点击后向上移动20像素,再次点击向下移动20像素

3. 排序:利用扑克牌的牌面大小和花色进行排序,将输入的扑克牌列表按照一定规则进行排序。

4. 重新摆放牌的顺序:根据游戏界面和需要摆放的集合,将扑克牌重新摆放到指定的位置。

登录界面类

LoginJFrame类中,首先定义了一些成员变量,比如按钮、文本框等,以及一个保存用户信息的列表(userDatabase)

注册新用户后会创建User类的一个新对象,用户对象实际存储在UserdatabaseList表中

构造方法LoginJFrame(),用于初始化界面、添加组件,并将界面显示出来。

public LoginJFrame(){
   
//初始化界面
   
initJFrame();
   
//初始化组件,在页面中添加内容
   
initView();
   
//让当前界面显示出来
   
this.setVisible(true);
}

initJFrame() 设置窗体的大小、标题

public void initJFrame(){

    //设置宽高 标题 关闭后停止运行 居中 置顶 取消默认布局

    this.setSize(640,420);

    this.setTitle("斗地主游戏登录 Version:1.0.0 ");

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    this.setLocationRelativeTo(null);

    this.setAlwaysOnTop(true);

    this.setLayout(null);

}

initView() 添加各种组件,比如标签、输入框、按钮

注意创建完标签,账号密码输入框,验证码,4个按钮后添加组件到面板中,由于本类已经继承了JFrame类,直接用this.getContentPane().add(组件),将组件添加到当前面板

GameJFrame类是一个基于 Java 编写的斗地主游戏的界面部分。它使用了 Swing 库来创建游戏窗口,并包含了玩家操作的按钮、玩家手牌的展示以及倒计时等功能。

在 `GameJFrame` 类中,首先定义了游戏界面的一些基本属性和组件,然后在构造函数中进行了界面的初始化工作。其中通过多线程的方式进行了牌的初始化(备牌、洗牌、发牌),以及播放游戏音乐的操作,避免阻塞主线程。界面初始化完成后,展示了抢地主和不抢地主两个按钮,以及倒计时文本等。

通过 `initView()` 方法,添加了抢地主和不抢地主两个按钮,以及出牌和不要的按钮,同时创建了玩家前的提示文字倒计时显示。

通用功能类

Common是一个扑克牌游戏中的通用功能类,其中包括了对扑克牌进行排序、判断牌型、移动牌等功能。

首先是jugdeType方法,用于判断牌型,包括单张、对子、三不带、炸弹、顺子、连对、飞机、四带二等类型。

然后是move方法,实现了移动牌的动画效果。

接着是order方法,利用牌的价值对集合中的牌进行排序。

rePosition方法用于重新摆放牌的顺序,包括左、中、右三个位置。

验证码类  CodeUtil.getCode()会返回一个 4个英文字符与一个数字字符 拼接成的字符串

          位置随机

创建一个ArrayList对象 可以动态改变大小的数组

 根据ascii码即字节码中 a – z 与 A – Z的关系

向list表中依次添加大小写共52个字母  例如:aA - zZ

利用Random类 对象的nextInt()方法 向其传入list表长 生成一个随机字母在表中的索引

表.get(索引) 获取索引对应字母

写在for循环中,遍历4次拼接字符串

利用Random类 对象的nextInt()方法 向其传入10 范围即为0-9

1个随机数字暂时拼接在4个随机字母后面

将字符串 转换 为字符数组

定义一个索引 利用Random类 对象的nextInt()方法 向其传入 字符数组长度

空水杯交换 空水杯 = 数字字符;数字字符 = 随机索引对应英文字符;英文字符 = 空水杯

public static String getCode(){

    //创建一个集合;

    ArrayList<Character> list = new ArrayList<>(); //52 索引范围0-51

    //添加字母 a - z  A - Z

    for(int i=0;i<26;i++){

        list.add((char)('a' + i));//类型转换为字符97-a 65-A

        list.add((char)('A' + i));

    }

    //打印集合

    //System.out.println(list);

    //生成4个随机字母

    String result = "";

    Random r = new Random();

    for(int i=0;i<4;i++){

        int randomIndex = r.nextInt(list.size());

        result = result + list.get(randomIndex);

    }

    //长度为4的随机字符串 return result;

    //基础上拼接数字0-9

    int number = r.nextInt(10);

    //把随机数字拼接到result后面

    result = result + number;

    //把字符串变成字符数组

    char[] chars = result.toCharArray();

    //生成一个字符数组长度的随机索引

    int index = r.nextInt(chars.length);

    //末索引4上的数字字符与随机索引上的字符交换 使数字出现在索引0-4的任何位置

    char temp = chars[4];

    chars[4] = chars[index];

    chars[index] = temp;

    //字符数组变回字符串

    String code = new String(chars);

    return code;

}

出牌类型类

  枚举类型enum表示一组相关的常量

方便判断出牌是否为同一类型

简单测试

在开发过程中,可以进行简单的测试来验证代码的正确性和可靠性。例如,可以模拟发牌、抢地主、出牌等操作,并检查结果是否符合预期。

测试过程发现音频无法播放,搜索错误得知不支持applet工具类,wav,m4p等音乐格式也不支持。于是导入javazoom下的Player类,构造方法抛出异常与文件无法找到的错误,为使音乐在不同路径下都能播放,采取项目路径与相对路径拼接为字符串,再将字符串传入文件输入流,并预先用缓冲流加载,while(true)死循环使音频不断播放。

又由于音频是在登录成功后跳转的游戏界面播放,因此在游戏界面类构造函数处调用播放音频方法,为避免音乐播放阻塞主程序,将音频播放构造方法添加到异步加载中,

   打包后cmd java -jar 包名或直接双击运行jar包,发现游戏界面的扑克与地主图片图片消失,原来是由于默认从src文件夹下找图片,img文件夹不在src里,可以在打包之后把图片文件夹img粘贴至jar包路径处,成功显示图片

  打包后音频也无法播放,还是路径原因,原先拼接成的绝对路径改为相对路径,jar包位置创建文件夹src再放置音乐文件夹。

总结,都是取决于原先的图片或音频的路径

视图设计

为了提供友好的用户界面,需要进行视图设计。可以使用图形用户界面(GUI)来展示游戏进程和玩家操作。例如,可以设计游戏桌面、玩家手牌区域、出牌区域等。视图设计应符合用户习惯,界面简洁明了,方便玩家操作。

GUI程序

基于视图设计,可以开发一个GUI程序来实现斗地主游戏。GUI程序应当具备以下功能:

1. 显示游戏进程和玩家操作。

2. 提供按钮或其他交互元素,用于玩家进行抢地主、出牌等操作。

3. 实时更新游戏状态,包括当前玩家、地主玩家、出牌倒计时等信息。

4. 提供可视化的手牌区域和出牌区域,方便玩家查看和选择牌。

5.注册后可以更改密码 或者 查看已注册用户列表

程序发布

完成代码开发后,可以将程序进行发布,以供用户下载和使用。程序发布应包括以下步骤:

对代码进行编译和打jar包,生成可执行文件。

通过以上介绍,详细阐述了斗地主游戏代码的设计要求、数据模型、简单测试、视图设计、GUI程序、程序发布等方面的内容。希望这个文档能够对开发斗地主游戏的学习和游玩有所帮助

源码分为game main util music四个包

game包下新建类

Common类

import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import lynu.rookie.main.Poker;


public class Common {
    //四种花色:1"黑桃",2"红桃",3"梅花",4"方块"
    //序号5 大小王
    //十三种序号:"3","4","5","6","7","8","9","10","J","Q","K","A"序号1,"2"序号2

    //判断牌型
    public static PokerType jugdeType(ArrayList<Poker> list) {
        int len = list.size();
        if (len <= 4) {
            if (list.size() > 0 && Common.getValue(list.get(0)) == Common.getValue(list.get(len - 1))) {
                switch (len) {
                    case 1:
                        return PokerType.c1;
                    case 2:
                        return PokerType.c2;
                    case 3:
                        return PokerType.c3;
                    case 4:
                        return PokerType.c4;
                }
            }

            if (len == 2 && Common.getColor(list.get(1)) == 5)
                return PokerType.c2;
            if (len == 4 && ((Common.getValue(list.get(0)) == Common.getValue(list.get(len - 2)))
                    || Common.getValue(list.get(1)) == Common.getValue(list.get(len - 1))))
                return PokerType.c31;
            else {
                return PokerType.c0;
            }
        }
        if (len >= 5) {
            PokerIndex pokerIndex = new PokerIndex();
            ArrayList<ArrayList<Integer>> indexList = pokerIndex.indexList;
            for (int i = 0; i < 4; i++) {
                indexList.add(new ArrayList<>());
            }
            Common.getMax(pokerIndex, list);
            if (indexList.get(2).size() == 1 && indexList.get(1).size() == 1 && len == 5)
                return PokerType.c32;
            if (indexList.get(3).size() == 1 && len == 6)
                return PokerType.c411;
            if (indexList.get(3).size() == 1 && indexList.get(1).size() == 2 && len == 8)
                return PokerType.c422;
            if ((Common.getColor(list.get(0)) != 5) && (indexList.get(0).size() == len)
                    && (Common.getValue(list.get(0)) - Common.getValue(list.get(len - 1)) == len - 1))
                return PokerType.c123;
            if (indexList.get(1).size() == len / 2 && len % 2 == 0 && len / 2 >= 3
                    && (Common.getValue(list.get(0)) - Common.getValue(list.get(len - 1)) == (len / 2 - 1)))
                return PokerType.c112233;
            if (indexList.get(2).size() == len / 3 && (len % 3 == 0)
                    && (Common.getValue(list.get(0)) - Common.getValue(list.get(len - 1)) == (len / 3 - 1)))
                return PokerType.c111222;
            if (indexList.get(2).size() == len / 4 && (indexList.get(2).get(len / 4 - 1)
                    - (indexList.get(2).get(0)) == len / 4 - 1))
                return PokerType.c11122234;

            if (indexList.get(2).size() == len / 5 && indexList.get(2).size() == len / 5
                    && ((indexList.get(2).get(len / 5 - 1)) - (indexList.get(2).get(0)) == len / 5
                    - 1))
                return PokerType.c1112223344;

        }
        return PokerType.c0;
    }


    //移动牌(有移动的动画效果) 形参 当前移动牌 目标起始索引 结束索引
    public static void move(Poker poker, Point from, Point to) {
        if (to.x != from.x) {
            double k = (1.0) * (to.y - from.y) / (to.x - from.x);
            double b = to.y - to.x * k;
            int flag = 0;
            if (from.x < to.x)
                flag = 20;
            else {
                flag = -20;
            }
            for (int i = from.x; Math.abs(i - to.x) > 20; i += flag) {
                double y = k * i + b;

                poker.setLocation(i, (int) y);
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        poker.setLocation(to);
    }


    //利用牌的价值,将集合中的牌进行排序
    public static void order(ArrayList<Poker> list) {
        //此时可以改为lambda表达式
        Collections.sort(list, new Comparator<Poker>() {
            @Override
            public int compare(Poker o1, Poker o2) {
                //获取花色
                //1-黑桃 2-红桃 3-梅花 4-方块 5-大小王
                int a1 = Integer.parseInt(o1.getName().substring(0, 1));
                int a2 = Integer.parseInt(o2.getName().substring(0, 1));

                //获取牌上的数字,同时也是牌的价值
                //1-A ... 11-J 12-Q 13-K
                int b1 = Integer.parseInt(o1.getName().substring(2));
                int b2 = Integer.parseInt(o2.getName().substring(2));

                //计算牌的价值,利用牌的价值进行排序
                //牌上的数字在3~10之间,价值就是3~10
                //3:价值3
                //...
                //10:价值10
                //J:价值11
                //Q:价值12
                //K:价值13
                //A:1 + 20 = 21
                //2:2 + 30 = 32
                //小王:1 + 100 = 101
                //大王:2 + 100 = 102

                //计算大小王牌的价值
                if (a1 == 5) {
                    b1 += 100;
                }
                if (a2 == 5) {
                    b2 += 100;
                }

                //计算A的价值
                if (b1 == 1) {
                    b1 += 20;
                }
                if (b2 == 1) {
                    b2 += 20;
                }
                //计算2的价值
                if (b1 == 2) {
                    b1 += 30;
                }
                if (b2 == 2) {
                    b2 += 30;
                }

                //倒序排列
                int flag = b2 - b1;

                //如果牌的价值一样,则按照花色排序
                if (flag == 0) {
                    return a2 - a1;
                } else {
                    return flag;
                }
            }
        });
    }

    //重新摆放牌的顺序 游戏界面 要摆放的集合 标记0 1 2 左 中 右
    public static void rePosition(GameJFrame m, ArrayList<Poker> list, int flag) {
        Point p = new Point();
        if (flag == 0) {
            p.x = 50;
            p.y = (450 / 2) - (list.size() + 1) * 15 / 2;
        }
        if (flag == 1) {
            p.x = (800 / 2) - (list.size() + 1) * 21 / 2;
            p.y = 450;
        }
        if (flag == 2) {
            p.x = 700;
            p.y = (450 / 2) - (list.size() + 1) * 15 / 2;
        }
        int len = list.size();
        for (int i = 0; i < len; i++) {
            Poker poker = list.get(i);
            Common.move(poker, poker.getLocation(), p);
            m.container.setComponentZOrder(poker, 0);
            if (flag == 1)
                p.x += 21;
            else
                p.y += 15;
        }
    }


    public static int getScore(ArrayList<Poker> list) {
        int count = 0;
        for (int i = 0, len = list.size(); i < len; i++) {
            Poker poker = list.get(i);
            if (poker.getName().substring(0, 1).equals("5")) {
                count += 5;
            }
            if (poker.getName().substring(2).equals("2")) {
                count += 2;
            }
        }
        return count;
    }

    public static int getColor(Poker poker) {
        return Integer.parseInt(poker.getName().substring(0, 1));
    }

    public static int getValue(Poker poker) {
        int i = Integer.parseInt(poker.getName().substring(2));
        if (poker.getName().substring(2).equals("2"))
            i += 13;
        if (poker.getName().substring(2).equals("1"))
            i += 13;
        if (Common.getColor(poker) == 5)
            i += 2;
        return i;
    }

    public static void getMax(PokerIndex pokerIndex, ArrayList<Poker> list) {
        int count[] = new int[14];
        for (int i = 0; i < 14; i++)
            count[i] = 0;

        for (int i = 0, len = list.size(); i < len; i++) {
            if (Common.getColor(list.get(i)) == 5)// 王
                count[13]++;
            else
                count[Common.getValue(list.get(i)) - 1]++;
        }
        ArrayList<ArrayList<Integer>> indexList = pokerIndex.indexList;
        for (int i = 0; i < 14; i++) {
            switch (count[i]) {
                case 1:
                    indexList.get(0).add(i + 1);
                    break;
                case 2:
                    indexList.get(1).add(i + 1);
                    break;
                case 3:
                    indexList.get(2).add(i + 1);
                    break;
                case 4:
                    indexList.get(3).add(i + 1);
                    break;
            }
        }
    }

    public static Model getModel(ArrayList<Poker> list, int[] orders) {
        ArrayList list2 = new ArrayList<>(list);
        Model model = new Model();
        for (int i = 0; i < orders.length; i++)
            showOrders(orders[i], list2, model);
        return model;
    }

    public static void get123(ArrayList<Poker> list, Model model) {
        ArrayList<Poker> del = new ArrayList<>();
        if (list.size() > 0 && (Common.getValue(list.get(0)) < 7 || Common.getValue(list.get(list.size() - 1)) > 10))
            return;
        if (list.size() < 5)
            return;
        ArrayList<Poker> list2 = new ArrayList<>();
        ArrayList<Poker> temp = new ArrayList<>();
        ArrayList<Integer> integers = new ArrayList<>();
        for (Poker poker : list2) {
            if (integers.indexOf(Common.getValue(poker)) < 0) {
                integers.add(Common.getValue(poker));
                temp.add(poker);
            }
        }
        Common.order(temp);
        for (int i = 0, len = temp.size(); i < len; i++) {
            int k = i;
            for (int j = i; j < len; j++) {
                if (Common.getValue(temp.get(i)) - Common.getValue(temp.get(j)) == j - i) {
                    k = j;
                }
            }
            if (k - i >= 4) {
                String s = "";
                for (int j = i; j < k; j++) {
                    s += temp.get(j).getName() + ",";
                    del.add(temp.get(j));
                }
                s += temp.get(k).getName();
                del.add(temp.get(k));
                model.a123.add(s);
                i = k;
            }
        }
        list.removeAll(del);
    }

    public static void getTwoTwo(ArrayList<Poker> list, Model model) {
        ArrayList<String> del = new ArrayList<>();
        ArrayList<String> l = model.a2;
        if (l.size() < 3)
            return;
        Integer s[] = new Integer[l.size()];
        for (int i = 0, len = l.size(); i < len; i++) {
            String[] name = l.get(i).split(",");
            s[i] = Integer.parseInt(name[0].substring(2, name[0].length()));
        }
        for (int i = 0, len = l.size(); i < len; i++) {
            int k = i;
            for (int j = i; j < len; j++) {
                if (s[i] - s[j] == j - i)
                    k = j;
            }
            if (k - i >= 2) {
                String ss = "";
                for (int j = i; j < k; j++) {
                    ss += l.get(j) + ",";
                    del.add(l.get(j));
                }
                ss += l.get(k);
                model.a112233.add(ss);
                del.add(l.get(k));
                i = k;
            }
        }
        l.removeAll(del);
    }

    public static void getPlane(ArrayList<Poker> list, Model model) {
        ArrayList<String> del = new ArrayList<>();
        ArrayList<String> l = model.a3;
        if (l.size() < 2)
            return;
        Integer s[] = new Integer[l.size()];
        for (int i = 0, len = l.size(); i < len; i++) {
            String[] name = l.get(i).split(",");
            s[i] = Integer.parseInt(name[0].substring(2, name[0].length()));
        }
        for (int i = 0, len = l.size(); i < len; i++) {
            int k = i;
            for (int j = i; j < len; j++) {
                if (s[i] - s[j] == j - i)
                    k = j;
            }
            if (k != i) {
                String ss = "";
                for (int j = i; j < k; j++) {
                    ss += l.get(j) + ",";
                    del.add(l.get(j));
                }
                ss += l.get(k);
                model.a111222.add(ss);
                del.add(l.get(k));
                i = k;
            }
        }
        l.removeAll(del);
    }

    public static void getBoomb(ArrayList<Poker> list, Model model) {
        ArrayList<Poker> del = new ArrayList<>();
        if (list.size() < 1)
            return;
        if (list.size() >= 2 && Common.getColor(list.get(0)) == 5 && Common.getColor(list.get(1)) == 5) {
            model.a4.add(list.get(0).getName() + "," + list.get(1).getName());
            del.add(list.get(0));
            del.add(list.get(1));
        }
        if (Common.getColor(list.get(0)) == 5 && Common.getColor(list.get(1)) != 5) {
            del.add(list.get(0));
            model.a1.add(list.get(0).getName());
        }
        list.removeAll(del);
        for (int i = 0, len = list.size(); i < len; i++) {
            if (i + 3 < len && Common.getValue(list.get(i)) == Common.getValue(list.get(i + 3))) {
                String s = list.get(i).getName() + ",";
                s += list.get(i + 1).getName() + ",";
                s += list.get(i + 2).getName() + ",";
                s += list.get(i + 3).getName();
                model.a4.add(s);
                for (int j = i; j <= i + 3; j++)
                    del.add(list.get(j));
                i = i + 3;
            }
        }
        list.removeAll(del);
    }

    public static void getThree(ArrayList<Poker> list, Model model) {
        ArrayList<Poker> del = new ArrayList<>();
        for (int i = 0, len = list.size(); i < len; i++) {
            if (i + 2 < len && Common.getValue(list.get(i)) == Common.getValue(list.get(i + 2))) {
                String s = list.get(i).getName() + ",";
                s += list.get(i + 1).getName() + ",";
                s += list.get(i + 2).getName();
                model.a3.add(s);
                for (int j = i; j <= i + 2; j++)
                    del.add(list.get(j));
                i = i + 2;
            }
        }
        list.removeAll(del);
    }

    public static void getTwo(ArrayList<Poker> list, Model model) {
        ArrayList<Poker> del = new ArrayList<>();
        for (int i = 0, len = list.size(); i < len; i++) {
            if (i + 1 < len && Common.getValue(list.get(i)) == Common.getValue(list.get(i + 1))) {
                String s = list.get(i).getName() + ",";
                s += list.get(i + 1).getName();
                model.a2.add(s);
                for (int j = i; j <= i + 1; j++)
                    del.add(list.get(j));
                i = i + 1;
            }
        }
        list.removeAll(del);
    }

    public static void getSingle(ArrayList<Poker> list, Model model) {
        ArrayList<Poker> del = new ArrayList<>();
        for (int i = 0, len = list.size(); i < len; i++) {
            model.a1.add(list.get(i).getName());
            del.add(list.get(i));
        }
        list.removeAll(del);
    }

    public static void hideCards(ArrayList<Poker> list) {
        for (int i = 0, len = list.size(); i < len; i++) {
            list.get(i).setVisible(false);
        }
    }

    public static int checkCards(ArrayList<Poker> c, ArrayList<ArrayList<Poker>> current, GameJFrame m) {
        ArrayList<Poker> currentlist;
        if (m.time[0].getText().equals("不要"))
            currentlist = current.get(2);
        else
            currentlist = current.get(0);
        PokerType cType = Common.jugdeType(c);
        PokerType cType2 = Common.jugdeType(currentlist);
        if (cType != PokerType.c4 && c.size() != currentlist.size())
            return 0;
        if (cType != PokerType.c4 && Common.jugdeType(c) != Common.jugdeType(currentlist)) {

            return 0;
        }
        if (cType == PokerType.c4) {
            if (c.size() == 2)
                return 1;
            if (cType2 != PokerType.c4) {
                return 1;
            }
        }

        if (cType == PokerType.c1 || cType == PokerType.c2 || cType == PokerType.c3 || cType == PokerType.c4) {
            if (Common.getValue(c.get(0)) <= Common.getValue(currentlist.get(0))) {
                return 0;
            } else {
                return 1;
            }
        }
        if (cType == PokerType.c123 || cType == PokerType.c112233 || cType == PokerType.c111222) {
            if (Common.getValue(c.get(0)) <= Common.getValue(currentlist.get(0)))
                return 0;
            else
                return 1;
        }
        if (cType == PokerType.c31 || cType == PokerType.c32 || cType == PokerType.c411 || cType == PokerType.c422
                || cType == PokerType.c11122234 || cType == PokerType.c1112223344) {
            List<Poker> a1 = Common.getOrder2(c);
            List<Poker> a2 = Common.getOrder2(currentlist);
            if (Common.getValue(a1.get(0)) < Common.getValue(a2.get(0)))
                return 0;
        }
        return 1;
    }

    public static ArrayList getOrder2(List<Poker> list) {
        ArrayList<Poker> list2 = new ArrayList<>(list);
        ArrayList<Poker> list3 = new ArrayList<>();
        int len = list2.size();
        int a[] = new int[20];
        for (int i = 0; i < 20; i++)
            a[i] = 0;
        for (int i = 0; i < len; i++) {
            a[Common.getValue(list2.get(i))]++;
        }
        int max = 0;
        for (int i = 0; i < 20; i++) {
            max = 0;
            for (int j = 19; j >= 0; j--) {
                if (a[j] > a[max])
                    max = j;
            }

            for (int k = 0; k < len; k++) {
                if (Common.getValue(list2.get(k)) == max) {
                    list3.add(list2.get(k));
                }
            }
            list2.remove(list3);
            a[max] = 0;
        }
        return list3;
    }

    public static void showOrders(int i, ArrayList<Poker> list, Model model) {
        switch (i) {
            case 1:
                Common.getSingle(list, model);
                break;
            case 2:
                Common.getTwo(list, model);
                Common.getTwoTwo(list, model);
                break;
            case 3:
                Common.getThree(list, model);
                Common.getPlane(list, model);
                break;
            case 4:
                Common.getBoomb(list, model);
                break;
            case 5:
                Common.get123(list, model);
                break;
        }
    }
}

class PokerIndex {
    ArrayList<ArrayList<Integer>> indexList = new ArrayList<>();
}

游戏界面GameJFrame类

import javazoom.jl.decoder.JavaLayerException;
import lynu.rookie.main.Poker;
import music.MusicPlayer;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;

public class GameJFrame extends JFrame implements ActionListener{

    //获取界面中的隐藏容器
    public static Container container = null;

    //抢地主和不抢两个按钮 初始
    JButton[]  landlord= new JButton[2];  //null

    //管理出牌和不要两个按钮
    JButton[] publishCard = new JButton[2];

    int lordFlag;
    int turn;

    //抢地主后的地主图标
    JLabel lord;

    //集合嵌套集合 大集合嵌套三个小集合
    //小集合装每一个玩家当前要出的牌
    //索引 0:左边电脑  1:中间玩家  2:右边电脑
    ArrayList<ArrayList<Poker>> currentList = new ArrayList<>();

    //小集合中装着每一个玩家的手牌
    ArrayList<ArrayList<Poker>> playerList = new ArrayList<>();

    //底牌
    ArrayList<Poker> lordList = new ArrayList<>();

    //牌库,装所有的牌
    ArrayList<Poker> pokerList = new ArrayList();

    //3个玩家前方的出牌倒计时提示
    JTextField time[] = new JTextField[3];

    //用户操作 多线程
    PlayerOperation po;

    boolean nextPlayer = false;

    public GameJFrame(){
        //设置任务栏地主图标
        setIconImage(Toolkit.getDefaultToolkit().getImage("image\\lord.png"));

        //设置窗口的基本属性,包括标题、大小、关闭模式、窗口是否可以调节、背景颜色等
        initJFrame();
        //添加添加界面中需要的组件,如抢地主和不抢地主按钮、玩家前的提示文字等
        initView();
        //先显示界面再发牌,发牌动画在界面展示前无法展示
        this.setVisible(true);

        //初始化牌 备-洗-发
        //initCard()方法放在新的线程中执行,可以实现在后台进行牌局的初始化操作
        new Thread(this::initCard).start();
        //进行牌局的初始化,包括创建三个集合装三个玩家要出的牌、展示抢地主和不抢地主两个按钮、展示倒计时文本等
        initGame();

        //播放音乐
        playMusic();

    }

    //由于登陆成功后游戏界面打开,音乐播放器阻塞游戏界面
    //将音乐播放器放在异步加载的线程中,以免阻塞主线程游戏界面的加载
    private void playMusic(){
        Thread thread = new Thread(() -> {
            //播放音乐
            try {
                new MusicPlayer();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (JavaLayerException e) {
                e.printStackTrace();
            }
        });
        thread.start();
    }
    //初始化 备-洗-发牌
    public void initCard(){
        //准备牌
        //把所有牌添加到牌盒cardList中 4个花色 13个序号 大小王当作第5种花色存两张
        for(int i=1;i<=5;i++){
            for(int j=1;j<=13;j++){
                if(i==5 && j>2){
                    break;
                }else{
                    //中央牌盒显示为背面
                    Poker poker = new Poker(this,i + "-" + j,false);
                    poker.setLocation(350,150);

                    pokerList.add(poker);
                    container.add(poker);
                }
            }
        }

        //洗牌
        Collections.shuffle(pokerList);

        //创建三个数据集合装三个玩家的牌,放到大集合管理
        ArrayList<Poker> player0 = new ArrayList<>();
        ArrayList<Poker> player1 = new ArrayList<>();
        ArrayList<Poker> player2 = new ArrayList<>();

        for(int i = 0;i<pokerList.size();i++){
            //获取当前遍历的牌
            Poker poker = pokerList.get(i);

            //给地主发三张牌
            if(i<=2){
                //移动牌 获取牌当前位置 设置新的坐标
                Common.move(poker,poker.getLocation(),new Point(270+(75*i),10));
                //把底牌添加到集合中
                lordList.add(poker);
                continue;
            }
            //给三个玩家发牌
            if(i%3 == 0){
                Common.move(poker,poker.getLocation(),new Point(50,60+i*5));
                player0.add(poker);
            }else if(i%3 == 1){
                Common.move(poker,poker.getLocation(),new Point(180+i*7,470));
                player1.add(poker);
                //自己的牌展示为正面
                poker.turnFront();
            }else if(i%3 == 2){
                Common.move(poker,poker.getLocation(),new Point(700,i*5));
                player2.add(poker);
            }
            //把三个装着牌的集合放入大集合管理
            playerList.add(player0);
            playerList.add(player1);
            playerList.add(player2);

            //把当前的牌置于顶端,效果:牌依次错开
            container.setComponentZOrder(poker,0);

        }

        //给手牌排序
        for(int i=0;i<3;i++){
            //排序
            Common.order(playerList.get(i));
            //重新摆放顺序
            Common.rePosition(this,playerList.get(i),i);
        }

    }

    //打牌之前的准备工作
    private void initGame(){
        //创建三个集合装三个玩家要出的牌
        for(int i=0;i<3;i++){
            ArrayList<Poker> list = new ArrayList<>();
            //添加到大集合
            currentList.add(list);
        }
        //展示抢地主和不抢地主两个按钮
        landlord[0].setVisible(true);
        landlord[1].setVisible(true);
        //展示自己前方倒计时文本
        time[1].setVisible(true);
        //倒计时10秒
        po = new PlayerOperation(this,10);
        //开启倒计时
        po.start();
    }
    @Override //0出抢 1不出不抢
    public void actionPerformed(ActionEvent e){
        if(e.getSource() == landlord[0]){
            //点击抢地主
            time[1].setText("抢地主");
            po.isRun = false;
        }else if(e.getSource() == landlord[1]){
            //点击不抢
            time[1].setText("不抢");
            po.isRun = false;
        }else if(e.getSource() == publishCard[1]){
            //点击不要 清空当前牌列表 轮到下一位玩家
            currentList.get(1).clear();
            this.nextPlayer = true;
            time[1].setText("不要");
        }else if(e.getSource() == publishCard[0]){
            //点击出牌
            //创建一个临时集合 存放当前 要出的牌
            ArrayList<Poker> c = new ArrayList<>();
            //获取当前 手牌
            ArrayList<Poker> player2 = playerList.get(1);

            //遍历手牌 要出的牌存放到临时集合
            for(int i=0;i<player2.size();i++){
                Poker poker = player2.get(i);
                if(poker.isClicked()){
                    c.add(poker);
                }
            }

            int flag = 0;
            //判断,如果左右两个玩家都不要
            if(time[0].getText().equals("不要") && time[2].getText().equals("不要")){
                //判断当前玩家出牌是否合法 PokerType.c0为不出牌
                if(Common.jugdeType(c) != PokerType.c0){
                    flag = 1;
                }
            } else {
                flag = Common.checkCards(c,currentList,this);
            }

            if(flag == 1){
                //牌合法 要出的牌放入大集合管理
                currentList.set(1,c);
                //手牌中去除已出的牌
                player2.removeAll(c);

                //计算坐标并移动牌
                //移动 使要出的牌出现在手牌上方
                Point point = new Point();
                point.x = (770/2) - (c.size() + 1) * 15 / 2;
                point.y = 300;
                for(int i=0,len = c.size();i<len;i++){
                    Poker poker = c.get(i);
                    Common.move(poker,poker.getLocation(),point);
                    point.x += 15;
                }
                //重新摆放剩余的牌
                Common.rePosition(this,player2,1);
                //隐藏文本提示
                time[1].setVisible(false);
                //轮到下一位玩家
                this.nextPlayer = true;
            }

        }

    }

    //设置界面
    public void initJFrame(){
        //设置标题
        this.setTitle("斗地主");
        //设置大小
        this.setSize(830,620);
        //设置关闭模式
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置窗口无法进行调节
        this.setResizable(false);
        //界面居中
        this.setLocationRelativeTo(null);
        //container获取界面中的隐藏容器,以后无需再次调用方法获取
        container = this.getContentPane();
        //取消内部默认的居中放置
        container.setLayout(null);
        //设置背景颜色
        container.setBackground(Color.LIGHT_GRAY);

    }


    //添加组件
    public void initView(){
        //创建抢地主的按钮
        JButton robBut = new JButton("抢地主");
        //设置位置
        robBut.setBounds(320,400,75,20);
        //添加点击事件
        robBut.addActionListener(this);
        robBut.setVisible(false);
        landlord[0] = robBut;
        container.add(robBut);

        //创建不抢的按钮
        JButton noBut = new JButton("不   抢");
        //设置位置
        noBut.setBounds(420,400,75,20);
        //添加点击事件
        noBut.addActionListener(this);
        noBut.setVisible(false);
        //添加到数组中管理
        landlord[1] = noBut;
        container.add(noBut);

        //创建出牌的按钮
        JButton outCardBut = new JButton("出牌");
        outCardBut.setBounds(320,400,60,20);
        outCardBut.addActionListener(this);
        outCardBut.setVisible(false);
        publishCard[0] = outCardBut;
        container.add(outCardBut);

        //创建不要的按钮
        JButton noCardBut = new JButton("不要");
        noCardBut.setBounds(420, 400, 60, 20);
        noCardBut.addActionListener(this);
        noCardBut.setVisible(false);
        publishCard[1] = noCardBut;
        container.add(noCardBut);


        //创建玩家前的提示文字 倒计时
        for (int i = 0; i < 3; i++) {
            time[i] = new JTextField("倒计时");
            //输入框不可编辑
            time[i].setEditable(false);
            time[i].setVisible(false);
            //三个输入框添加到容器界面
            container.add(time[i]);
            int x = 150 + 235  * i;
            int y = 230 + (i==1 ? 130 : 0);
            time[i].setBounds(x, y, 60, 20);
        }

        //创建地主图标 先不设置位置
        lord = new JLabel(new ImageIcon("image/lord.png"));
        lord.setVisible(false);
        lord.setSize(40,40);
        container.add(lord);

    }

}

登录注册类LoginJFrame

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


//继承JFrame类 鼠标监听接口
public class LoginJFrame extends JFrame implements MouseListener {
    private String newcodeStr = ""; //保存codeStr的值的变量 newcodeStr为全局变量 封装后仅有本类可以访问 可以在本类不同方法传递
    private static List<User> userDatabase = new ArrayList<>();
    //静态方法getUser(String userName) 从userDatabase列表中根据用户名查找用户对象
    //在登录和修改密码的事件监听器中
    //根据用户名从数据库中获取对应的用户对象
    private static User getUser(String userName){
        for(User user: userDatabase){
            //for-each 循环来遍历 userDatabase 列表中的每个用户对象
            if(user.getUserName().equals(userName)){
                return user;
            }
        }
        return null;
    }


    JButton loginButton = new JButton();
    JButton registerButton = new JButton();
    JButton changePasswordButton = new JButton();
    JButton showUserListButton = new JButton();
    JTextField usernameText  = new JTextField(20);
    JPasswordField passwordText = new JPasswordField(20);
    JTextField codeText = new JTextField(6);

    //正确的验证码
    JLabel rightCode = new JLabel();

    public LoginJFrame(){
        //初始化界面
        initJFrame();
        //初始化组件,在页面中添加内容
        initView();
        //让当前界面显示出来
        this.setVisible(true);
    }

    public void initJFrame(){
        //设置宽高 标题 关闭后停止运行 居中 置顶 取消默认布局
        this.setSize(640,420);
        this.setTitle("斗地主游戏登录 Version:1.0.0 ");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setAlwaysOnTop(true);
        this.setLayout(null);
    }

    public void initView(){
        //添加用户名文字 Font字体样式大小 JLabel标签 setForeground设置前景颜色  setFont传入定义字体 setBounds设置字边框大小
        //getContentPane(添加标签).add() 获取内容窗格
        Font usernameFont = new Font("微软雅黑",1,16);
        JLabel usernameLabel = new JLabel("用户名");
        usernameLabel.setForeground(Color.white);
        usernameLabel.setFont(usernameFont);
        usernameLabel.setBounds(140,55,55,22);
        this.getContentPane().add(usernameLabel);

        //添加用户名输入框
        usernameText.setBounds(223,46,200,30);
        this.getContentPane().add(usernameText);

        //添加密码文字
        Font passwordFont = new Font("微软雅黑",1,16);
        JLabel passwordLabel = new JLabel("密码");
        passwordLabel.setForeground(Color.white);
        passwordLabel.setFont(passwordFont);
        passwordLabel.setBounds(197,95,40,22);
        this.getContentPane().add(passwordLabel);

        //添加密码输入框
        passwordText.setBounds(263,87,160,30);
        this.getContentPane().add(passwordText);

        //验证码文字
        Font codeFont = new Font("微软雅黑",1,16);
        JLabel codeLabel = new JLabel("验证码");
        codeLabel.setForeground(Color.white);
        codeLabel.setFont(codeFont);
        codeLabel.setBounds(215,142,55,22);
        this.getContentPane().add(codeLabel);

        //验证码输入框
        codeText.setBounds(291,133,100,30);
        this.getContentPane().add(codeText);

        //获取正确的验证码
        String codeStr = CodeUtil.getCode();
        Font rightCodeFont = new Font("微软雅黑",1,15);
        //设置颜色
        rightCode.setForeground(Color.white);
        //设置字体
        rightCode.setFont(rightCodeFont);
        //设置内容
        rightCode.setText(codeStr);
        newcodeStr = codeStr; //组件初始化时,调用CodeUtil.getCode()方法获取随机验证码保存到codeStr中 再将codeStr的值赋给newCodeStr
        //绑定鼠标事件
        rightCode.addMouseListener(this);
        //设置位置和宽高
        rightCode.setBounds(400,133,100,30);
        //添加到界面
        this.getContentPane().add(rightCode);

        //添加登录按钮
        loginButton.setBounds(50,310,128,47);
        loginButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\登录按钮.png"));
        //去除按钮的边框背景
        loginButton.setBorderPainted(false);
        loginButton.setContentAreaFilled(false);
        //给登录按钮绑定鼠标事件
        loginButton.addMouseListener(this);
        loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("点击了登录按钮");
                // 获取用户名输入框与密码输入框内容
                String usernameInput = usernameText.getText();
                String passwordInput = new String(passwordText.getPassword());
                String codeInput = codeText.getText();
                User user = getUser(usernameInput);
                //Java中,当一个对象为null时,如果我们试图调用该对象的方法或访问其属性,就会抛出空指针异常
                //检查getUser()返回的user对象是否为null,以避免空指针异常
                if(codeInput.length() != 0 && codeInput.equals(newcodeStr)){
                    System.out.println("验证码正确");
                    if (user != null && user.getUserName().equals(usernameInput) && user.getPassWord().equals(passwordInput)) {
                        showJDialog("登录成功");
                        //关闭当前登录界面并打开游戏界面
                        closeOpenGameWindow();

                        usernameText.setText("");
                        passwordText.setText("");
                        codeText.setText("");
                    } else {
                        showJDialog("用户名或密码错误");
                    }
                }else{
                    showJDialog("验证码错误");
                }

            }
        });
        this.getContentPane().add(loginButton);

        //添加注册按钮 大小图标
        registerButton.setBounds(190,310,128,47);
        registerButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\注册按钮.png"));
        //去除按钮的边框背景
        registerButton.setBorderPainted(false);
        registerButton.setContentAreaFilled(false);
        //给注册按钮绑定鼠标事件
        registerButton.addMouseListener(this);
        registerButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("点击了注册按钮");
                String usernameInput = usernameText.getText();
                String passwordInput = new String(passwordText.getPassword());
                String codeInput = codeText.getText();
                if(codeInput.length() !=0 && codeInput.equals(newcodeStr)){
                      System.out.println("验证码正确");
                    if(usernameInput.length() != 0 && passwordInput.length() !=0){
                        User user = getUser(usernameInput);
                        if(user == null){
                            user = new User(usernameInput,passwordInput);
                            userDatabase.add(user);
                            showJDialog("注册成功");
                            //更换验证码
                            String code = CodeUtil.getCode();
                            rightCode.setText(code);
                            newcodeStr = code;
                            //如果没有newCoderStr保存改变验证码的值 那么rightCode标签变化CodeStr值不变 登录验证码不匹配
                            usernameText.setText("");
                            passwordText.setText("");
                            codeText.setText("");
                        } else {
                            showJDialog("用户已存在");
                        }
                    } else {
                        showJDialog("用户名或密码为空");
                    }
                  }else{
                    showJDialog("验证码错误");
                }

            }
        });
        this.getContentPane().add(registerButton);

        //添加修改密码按钮 大小图标
        changePasswordButton.setBounds(330,310,128,47);
        changePasswordButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\修改密码按钮.png"));
        //去除按钮边框背景
        changePasswordButton.setBorderPainted(false);
        changePasswordButton.setContentAreaFilled(false);
        //给按钮绑定鼠标事件和监听器
        changePasswordButton.addMouseListener(this);
        changePasswordButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String usernameInput = usernameText.getText();
                User user = getUser(usernameInput);
                if(user != null && user.getUserName().equals(usernameInput)){
                    String newPassword = new String(passwordText.getPassword());
                    if(newPassword != null && !newPassword.isEmpty()){
                        user.setPassword(newPassword); // 更新用户密码
                        showJDialog("更改密码成功");
                    } else {
                        showJDialog("密码不能为空");
                    }
                } else {
                    showJDialog("用户不存在");
                }
            }
        });

        this.getContentPane().add(changePasswordButton);

        //添加用户列表按钮 大小图标
        showUserListButton.setBounds(470,310,128,47);
        showUserListButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\用户列表按钮.png"));
        //去除按钮边框背景
        showUserListButton.setBorderPainted(false);
        showUserListButton.setContentAreaFilled(false);
        //给按钮添加鼠标事件和监听
        showUserListButton.addMouseListener(this);
        showUserListButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                StringBuilder userList = new StringBuilder("注册用户名列表:\n");
                if (!userDatabase.isEmpty()) {
                    for (User user : userDatabase) {
                        userList.append(user.getUserName()).append("\n");
                    }
                    showJDialog(userList.toString());
                } else {
                    showJDialog("未注册用户");
                }
            }
        });

        this.getContentPane().add(showUserListButton);

        //添加背景图片
        JLabel background = new JLabel(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\background.png"));
        background.setBounds(0,0,633,423);
        this.getContentPane().add(background);

    }


    public void closeOpenGameWindow(){
        this.dispose();
        new GameJFrame();
    }


    //弹窗方法
    public void showJDialog(String content){
        //创建一个弹窗对象
        JDialog jDialog =  new JDialog();
        //给弹窗设置大小
        jDialog.setSize(260,150);
        //给弹窗置顶
        jDialog.setAlwaysOnTop(true);
        //让弹窗居中
        jDialog.setLocationRelativeTo(null);
        //弹窗不关闭无法操作下面界面
        jDialog.setModal(true);
        //设置弹窗背景颜色
        jDialog.getContentPane().setBackground(Color.LIGHT_GRAY);
        //设置边框
        jDialog.getRootPane().setBorder(BorderFactory.createLineBorder(Color.GRAY,2));

        //创建JLabel对象 添加文字到弹窗上
        JLabel warning = new JLabel(content,SwingConstants.CENTER);
        warning.setFont(new Font("微软雅黑",Font.BOLD,16));
        warning.setBounds(0,0,200,150);

        jDialog.getContentPane().add(warning);
        //添加重试按钮
        JPanel widowPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        jDialog.add(widowPanel,BorderLayout.SOUTH);
        JButton closeButton = new JButton("重试");
        closeButton.setFocusPainted(false);
        closeButton.setFont(new Font("微软雅黑",Font.BOLD,16));
        widowPanel.add(closeButton);
        closeButton.addActionListener(e -> jDialog.dispose());
        //显示弹窗
        jDialog.setVisible(true);
    }


    @Override  //鼠标点击  e.getSource()方法获取用户单击的组件
    public void mouseClicked(MouseEvent e) {
        if(e.getSource() == rightCode){
            System.out.println("更换了验证码");
            //更换验证码
            String code = CodeUtil.getCode();
            rightCode.setText(code);
            newcodeStr = code;
        }
    }

    @Override  //按下不松
    public void mousePressed(MouseEvent e) {
        if(e.getSource() == loginButton){
            loginButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\登录按下.png"));
        }else if(e.getSource() == registerButton){
            registerButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\注册按下.png"));
        }else if(e.getSource() == changePasswordButton){
            changePasswordButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\修改密码按下.png"));
        }else if(e.getSource() == showUserListButton){
            showUserListButton.setIcon(new ImageIcon("D:\\\\CHINESEPOKER\\\\image\\\\login\\\\用户列表按下.png"));
        }
    }

    @Override  //松开按钮
    public void mouseReleased(MouseEvent e) {
        if(e.getSource() == loginButton){
            loginButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\登录按钮.png"));
        }else if(e.getSource() == registerButton){
            registerButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\注册按钮.png"));
        }else if(e.getSource() == changePasswordButton){
            changePasswordButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\修改密码按钮.png"));
        }else if(e.getSource() == showUserListButton){
            showUserListButton.setIcon(new ImageIcon("D:\\\\CHINESEPOKER\\\\image\\\\login\\\\用户列表按钮.png"));
        }
    }

    @Override  //鼠标划入
    public void mouseEntered(MouseEvent e) {
    }

    @Override  //鼠标划出
    public void mouseExited(MouseEvent e) {
    }




}

Model类

import java.util.ArrayList;

public class Model {
    int value; //极值
    int num; //过手数
    ArrayList<String> a1 = new ArrayList<>(); //单张
    ArrayList<String> a2 = new ArrayList<>(); //对子
    ArrayList<String> a3 = new ArrayList<>(); //三带
    ArrayList<String> a123 = new ArrayList<>(); //连子
    ArrayList<String> a112233 = new ArrayList<>(); //连牌
    ArrayList<String> a111222 = new ArrayList<>(); //飞机
    ArrayList<String> a4 = new ArrayList<>(); //炸弹
}

游戏操作类PlayerOperation

  import lynu.rookie.main.Poker;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class PlayerOperation extends Thread {

    //游戏主界面
    GameJFrame gameJFrame;

    //是否能走
    boolean isRun = true;

    //倒计时
    int i;

    public PlayerOperation(GameJFrame m, int i) {
        this.gameJFrame = m;
        this.i = i;
    }

    @Override
    public void run() {
        while (i > -1 && isRun) {
            gameJFrame.time[1].setText("倒计时:" + i--);
            sleep(1);
        }
        if (i == -1){
            gameJFrame.time[1].setText("不抢");
        }
        gameJFrame.landlord[0].setVisible(false);
        gameJFrame.landlord[1].setVisible(false);
        for (Poker poker2 : gameJFrame.playerList.get(1)){
            poker2.setCanClick(true);// 可被点击
        }

        if (gameJFrame.time[1].getText().equals("抢地主")) {
            gameJFrame.playerList.get(1).addAll(gameJFrame.lordList);
            openlord(true);
            sleep(2);
            Common.order(gameJFrame.playerList.get(1));
            Common.rePosition(gameJFrame, gameJFrame.playerList.get(1), 1);
            gameJFrame.publishCard[1].setEnabled(false);
            setlord(1);
        } else {
            if (Common.getScore(gameJFrame.playerList.get(0)) < Common.getScore(gameJFrame.playerList.get(2))) {
                gameJFrame.time[2].setText("抢地主");
                gameJFrame.time[2].setVisible(true);
                setlord(2);
                openlord(true);
                sleep(3);
                gameJFrame.playerList.get(2).addAll(gameJFrame.lordList);
                Common.order(gameJFrame.playerList.get(2));
                Common.rePosition(gameJFrame, gameJFrame.playerList.get(2), 2);
                openlord(false);
            } else {
                gameJFrame.time[0].setText("抢地主");
                gameJFrame.time[0].setVisible(true);
                setlord(0);
                openlord(true);
                sleep(3);
                gameJFrame.playerList.get(0).addAll(gameJFrame.lordList);
                Common.order(gameJFrame.playerList.get(0));
                Common.rePosition(gameJFrame, gameJFrame.playerList.get(0), 0);
                openlord(false);
            }
        }
        gameJFrame.landlord[0].setVisible(false);
        gameJFrame.landlord[1].setVisible(false);
        turnOn(false);
        for (int i = 0; i < 3; i++) {
            gameJFrame.time[i].setText("不要");
            gameJFrame.time[i].setVisible(false);
        }
        gameJFrame.turn = gameJFrame.lordFlag;
        while (true) {

            if (gameJFrame.turn == 1) {

                if (gameJFrame.time[0].getText().equals("不要") && gameJFrame.time[2].getText().equals("不要"))
                    gameJFrame.publishCard[1].setEnabled(false);
                else {
                    gameJFrame.publishCard[1].setEnabled(true);
                }
                turnOn(true);
                timeWait(30, 1);
                turnOn(false);
                gameJFrame.turn = (gameJFrame.turn + 1) % 3;
                if (win())
                    break;
            }
            if (gameJFrame.turn == 0) {
                computer0();
                gameJFrame.turn = (gameJFrame.turn + 1) % 3;
                if (win())
                    break;
            }
            if (gameJFrame.turn == 2) {
                computer2();
                gameJFrame.turn = (gameJFrame.turn + 1) % 3;
                if (win())
                    break;
            }
        }
    }

    //定义一个方法用来暂停N秒
    //参数为等待的时间
    //因为线程中的sleep方法有异常,直接调用影响阅读
    public void sleep(int i) {
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public void openlord(boolean is) {
        for (int i = 0; i < 3; i++) {
            if (is)
                gameJFrame.lordList.get(i).turnFront();
            else {
                gameJFrame.lordList.get(i).turnRear();
            }
            gameJFrame.lordList.get(i).setCanClick(true);
        }
    }

    public void setlord(int i) {
        Point point = new Point();
        if (i == 1) {
            point.x = 80;
            point.y = 430;
            gameJFrame.lordFlag = 1;
        }
        if (i == 0) {
            point.x = 80;
            point.y = 20;
            gameJFrame.lordFlag = 0;
        }
        if (i == 2) {
            point.x = 700;
            point.y = 20;
            gameJFrame.lordFlag = 2;
        }
        gameJFrame.lord.setLocation(point);
        gameJFrame.lord.setVisible(true);
    }

    public void turnOn(boolean flag) {
        gameJFrame.publishCard[0].setVisible(flag);
        gameJFrame.publishCard[1].setVisible(flag);
    }

    public void computer0() {
        timeWait(1, 0);
        ShowCard(0);

    }

    public void computer2() {
        timeWait(1, 2);
        ShowCard(2);

    }

    public void ShowCard(int role) {
        int orders[] = new int[] { 4, 3, 2, 1, 5 };
        Model model = Common.getModel(gameJFrame.playerList.get(role), orders);
        ArrayList<String> list = new ArrayList<>();
        if (gameJFrame.time[(role + 1) % 3].getText().equals("不要") && gameJFrame.time[(role + 2) % 3].getText().equals("不要")) {
            if (model.a123.size() > 0) {
                list.add(model.a123.get(model.a123.size() - 1));
            } else if (model.a3.size() > 0) {
                if (model.a1.size() > 0) {
                    list.add(model.a1.get(model.a1.size() - 1));
                } else if (model.a2.size() > 0) {
                    list.add(model.a2.get(model.a2.size() - 1));
                }
                list.add(model.a3.get(model.a3.size() - 1));
            } else if (model.a112233.size() > 0) {
                list.add(model.a112233.get(model.a112233.size() - 1));
            } else if (model.a111222.size() > 0) {
                String name[] = model.a111222.get(0).split(",");

                if (name.length / 3 <= model.a1.size()) {
                    list.add(model.a111222.get(model.a111222.size() - 1));
                    for (int i = 0; i < name.length / 3; i++)
                        list.add(model.a1.get(i));
                } else if (name.length / 3 <= model.a2.size()) {
                    list.add(model.a111222.get(model.a111222.size() - 1));
                    for (int i = 0; i < name.length / 3; i++)
                        list.add(model.a2.get(i));
                }

            } else if (model.a2.size() > (model.a111222.size() * 2 + model.a3.size())) {
                list.add(model.a2.get(model.a2.size() - 1));
            } else if (model.a1.size() > (model.a111222.size() * 2 + model.a3.size())) {
                list.add(model.a1.get(model.a1.size() - 1));
            } else if (model.a4.size() > 0) {
                int sizea1 = model.a1.size();
                int sizea2 = model.a2.size();
                if (sizea1 >= 2) {
                    list.add(model.a1.get(sizea1 - 1));
                    list.add(model.a1.get(sizea1 - 2));
                    list.add(model.a4.get(0));

                } else if (sizea2 >= 2) {
                    list.add(model.a2.get(sizea1 - 1));
                    list.add(model.a2.get(sizea1 - 2));
                    list.add(model.a4.get(0));

                } else {
                    list.add(model.a4.get(0));

                }

            }
        } else {

            if (role != gameJFrame.lordFlag) {
                int f = 0;
                if (gameJFrame.time[gameJFrame.lordFlag].getText().equals("不要")) {
                    f = 1;
                }
                if ((role + 1) % 3 == gameJFrame.lordFlag) {
                    if ((Common.jugdeType(gameJFrame.currentList.get((role + 2) % 3)) != PokerType.c1
                            || Common.jugdeType(gameJFrame.currentList.get((role + 2) % 3)) != PokerType.c2)
                            && gameJFrame.currentList.get(gameJFrame.lordFlag).size() < 1)
                        f = 1;
                    if (gameJFrame.currentList.get((role + 2) % 3).size() > 0
                            && Common.getValue(gameJFrame.currentList.get((role + 2) % 3).get(0)) > 13)
                        f = 1;
                }
                if (f == 1) {
                    gameJFrame.time[role].setVisible(true);
                    gameJFrame.time[role].setText("不要");
                    return;
                }
            }

            int can = 0;
            if (role == gameJFrame.lordFlag) {
                if (gameJFrame.playerList.get((role + 1) % 3).size() <= 5 || gameJFrame.playerList.get((role + 2) % 3).size() <= 5)
                    can = 1;
            } else {
                if (gameJFrame.playerList.get(gameJFrame.lordFlag).size() <= 5)
                    can = 1;
            }

            ArrayList<Poker> player;
            if (gameJFrame.time[(role + 2) % 3].getText().equals("不要"))
                player = gameJFrame.currentList.get((role + 1) % 3);
            else
                player = gameJFrame.currentList.get((role + 2) % 3);

            PokerType cType = Common.jugdeType(player);

            if (cType == PokerType.c1) {
                if (can == 1)
                    model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 1, 4, 3, 2, 5 });
                AI_1(model.a1, player, list, role);
            } else if (cType == PokerType.c2) {
                if (can == 1)
                    model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 2, 4, 3, 5, 1 });
                AI_1(model.a2, player, list, role);
            } else if (cType == PokerType.c3) {
                AI_1(model.a3, player, list, role);
            } else if (cType == PokerType.c4) {
                AI_1(model.a4, player, list, role);
            } else if (cType == PokerType.c31) {
                if (can == 1)
                    model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 3, 1, 4, 2, 5 });
                AI_2(model.a3, model.a1, player, list, role);
            } else if (cType == PokerType.c32) {
                if (can == 1)
                    model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 3, 2, 4, 5, 1 });
                AI_2(model.a3, model.a2, player, list, role);
            } else if (cType == PokerType.c411) {
                AI_5(model.a4, model.a1, player, list, role);
            }

            else if (cType == PokerType.c422) {
                AI_5(model.a4, model.a2, player, list, role);
            }

            else if (cType == PokerType.c123) {
                if (can == 1)
                    model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 5, 3, 2, 4, 1 });
                AI_3(model.a123, player, list, role);
            }

            else if (cType == PokerType.c112233) {
                if (can == 1)
                    model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 2, 4, 3, 5, 1 });
                AI_3(model.a112233, player, list, role);
            }

            else if (cType == PokerType.c11122234) {
                AI_4(model.a111222, model.a1, player, list, role);
            }

            else if (cType == PokerType.c1112223344) {
                AI_4(model.a111222, model.a2, player, list, role);
            }
            if (list.size() == 0 && can == 1) {
                int len4 = model.a4.size();
                if (len4 > 0)
                    list.add(model.a4.get(len4 - 1));
            }

        }

        gameJFrame.currentList.get(role).clear();
        if (list.size() > 0) {
            Point point = new Point();
            if (role == 0)
                point.x = 200;
            if (role == 2)
                point.x = 550;
            if (role == 1) {
                point.x = (770 / 2) - (gameJFrame.currentList.get(1).size() + 1) * 15 / 2;
                point.y = 300;
            }
            point.y = (400 / 2) - (list.size() + 1) * 15 / 2;
            ArrayList<Poker> temp = new ArrayList<>();
            for (int i = 0, len = list.size(); i < len; i++) {
                List<Poker> pokers = getCardByName(gameJFrame.playerList.get(role), list.get(i));
                for (Poker poker : pokers) {
                    temp.add(poker);
                }
            }
            temp = Common.getOrder2(temp);
            for (Poker poker : temp) {
                Common.move(poker, poker.getLocation(), point);
                point.y += 15;
                gameJFrame.container.setComponentZOrder(poker, 0);
                gameJFrame.currentList.get(role).add(poker);
                gameJFrame.playerList.get(role).remove(poker);
            }
            Common.rePosition(gameJFrame, gameJFrame.playerList.get(role), role);
        } else {
            gameJFrame.time[role].setVisible(true);
            gameJFrame.time[role].setText("不要");
        }
        for (Poker poker : gameJFrame.currentList.get(role))
            poker.turnFront();
    }

    public List getCardByName(List<Poker> list, String n) {
        String[] name = n.split(",");
        ArrayList cardsList = new ArrayList();
        int j = 0;
        for (int i = 0, len = list.size(); i < len; i++) {
            if (j < name.length && list.get(i).getName().equals(name[j])) {
                cardsList.add(list.get(i));
                i = 0;
                j++;
            }
        }
        return cardsList;
    }

    public void AI_3(List<String> model, List<Poker> player, List<String> list, int role) {

        for (int i = 0, len = model.size(); i < len; i++) {
            String[] s = model.get(i).split(",");
            if (s.length == player.size() && getValueInt(model.get(i)) > Common.getValue(player.get(0))) {
                list.add(model.get(i));
                return;
            }
        }
    }

    public void AI_4(List<String> model1, List<String> model2, List<Poker> player, List<String> list, int role) {
        player = Common.getOrder2(player);
        int len1 = model1.size();
        int len2 = model2.size();

        if (len1 < 1 || len2 < 1)
            return;
        for (int i = 0; i < len1; i++) {
            String[] s = model1.get(i).split(",");
            String[] s2 = model2.get(0).split(",");
            if ((s.length / 3 <= len2) && (s.length * (3 + s2.length) == player.size())
                    && getValueInt(model1.get(i)) > Common.getValue(player.get(0))) {
                list.add(model1.get(i));
                for (int j = 1; j <= s.length / 3; j++)
                    list.add(model2.get(len2 - j));
            }
        }
    }

    public void AI_5(List<String> model1, List<String> model2, List<Poker> player, List<String> list, int role) {
        player = Common.getOrder2(player);
        int len1 = model1.size();
        int len2 = model2.size();

        if (len1 < 1 || len2 < 2)
            return;
        for (int i = 0; i < len1; i++) {
            if (getValueInt(model1.get(i)) > Common.getValue(player.get(0))) {
                list.add(model1.get(i));
                for (int j = 1; j <= 2; j++)
                    list.add(model2.get(len2 - j));
            }
        }
    }

    public void AI_1(List<String> model, List<Poker> player, List<String> list, int role) {

        for (int len = model.size(), i = len - 1; i >= 0; i--) {
            if (getValueInt(model.get(i)) > Common.getValue(player.get(0))) {
                list.add(model.get(i));
                break;
            }
        }

    }

    public void AI_2(List<String> model1, List<String> model2, List<Poker> player, List<String> list, int role) {
        player = Common.getOrder2(player);
        int len1 = model1.size();
        int len2 = model2.size();
        if (len1 > 0 && model1.get(0).length() < 10) {
            list.add(model1.get(0));
            System.out.println("王炸");
            return;
        }
        if (len1 < 1 || len2 < 1)
            return;
        for (int len = len1, i = len - 1; i >= 0; i--) {
            if (getValueInt(model1.get(i)) > Common.getValue(player.get(0))) {
                list.add(model1.get(i));
                break;
            }
        }
        list.add(model2.get(len2 - 1));
        if (list.size() < 2)
            list.clear();
    }

    public void timeWait(int n, int player) {

        if (gameJFrame.currentList.get(player).size() > 0)
            Common.hideCards(gameJFrame.currentList.get(player));
        if (player == 1) {
            int i = n;

            while (gameJFrame.nextPlayer == false && i >= 0) {
                gameJFrame.time[player].setText("倒计时:" + i);
                gameJFrame.time[player].setVisible(true);
                sleep(1);
                i--;
            }
            if (i == -1 && player == 1) {

                ShowCard(1);
            }
            gameJFrame.nextPlayer = false;
        } else {
            for (int i = n; i >= 0; i--) {
                sleep(1);
                gameJFrame.time[player].setText("倒计时:" + i);
                gameJFrame.time[player].setVisible(true);
            }
        }
        gameJFrame.time[player].setVisible(false);
    }

    public int getValueInt(String n) {
        String name[] = n.split(",");
        String s = name[0];
        int i = Integer.parseInt(s.substring(2, s.length()));
        if (s.substring(0, 1).equals("5"))
            i += 3;
        if (s.substring(2, s.length()).equals("1") || s.substring(2, s.length()).equals("2"))
            i += 13;
        return i;
    }

    public boolean win() {
        for (int i = 0; i < 3; i++) {
            if (gameJFrame.playerList.get(i).size() == 0) {
                String s;
                if (i == 1) {
                    s = "恭喜你,胜利了!";
                } else {
                    s = "恭喜电脑" + i + ",赢了! 你的智商有待提高哦";
                }
                for (int j = 0; j < gameJFrame.playerList.get((i + 1) % 3).size(); j++)
                    gameJFrame.playerList.get((i + 1) % 3).get(j).turnFront();
                for (int j = 0; j < gameJFrame.playerList.get((i + 2) % 3).size(); j++)
                    gameJFrame.playerList.get((i + 2) % 3).get(j).turnFront();
                JOptionPane.showMessageDialog(gameJFrame, s);
                return true;
            }
        }
        return false;
    }
}

出牌类型PokerType 枚举 一些有相同关系的常量

public enum PokerType {
    c0,//不出牌
    c1,//单张牌
    c2,//二张相同牌,对子
    c3,//三张相同牌
    c4,//四张相同牌,炸弹
    c31,//三张相同牌与单张牌,三带一
    c32,//三张相同牌与二张相同牌,三带二
    c411,//4张相同牌与二张牌
    c422,//4张相同牌与二对牌
    c123,//连牌
    c112233,//连对
    c111222,//飞机
    c11122234,//飞机带二张牌
    c1112223344,//飞机带对子
}

main包下新建类

Poker类

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Poker extends JLabel implements MouseListener {

    //游戏的主界面
    GameJFrame gameJFrame;
    //牌的名字
    String name;
    //牌显示正面还是反面
    boolean up;
    //是否可点击
    boolean canClick = false;
    //当前状态,是否已经被点击
    boolean clicked = false;

    public Poker(GameJFrame m, String name, boolean up) {
        this.gameJFrame = m;
        this.name = name;
        this.up = up;
        //判断当前的牌是显示正面还是背面
        if (this.up){
            this.turnFront();
        }else {
            this.turnRear();
        }
        //设置牌的宽高大小
        this.setSize(71, 96);
        //把牌显示出来
        this.setVisible(true);
        //给每一张牌添加鼠标监听
        this.addMouseListener(this);
    }

    public Poker() {
    }

    public Poker(GameJFrame gameJFrame, String name, boolean up, boolean canClick, boolean clicked) {
        this.gameJFrame = gameJFrame;
        this.name = name;
        this.up = up;
        this.canClick = canClick;
        this.clicked = clicked;
    }

    //显示正面
    public void turnFront() {
        this.setIcon(new ImageIcon("image\\poker\\" + name + ".png"));
        this.up = true;
    }

    //显示背面
    public void turnRear() {
        this.setIcon(new ImageIcon("image\\poker\\rear.png"));
        this.up = false;
    }


    //出牌时,需要点击牌
    //被点击之后,牌向上移动20个像素
    //再次被点击,牌回落20个像素
    @Override
    public void mouseClicked(MouseEvent e) {
        if (canClick) {
            Point from = this.getLocation();
            int step;
            if (clicked){
                step = 20;
            }else {
                step = -20;
            }
            clicked = !clicked;
            Point to = new Point(from.x, from.y + step);
            this.setLocation(to);
        }
    }

    public void mouseEntered(MouseEvent arg0) {
    }

    public void mouseExited(MouseEvent arg0) {
    }

    public void mouseReleased(MouseEvent arg0) {
    }

    public void mousePressed(MouseEvent e) {
    }


    /**
     * 获取
     * @return gameJFrame
     */
    public GameJFrame getGameJFrame() {
        return gameJFrame;
    }

    /**
     * 设置
     * @param gameJFrame
     */
    public void setGameJFrame(GameJFrame gameJFrame) {
        this.gameJFrame = gameJFrame;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return up
     */
    public boolean isUp() {
        return up;
    }

    /**
     * 设置
     * @param up
     */
    public void setUp(boolean up) {
        this.up = up;
    }

    /**
     * 获取
     * @return canClick
     */
    public boolean isCanClick() {
        return canClick;
    }

    /**
     * 设置
     * @param canClick
     */
    public void setCanClick(boolean canClick) {
        this.canClick = canClick;
    }

    /**
     * 获取
     * @return clicked
     */
    public boolean isClicked() {
        return clicked;
    }

    /**
     * 设置
     * @param clicked
     */
    public void setClicked(boolean clicked) {
        this.clicked = clicked;
    }

    public String toString() {
        return "Poker{gameJFrame = " + gameJFrame + ", name = " + name + ", up = " + up + ", canClick = " + canClick + ", clicked = " + clicked + "}";
    }
}

User类

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class User {
    //    每当用户注册时,会创建一个新的User对象
    //    用户对象实际中存储在userDatabase的List列表中

    private String username;
    private String password;

    public User(String username,String password){
         this.username = username;
         this.password = password;
    }
    /*
    获取
     */
    public String getUserName(){
        return  username;
    }
    public  String getPassWord(){
        return  password;
    }
    /*
    设置
     */
    public void setUsername(String username){
        this.username = username;
    }
    public void setPassword(String password) { this.password = password;}

    @Override
    public boolean equals(Object o){
        if(this == o) return true;
        if(o == null || getClass() != o.getClass()) return false;
        User user = (User)o;
        return Objects.equals(username,user.username) &&
                Objects.equals(password,user.password);
    }

    @Override
    public int hashCode(){
        return Objects.hash(username,password);
    }
    public String toString(){  //{"内为变量"}
        return "User{username = " + username +
                ", password = " + password +"}";

    }
}

util包下新建类

验证码CodeUtil类

import java.util.ArrayList;
import java.util.Random;

public class CodeUtil {

    public static String getCode(){
        //创建一个集合;
        ArrayList<Character> list = new ArrayList<>(); //52 索引范围0-51
        //添加字母 a - z  A - Z
        for(int i=0;i<26;i++){
            list.add((char)('a' + i));//类型转换为字符97-a 65-A
            list.add((char)('A' + i));
        }
        //打印集合
        //System.out.println(list);
        //生成4个随机字母
        String result = "";
        Random r = new Random();
        for(int i=0;i<4;i++){
            int randomIndex = r.nextInt(list.size());
            result = result + list.get(randomIndex);
        }
        //长度为4的随机字符串 return result;
        //基础上拼接数字0-9
        int number = r.nextInt(10);
        //把随机数字拼接到result后面
        result = result + number;
        //把字符串变成字符数组
        char[] chars = result.toCharArray();
        //生成一个字符数组长度的随机索引
        int index = r.nextInt(chars.length);
        //末索引4上的数字字符与随机索引上的字符交换 使数字出现在索引0-4的任何位置
        char temp = chars[4];
        chars[4] = chars[index];
        chars[index] = temp;
        //字符数组变回字符串
        String code = new String(chars);
        return code;
    }

}

music包下新建类

MusicPlayer类

音乐可自行替换 javazoom需要配置jar包 jlayer-1.0.1-1.jar 搜索下载

package music;

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class MusicPlayer {

    public MusicPlayer() throws FileNotFoundException, JavaLayerException {
        Player player;
        //工作目录路径拼接音乐的相对路径
        String str = System.getProperty("user.dir")+"/src/music/Omeo.mp3";
        //BufferedInputStream对象,用于读取音乐文件。将文件路径传递给FileInputStream的构造函数,
        // 将其包装在BufferedInputStream中,以提高文件读取的效率
        while(true){
            BufferedInputStream name = new BufferedInputStream(new FileInputStream(str));
            player = new Player(name);
            player.play();
        }
    }

}

src下新建App类

import rookie.game.LoginJFrame;

public class App {
    public static void main(String[] args) {

        new LoginJFrame();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值