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

综合项目(斗地主)


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



java 复制代码
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(利用序号进行排序)


java 复制代码
//准备牌
    //牌盒
    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(给每一张牌计算价值)

价值:积分、得分

java 复制代码
//准备牌
    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

java 复制代码
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

java 复制代码
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,内容都是随机的,但是数字不能连续

java 复制代码
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 登录界面

java 复制代码
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.游戏界面


java 复制代码
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;
        }
    }

}
相关推荐
安之若素^11 分钟前
启用不安全的HTTP方法
java·开发语言
ruanjiananquan9917 分钟前
c,c++语言的栈内存、堆内存及任意读写内存
java·c语言·c++
chuanauc44 分钟前
Kubernets K8s 学习
java·学习·kubernetes
一头生产的驴1 小时前
java整合itext pdf实现自定义PDF文件格式导出
java·spring boot·pdf·itextpdf
YuTaoShao1 小时前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵
zzywxc7871 小时前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring
YuTaoShao3 小时前
【LeetCode 热题 100】56. 合并区间——排序+遍历
java·算法·leetcode·职场和发展
程序员张33 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
llwszx6 小时前
深入理解Java锁原理(一):偏向锁的设计原理与性能优化
java·spring··偏向锁
云泽野7 小时前
【Java|集合类】list遍历的6种方式
java·python·list