十四、综合项目(斗地主)

news2024/11/20 3:17:58

综合项目(斗地主)

  • 1.准备牌、洗牌、发牌、看牌
  • 2.对每人手中的牌进行排序
    • 2.1 排序方法1(利用序号进行排序)
    • 2.2排序方法2(给每一张牌计算价值)
  • 3.两个实体类
    • 3.1 User
    • 3.2 Poker
  • 4.登录页面
    • 4.1 验证码代码
    • 4.2 登录界面
  • 5.游戏界面


在这里插入图片描述

1.准备牌、洗牌、发牌、看牌

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

public class PokerGame {
    static ArrayList<String> list = new ArrayList<>();

    //准备牌
    static {
        String[] color = {"♠", "♥", "♦", "♣"};
        String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        for (String s : color) {
            for (String n : number) {
                list.add(s + n);
            }
        }
        list.add("大王");
        list.add("小王");
    }

    public PokerGame() {
        //洗牌
        Collections.shuffle(list);

        //发牌
        ArrayList<String> lord = new ArrayList<>();
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();

        //遍历牌盒
        for (int i = 0; i < list.size(); i++) {
            String poker = list.get(i);
            if (i <= 2) {
                lord.add(poker);
                continue;
            }
            //给三个玩家轮流发牌
            if (i % 3 == 0) {
                player1.add(poker);
            } else if (i % 3 == 1) {
                player2.add(poker);
            } else {
                player3.add(poker);
            }

        }

        //看牌
        lookPoker("底牌",lord);
        lookPoker("钢脑壳", player1);
        lookPoker("大帅比", player2);
        lookPoker("蛋筒", player3);
    }

    /*参数1:玩家名字
    * 参数2:每位玩家的牌*/
    private void lookPoker(String name,ArrayList<String> list) {
        System.out.print(name + ": ");
        for (String poker : list) {
            System.out.print(poker+" ");
        }
        System.out.println();
    }
}

在这里插入图片描述

2.对每人手中的牌进行排序

2.1 排序方法1(利用序号进行排序)

在这里插入图片描述
在这里插入图片描述

//准备牌
    //牌盒
    static HashMap<Integer, String> hm = new HashMap<>();
    static ArrayList<Integer> list = new ArrayList<>();

    /*
        1=♠3, 2=♠4, 3=♠5, 4=♠6, 5=♠7, 6=♠8, 7=♠9, 8=♠10, 9=♠J, 10=♠Q, 11=♠K, 12=♠A, 13=♠2,
        14=♥3, 15=♥4, 16=♥5, 17=♥6, 18=♥7, 19=♥8, 20=♥9, 21=♥10, 22=♥J, 23=♥Q, 24=♥K, 25=♥A, 26=♥2,
        27=♦3, 28=♦4, 29=♦5, 30=♦6, 31=♦7, 32=♦8, 33=♦9, 34=♦10, 35=♦J, 36=♦Q, 37=♦K, 38=♦A, 39=♦2,
        40=♣3, 41=♣4, 42=♣5, 43=♣6, 44=♣7, 45=♣8, 46=♣9, 47=♣10, 48=♣J, 49=♣Q, 50=♣K, 51=♣A, 52=♣2,
        53=小王, 54=大王
    */
/*
    1=♠3, 2=♥3, 3=♦3, 4=♣3,
    5=♠4, 6=♥4, 7=♦4, 8=♣4,
    9=♠5, 10=♥5, 11=♦5, 12=♣5,
    13=♠6, 14=♥6, 15=♦6, 16=♣6,
    17=♠7, 18=♥7, 19=♦7, 20=♣7,
    21=♠8, 22=♥8, 23=♦8, 24=♣8,
    25=♠9, 26=♥9, 27=♦9, 28=♣9,
    29=♠10, 30=♥10, 31=♦10, 32=♣10,
    33=♠J, 34=♥J, 35=♦J, 36=♣J,
    37=♠Q, 38=♥Q, 39=♦Q, 40=♣Q,
    41=♠K, 42=♥K, 43=♦K, 44=♣K,
    45=♠A, 46=♥A, 47=♦A, 48=♣A,
    49=♠2, 50=♥2, 51=♦2, 52=♣2,
    53=小王, 54=大王
*/
    static {
        String[] color = {"♠", "♥", "♦", "♣"};
        String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        int serialNumber = 1;
        for (String n : number) {
            for (String s : color) {
                hm.put(serialNumber, s + n);
                list.add(serialNumber);
                serialNumber++;
            }
        }

        hm.put(serialNumber, "小王");
        list.add(serialNumber);
        serialNumber++;
        hm.put(serialNumber, "大王");
        list.add(serialNumber);
    }

    public PokerGame() {
        //洗牌
        Collections.shuffle(list);

        //发牌
        TreeSet<Integer> lord = new TreeSet<>();
        TreeSet<Integer> player1 = new TreeSet<>();
        TreeSet<Integer> player2 = new TreeSet<>();
        TreeSet<Integer> player3 = new TreeSet<>();

        for (int i = 0; i < list.size(); i++) {
            int serialNumber = list.get(i);

            if (i < 3) {
                lord.add(serialNumber);
            } else if (i % 3 == 0) {
                player1.add(serialNumber);
            } else if (i % 3 == 1) {
                player2.add(serialNumber);
            } else {
                player3.add(serialNumber);
            }
        }

        //看牌
        lookPoker("底牌",lord);
        lookPoker("钢脑壳", player1);
        lookPoker("大帅比", player2);
        lookPoker("蛋筒", player3);

    }

    private void lookPoker(String name,TreeSet<Integer> ts){
        System.out.print(name+": ");
        for (int serialNumber : ts) {
            String poker = hm.get(serialNumber);
            System.out.print(poker + " ");
        }
        System.out.println();
    }

在这里插入图片描述

2.2排序方法2(给每一张牌计算价值)

价值:积分、得分
在这里插入图片描述

//准备牌
    static ArrayList<String> list = new ArrayList<>();

    static HashMap<String, Integer> hm = new HashMap<>();

    static {
        String[] color = {"♠", "♥", "♦", "♣"};
        String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        for (String c : color) {
            for (String n : number) {
                list.add(c + n);
            }
        }

        list.add(" 大王");
        list.add(" 小王");

        //指定牌的价值
        /*牌上的数组到Map集合中判断是否存在
         * 存在:获取价值
         * 不存在:本身的数字就是价值*/
        hm.put("J", 11);
        hm.put("Q", 12);
        hm.put("K", 13);
        hm.put("A", 14);
        hm.put("2", 15);
        hm.put("小王", 50);
        hm.put("大王", 100);
    }

    public PokerGame() {
        //洗牌
        Collections.shuffle(list);

        //发牌
        ArrayList<String> lord = new ArrayList<>();
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();

        for (int i = 0; i < list.size(); i++) {
            String poker = list.get(i);
            if (i < 3) {
                lord.add(poker);
            } else if (i % 3 == 0) {
                player1.add(poker);
            } else if (i % 3 == 1) {
                player2.add(poker);
            } else {
                player3.add(poker);
            }
        }

        //排序
        order(lord);
        order(player1);
        order(player2);
        order(player3);

        //看牌
        lookPoker("底牌",lord);
        lookPoker("钢脑壳", player1);
        lookPoker("大帅比", player2);
        lookPoker("蛋筒", player3);

    }

    /*参数1:玩家名字
     * 参数2:每位玩家的牌*/
    private void lookPoker(String name, ArrayList<String> list) {
        System.out.print(name + ": ");
        for (String poker : list) {
            System.out.print(poker + " ");
        }
        System.out.println();
    }

    //排序
    private void order(ArrayList<String> list) {
        Collections.sort(list, new Comparator<>() {
            @Override
            public int compare(String o1, String o2) {
                /*o1:表示当前要插入到有序序列中的牌
                 * o2:表示已经 在有序序列中存在的牌
                 *
                 * 负数:o1小 插入到前面
                 * 正数:o1大,插入到后面
                 * 0:o1的数字跟o2的数字是一样的,需要按照花色再次排序*/

                //计算o1的花色和价值
                String color1 = o1.substring(0, 1);
                int value1 = getValue(o1);

                //计算o2的花色和价值
                String color2 = o2.substring(0, 1);
                int value2 = getValue(o2);
                int i = value1 - value2;
                return i == 0 ? color1.compareTo(color2) : i;
            }
        });
    }

    //计算牌的价值
    private int getValue(String poker) {
        String number = poker.substring(1);
        if (hm.containsKey(number)) {
            return hm.get(number);
        }
        return Integer.parseInt(number);
    }

在这里插入图片描述

3.两个实体类

3.1 User

package farmerAndLoder.domain;

import java.util.Objects;

public class User {
    private String userName;
    private String password;

    public User() {
    }

    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    /**
     * 获取
     * @return userName
     */
    public String getUserName() {
        return userName;
    }

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

    /**
     * 获取
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     * 设置
     * @param password
     */
    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 + "}";
    }
}

3.2 Poker

package farmerAndLoder.domain;

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

public class Poker extends JLabel implements MouseListener {
    //牌的名字
    private String name;

    //牌显示正面还是方面
    private boolean up;

    //是否可点击
    private boolean canClick = false;

    //当前状态,是否已经被点击
    private boolean clicked = false;

    public Poker(String name, boolean up) {
        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 void turnFront() {
        this.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\poker\\" + name + ".png"));
        this.up = true;
    }
    //显示方面
    public void turnRear(){
        this.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\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;

            //。。。牌被点击之后,还需要写移动牌的代码
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    /**
     * 获取
     * @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{name = " + name + ", up = " + up + ", canClick = " + canClick + ", clicked = " + clicked + "}";
    }
}

4.登录页面

在这里插入图片描述

4.1 验证码代码

新建一个util包,包中新建CodeUtil类,定义一个可以生成验证码的静态方法

验证码要求:

​ 包含大小写A-Z和数字0-9

​ 字母4个,数字1个

​ 字母和数字的位置是随机的。

完成上面的要求之后,自己思考,如果换一个验证码的需求是否可以完成呢?

比如1:包含大小写A-Z和数字0-9,总长度为5,内容随机的,生成的结果不包含大小写字母o

比如2:包含大小写A-Z和数字0-9,总共长度为4或5,内容都是随机的,但是数字不能连续

package farmerAndLoder.util;

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

public class CodeUtil {
    /*要求二:
        新建一个util包,包中新建CodeUtil类,定义一个可以生成验证码的静态方法
        验证码要求:
            包含大小写A-Z和数字0-9
            字母4个,数字1个
            字母和数字的位置是随机的。*/
    public static String getCode() {
        //0.创建集合
        ArrayList<Character> list = new ArrayList<>();

        //1.添加字母
        for (int i = 0; i < 26; i++) {
            list.add((char) ('a' + i));
            list.add((char) ('A' + i));
        }

//        System.out.println(list);

        //2.生成4个随机字母
        String result = "";
        Random r = new Random();
        for (int i = 0; i < 4; i++) {
            int index = r.nextInt(list.size());
            char c = list.get(index);
            result += c;
        }

        //3.拼接数字
        int num = r.nextInt(10);
        result += num;

        //4.将字符串变成数组
        char[] chars = result.toCharArray();

        //5.将最后一位数组与随机索引进行交换
        int index = r.nextInt(chars.length);
        char temp = chars[4];
        chars[4] = chars[index];
        chars[index] = temp;

        //6.将数组转换成字符串
        String code = new String(chars);

        return code;
    }

    //完成上面的要求之后,自己思考,如果换一个验证码的需求是否可以完成呢?
    //比如1:包含大小写A-Z和数字0-9,总长度为5,内容随机的,生成的结果不包含大小写字母o
    public static String getCode2() {
        //0.创建集合
        ArrayList<Character> list = new ArrayList<>();

        //1.添加字母
        for (int i = 0; i < 26; i++) {
            if (!('a' + i == 'o' && 'A' + i == 'O')) {
                list.add((char) ('a' + i));
                list.add((char) ('A' + i));
            }
        }

        for (int i = 0; i < 10; i++) {
            list.add((char) ('0' + i));
        }

        //2.生成5个随机字母
        String result = "";
        Random r = new Random();
        for (int i = 0; i < 5; i++) {
            int index = r.nextInt(list.size());
            char c = list.get(index);
            result += c;
        }
        return result;
    }

    //比如2:包含大小写A-Z和数字0-9,总共长度为4或5,内容都是随机的,但是数字不能连续
    public static String getCode3() {
        //0.创建集合
        ArrayList<Character> list = new ArrayList<>();

        //1.添加字母
        for (int i = 0; i < 26; i++) {
            list.add((char) ('a' + i));
            list.add((char) ('A' + i));
        }
        //2.添加数字
        for (int i = 0; i < 10; i++) {
            list.add((char) ('0' + i));
        }

        //3.随机字符串长度
        Random r = new Random();
        int stringLength = r.nextInt(2) + 4;

        //创建一个StringBuilder用来存储验证码
        StringBuilder sb = new StringBuilder();

        //4.向字符串中添加数据
        for (int i = 0; i < stringLength; i++) {
            //随机获取字符
            char c = getCharCode(list);
            //前一位和当前获取的字符是否是数字
            //是:重新获取
            //否:跳过
            boolean flag1 = false;
            if (i >= 1) {
                flag1 = isNumber(sb.substring(i - 1, i));
            }
            while (flag1){
                //判断当前字符是否是数字
                boolean flag2 = isNumber(String.valueOf(c));
                if (flag2){
                    c = getCharCode(list);
                }else {
                    break;
                }
            }
            sb.append(c);
        }
        return sb.toString();
    }

    //随机获取字符
    private static char getCharCode(ArrayList<Character> list) {
        Random r = new Random();
        int index = r.nextInt(list.size());
        char c = list.get(index);
        return c;
    }

    //判断验证码中截取的前一位是否是数字
    private static boolean isNumber(String c) {
        //判断c1是否是数字
        for (int j = 0; j < 10; j++) {
            if (c.equals(j + "")) {
                return true;
            }
        }
        return false;
    }
}


4.2 登录界面

在这里插入图片描述

package farmerAndLoder.game;

import farmerAndLoder.domain.User;
import farmerAndLoder.util.CodeUtil;

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

public class LoginJFrame extends JFrame implements MouseListener {
    static ArrayList<User> allUsers = new ArrayList<>();

    static {
        allUsers.add(new User("zhangsan", "123"));
        allUsers.add(new User("lisi", "1234"));
    }

    JButton login = new JButton();
    JButton register = new JButton();
    JTextField username = new JTextField();
    JPasswordField password = new JPasswordField();
    JTextField code = new JTextField();

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

    public LoginJFrame() {
        //初始化界面
        InitJFrame();

        //初始化组件,在这个界面中添加内容
        InitView();

        //显示界面
        this.setVisible(true);
    }

    //初始化组件,在这个界面中添加内容
    private void InitView() {
        //0.添加用户名文字
        Font usernameFont = new Font(null, 1, 16);
        JLabel usernameText = new JLabel("用户名");
        usernameText.setForeground(Color.WHITE);
        usernameText.setFont(usernameFont);
        usernameText.setBounds(140, 55, 55, 22);
        this.getContentPane().add(usernameText);

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

        //2.添加密码文字
        JLabel passwordText = new JLabel("密码");
        Font passwordFont = new Font(null, 1, 16);
        passwordText.setForeground(Color.WHITE);
        passwordText.setFont(passwordFont);
        passwordText.setBounds(197, 95, 40, 22);
        this.getContentPane().add(passwordText);

        //3.密码输入框
        password.setBounds(263, 87, 160, 30);
        this.getContentPane().add(password);

        //4.验证码提示
        JLabel codeText = new JLabel("验证码");
        Font codeFont = new Font(null, 1, 16);
        codeText.setForeground(Color.WHITE);
        codeText.setFont(codeFont);
        codeText.setBounds(215, 142, 55, 22);
        this.getContentPane().add(codeText);

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

        //6.获取正确的验证码
        String codeStr = CodeUtil.getCode3();
        Font rightCodeFont = new Font(null, 1, 15);
        rightCode.setForeground(Color.RED);
        rightCode.setFont(rightCodeFont);
        rightCode.setText(codeStr);
        rightCode.setBounds(400, 133, 100, 30);
        this.getContentPane().add(rightCode);

        //登录按钮
        login.setBounds(170, 310, 128, 47);
        login.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\login/登录按钮.png"));
        login.setBorderPainted(false);
        login.setContentAreaFilled(false);
        login.addMouseListener(this);
        this.getContentPane().add(login);

        //7.添加注册按钮
        register.setBounds(310, 310, 128, 47);
        register.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\login/注册按钮.png"));
        register.setBorderPainted(false);
        register.setContentAreaFilled(false);
        register.addMouseListener(this);
        this.getContentPane().add(register);


        //设置背景
        JLabel background = new JLabel(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\login/background.png"));
        background.setBounds(0, 0, 633, 423);
        this.getContentPane().add(background);
    }

    //初始化组件
    private void InitJFrame() {
        this.setSize(633, 423);//设置宽高
        this.setTitle("斗地主游戏 V1.0 登录");//设置标题
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);//设置关闭模式
        this.setLocationRelativeTo(null);//居中
        this.setAlwaysOnTop(true); //置顶
        this.setLayout(null);//取消内部默认布局
    }

    //点击
    @Override
    public void mouseClicked(MouseEvent e) {
        Object obj = e.getSource();
        if (obj == login) {
            //获取两个文本输入框中的文本
            String userNameInput = username.getText();
            String passwordInput = password.getText();

            //获取用户输入的验证码
            String codeInput = code.getText();

            //判断用户名和密码是否为空
            if (userNameInput.length() == 0 || passwordInput.length() == 0) {
                showJDialog("用户名或者密码为空");
                return;
            }

            //判断验证码是否为空
            if (codeInput.length() == 0) {
                showJDialog("验证码不能为空");
                return;
            }

            //判断验证码是否正确
            if (!codeInput.equalsIgnoreCase(rightCode.getText())) {
                showJDialog("验证码输入错误");
                return;
            }

            //判断集合中是否包含当前用户对象
            //其实就是验证用户名和密码是否相同
            //contains底层是依赖equals方法判断的,所以需要重写equals方法
            User userInfo = new User(userNameInput, passwordInput);
            if (allUsers.contains(userInfo)) {
                //关闭当前登录界面
                this.setVisible(false);
                //打开游戏的主界面
                new GameJFrame();
            } else {
                showJDialog("用户名或密码错误");
            }
        } else if (obj == register) {
            showJDialog("点击了注册按钮");
        } else if (obj == rightCode) {
            //获取一个新的验证码
            String code = CodeUtil.getCode3();
            System.out.println(code);
            rightCode.setText(code);
        }
    }

    private void showJDialog(String content) {
        JDialog jDialog = new JDialog();
        jDialog.setSize(200, 150);
        jDialog.setAlwaysOnTop(true);
        jDialog.setLocationRelativeTo(null);
        jDialog.setModal(true);

        JLabel warning = new JLabel(content);
        warning.setBounds(0, 0, 200, 150);
        jDialog.getContentPane().add(warning);
        jDialog.setVisible(true);
    }

    //按下不松
    @Override
    public void mousePressed(MouseEvent e) {
        Object obj = e.getSource();
        if (obj==login){
            login.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\login/登录按下.png"));
        } else if (obj==register) {
            register.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\login/注册按下.png"));
        }
    }

    //按下释放
    @Override
    public void mouseReleased(MouseEvent e) {
        Object obj = e.getSource();
        if (obj==login){
            login.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\login/登录按钮.png"));
        } else if (obj==register) {
            register.setIcon(new ImageIcon("day25_code\\src\\farmerAndLoder\\image\\login/注册按钮.png"));
        }
    }

    //鼠标划入
    @Override
    public void mouseEntered(MouseEvent e) {
        Object obj = e.getSource();
        if (obj == rightCode){
            System.out.println("刷新验证码");
        }
    }

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

5.游戏界面

在这里插入图片描述
在这里插入图片描述

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

public class GameJFrame extends JFrame implements ActionListener {

    //获取界面中的隐藏容器,现在统一获取了,后面直接用就可以了
    public static Container container = null;

    //管理抢地主和不抢两个按钮
    JButton landlord[] = new JButton[2];

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

    //游戏界面中地主的图标
    JLabel dizhu;

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

    //集合嵌套集合
    //大集合中有三个小集合
    //小集合中装着每一个玩家手上的牌
    //0索引:左边的电脑玩家
    //1索引:中间的自己
    //2索引:右边的电脑玩家
    ArrayList<ArrayList<Poker>> playerList = new ArrayList<>();

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

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

    //三个玩家前方的文本提示
    //0索引:左边的电脑玩家
    //1索引:中间的自己
    //2索引:右边的电脑玩家
    JTextField time[] = new JTextField[3];

    public GameJFrame() {
        //设置任务栏的图标
        setIconImage(Toolkit.getDefaultToolkit().getImage("farmerandlord\\image\\poker\\dizhu.png"));
        //设置界面
        initJframe();
        //添加组件
        initView();
        //界面显示出来
        //先展示界面再发牌,因为发牌里面有动画,界面不展示出来,动画无法展示
        this.setVisible(true);
        //初始化牌
        //准备牌,洗牌,发牌
        initCard();
        //打牌之前的准备工作
        //展示抢地主和不抢地主两个按钮并且再创建三个集合用来装三个玩家准备要出的牌
        initGame();
    }

    //打牌之前的准备工作
    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);

        //展示自己前面的倒计时文本
        for (JTextField field : time) {
            field.setText("倒计时30秒");
            field.setVisible(true);
        }

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == landlord[0]) {
            //点击抢地主
            time[1].setText("抢地主");
            ArrayList<Poker> player1 = playerList.get(1);
            player1.addAll(lordList);
            lordList.clear();
            order(playerList.get(1));
            for (Poker poker : player1) {
                poker.turnFront();
            }
            rePosition(playerList.get(1),1);
        } else if (e.getSource() == landlord[1]) {
            //点击不抢
            time[1].setText("不抢");
        } else if (e.getSource() == publishCard[1]) {
            //点击不要
            time[1].setText("不要");
        } else if (e.getSource() == publishCard[0]) {
            time[1].setText("出牌");
        }
    }

    //初始化牌(准备牌,洗牌,发牌)
    public void initCard() {
        //准备牌
        //把所有的牌,包括大小王都添加到牌盒cardList当中
        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(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) {
                //把底牌添加到集合中
                lordList.add(poker);
                move(poker, poker.getLocation(), new Point(270 + (75 * i), 10));
                continue;
            }

            //给三个玩家发牌
            if (i % 3 == 0) {
                //给左边的电脑发牌
                move(poker, poker.getLocation(), new Point(50, 60 + i * 5));
                player0.add(poker);
            } else if (i % 3 == 1) {
                //给中间的自己发牌
                move(poker, poker.getLocation(), new Point(180 + i * 7, 450));
                player1.add(poker);
                //把自己的牌展示正面
                poker.turnFront();
            } else if (i % 3 == 2) {
                //给右边的电脑发牌
                move(poker, poker.getLocation(), new Point(700, 60 + 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++) {
            order(playerList.get(i));
        }

    }

    //排序
    public void order(ArrayList<Poker> list) {
        //此处可以改为lambda表达式
        Collections.sort(list, new Comparator<Poker>() {
            @Override
            public int compare(Poker o1, Poker o2) {
                //获取o1的花色和价值
                int color1 = Integer.parseInt(o1.getName().substring(0, 1));
                int value1 = getValue(o1);

                //获取o2的花色和价值
                int color2 = Integer.parseInt(o2.getName().substring(0, 1));
                int value2 = getValue(o2);

                //倒序排列
                int flag = value2 - value1;

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

    //获取每一张牌的价值
    public int getValue(Poker poker) {
        //获取牌的名字 1-1
        String name = poker.getName();
        //获取牌的花色
        int color = Integer.parseInt(poker.getName().substring(0, 1));
        //获取牌对应的数字,同时也是牌的价值
        int value = Integer.parseInt(name.substring(2));

        //在本地文件中,每张牌的文件名为:数字1-数字2
        //数字1表示花色,数字2表示牌的数字
        //其中3~K对应的数字2,可以视为牌的价值
        //所以,我们单独判断大小王,A,2即可

        //计算大小王牌的价值
        if (color == 5){
            //小王的初始价值为1,在1的基础上加100,小王价值为:101
            //大王的初始价值为2,在2的基础上加100,大王价值为:102
           return value += 100;
        }

        //计算A的价值
        if (value == 1){
            //A的初始价值为1,在1的基础上加20,大王价值为:21
            return value += 20;
        }

        //计算2的价值
        if (value == 2){
            //2的初始价值为2,在2的基础上加30,大王价值为:32
            return value += 30;
        }

        //如果不是大小王,不是A,不是2,牌的价值就是牌对应的数字
        return value;
    }

    //添加组件
    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);


        //创建三个玩家前方的提示文字:倒计时
        //每个玩家一个
        //左边的电脑玩家是0
        //中间的自己是1
        //右边的电脑玩家是2
        for (int i = 0; i < 3; i++) {
            time[i] = new JTextField("倒计时:");
            time[i].setEditable(false);
            time[i].setVisible(false);
            container.add(time[i]);
        }
        time[0].setBounds(140, 230, 60, 20);
        time[1].setBounds(374, 360, 60, 20);
        time[2].setBounds(620, 230, 60, 20);


        //创建地主图标
        dizhu = new JLabel(new ImageIcon("images/dizhu.png"));
        dizhu.setVisible(false);
        dizhu.setSize(40, 40);
        container.add(dizhu);



    }

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

    //移动牌(有移动的动画效果)
    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 rePosition(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);
            move(poker, poker.getLocation(), p);
            container.setComponentZOrder(poker, 0);
            if (flag == 1)
                p.x += 21;
            else
                p.y += 15;
        }
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1475493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【蓝桥杯】快读|min和max值的设置|小明和完美序列|​顺子日期​|星期计算|山

目录 一、输入的三种方式 1.最常见的Scanner的输入方法 2.数据多的时候常用BufferedReader快读 3.较麻烦的StreamTokenizer快读&#xff08;用的不多&#xff09; StreamTokenizer常见错误&#xff1a; 二、min和max值的设置 三、妮妮的翻转游戏 四、小明和完美序列 五…

如何删除视频中不想要的部分?分享实用工具和步骤!

在数字化时代&#xff0c;视频已成为我们生活中不可或缺的一部分。无论是观看电影、记录生活&#xff0c;还是制作专业的广告、教学材料&#xff0c;我们都需要对视频进行编辑处理。其中&#xff0c;删除视频中不想要的部分是最常见的需求之一。那么&#xff0c;如何轻松实现这…

Pytorch添加自定义算子之(5)-配置GPU形式的简单add自定义算子

参考:https://zhuanlan.zhihu.com/p/358778742 一、头文件 命名为:add2.h void launch_add2(float *c,const float *a,const float *b,int n);

Jvm之内存泄漏

1 内存溢出 1.1 概念 java.lang.OutOfMemoryError&#xff0c;是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现OutOfMemoryError。产生该错误的原因主要包括&#xff1a;JVM内存过小。程序不严密&#xff0c;产生了过多的垃圾。 程序体现: 内…

Win UI3开发笔记(四)设置主题续

上文讲到过关于界面和标题栏以及普通文本的主题设置&#xff0c;这篇说一下关于对话框的主题设置。 我最终没找到办法&#xff0c;寻求办法的朋友可以不用接着看了&#xff0c;以下只是过程。 一个对话框包括标题部分、内容部分和按钮部分&#xff0c;其中&#xff0c;在Cont…

论文笔记:A survey on zero knowledge range proofs and applications

https://link.springer.com/article/10.1007/s42452-019-0989-z 描述了构建零知识区间证明&#xff08;ZKRP&#xff09;的不同策略&#xff0c;例如2001年Boudot提出的方案&#xff1b;2008年Camenisch等人提出的方案&#xff1b;以及2017年提出的Bulletproofs。 Introducti…

Python 全栈系列227 部署chatglm3-API接口

说明 上一篇介绍了基于算力租用的方式部署chatglm3, 见文章&#xff1b;本篇接着看如何使用API方式进行使用。 内容 1 官方接口 详情可见接口调用文档 调用有两种方式&#xff0c;SDK包和Http。一般来说&#xff0c;用SDK会省事一些。 以下是Python SDK包的git项目地址 安…

ChatGPT 正测试Android屏幕小组件;联想ThinkBook 推出透明笔记本电脑

▶ ChatGPT 测试屏幕小组件 近日 ChatGPT 正在测试 Android 平台上的屏幕小组件&#xff0c;类似于手机中的悬浮窗&#xff0c;按住 Android 手机主屏幕上的空白位置就可以调出 ChatGPT 的部件菜单。 菜单中提供了许多选项&#xff0c;包括文本、语音和视频查询的快捷方式&…

vue3的echarts从后端获取数据,用于绘制图表

场景需求&#xff1a;后端采用flask通过pymysql从数据库获取数据&#xff0c;并返回给前端。前端vue3利用axios获取数据并运用到echarts绘制图表。 第一步&#xff0c;vue中引入echarts 首先vue下载echarts npm install echarts 然后在main.js文件写如下代码 import {create…

【appium】App类型、页面元素|UiAutomator与appium|App元素定位

目录 一、App前端基础知识 1、App类型划分 2、App类型对比 3、App页面元素 App页面元素分为布局和控件两种 常见布局&#xff1a; 常见控件&#xff1a;定位软件&#xff1a;appium和sdk自带的uiautomatorviewer都可以定位 二、App元素定位 1、id定位 2、text定位 3…

RISC-V SoC + AI | 在全志 D1「哪吒」开发板上,跑个 ncnn 神经网络推理框架的 demo

引言 D1 是全志科技首款基于 RISC-V 指令集的 SoC&#xff0c;主核是来自阿里平头哥的 64 位的 玄铁 C906。「哪吒」开发板 是全志在线基于全志科技 D1 芯片定制的 AIoT 开发板&#xff0c;是目前还比较罕见的使用 RISC-V SoC 且可运行 GNU/Linux 操作系统的可量产开发板。 n…

Linux:Ansible的常用模块

模块帮助 ansible-doc -l 列出ansible的模块 ansible-doc 模块名称 # 查看指定模块的教程 ansible-doc command 查看command模块的教程 退出教程时候建议不要使用ctrlc 停止&#xff0c;某些shell工具会出现错误 command ansible默认的模块,执行命令&#xff0c;注意&#x…

【MySQL】DQL

DQL&#xff08;数据查询语言&#xff09;用于在MySQL数据库中执行数据查询操作。它主要包括SELECT语句&#xff0c;用于从表中检索数据。 0. 基本语法 SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后条件列表 ORDER BY 排序字段列表 …

【深度学习】Pytorch教程(八):PyTorch数据结构:2、张量的数学运算(6):高维张量:乘法、卷积(conv2d~四维张量;conv3d~五维张量)

文章目录 一、前言二、实验环境三、PyTorch数据结构1、Tensor&#xff08;张量&#xff09;1. 维度&#xff08;Dimensions&#xff09;2. 数据类型&#xff08;Data Types&#xff09;3. GPU加速&#xff08;GPU Acceleration&#xff09; 2、张量的数学运算1. 向量运算2. 矩阵…

NerfStudio安装及第一个场景重建

NerfStudio文档是写在windows和linux上安装&#xff0c;本文记录Linux安装的过程&#xff0c;且我的cuda是11.7 创建环境 conda create --name nerfstudio -y python3.8 conda activate nerfstudio python -m pip install --upgrade pip Pytorch要求2.0.1之后的,文档推荐cud…

Vue:【亲测可用】父组件数组包对象,传给子组件对象,子组件修改属性(字段)后,父组件没有更新

场景&#xff1a;vue中父组件数组包对象&#xff0c;传给子组件对象&#xff0c;子组件修改属性&#xff08;字段&#xff09;后&#xff0c;父组件没有更新 代码&#xff1a; # 父组件 <div v-for"(object, name, index) in arr" :key"index"><…

autocrlf和safecrlf

git远程拉取及提交代码&#xff0c;windows和linux平台换行符转换问题&#xff0c;用以下两行命令进行配置&#xff1a; git config --global core.autocrlf false git config --global core.safecrlf true CRLF是windows平台下的换行符&#xff0c;LF是linux平台下的换行符。…

jvm常用参数配置

一、 常用参数 -Xms JVM启动时申请的初始Heap值&#xff0c;默认为操作系统物理内存的1/64但小于1G。默认当空余堆内存大于70%时&#xff0c;JVM会减小heap的大小到-Xms指定的大小&#xff0c;可通过-XX:MaxHeapFreeRation来指定这个比列。Server端JVM最好将-Xms和-Xmx设为相同…

LVGL 环境搭建-基于WSL

背景说明 小白刚开始接触LVGL&#xff0c;前些日子狠心花198元入手了一块堪称LVGL 入门利器~HMI-Board 开发板&#xff0c;虽然有RT-Thread 集成好的LVGL 环境&#xff0c;只需要几个步骤就能成功把lvgl 的示例运行起来&#xff0c;对于爱折腾的我来说&#xff0c;过于简单也并…

Nginx高级技巧:实现负载均衡和反向代理

文章目录 Nginx概述Nginx作用正向代理反向代理负载均衡动静分离 Nginx的安装 -->Docker3.1 安装Nginx3.2 Nginx的配置文件3.3 修改docker-compose文件 Nginx源码安装nginx常用命令nginx配置文件配置文件位置配置文件结构详情 Nginx的反向代理【重点】基于Nginx实现反向代理4…