28-阶段项目:斗地主小游戏

斗地主小游戏

分析1

  • 刚开始写,是不是没有思路?没关系!

  • 你就结合实际生活来想啊!

  • 比如,你有一天非常的郁闷,想要找你的两位好基友一起斗地主!

  • 那么,第一步是不是要去超市或商店购买一副牌啊!

    在这里插入图片描述


  • 然后,第二步是不是洗牌啊!(洗牌)

    在这里插入图片描述


  • 之后,第三步是不是发牌啊!(发牌)

    在这里插入图片描述


1、准、洗、发、看牌
扑克游戏类
package com.app.comprehensive12.doudizhu.entity;

import java.util.ArrayList;
import java.util.Collections;

/*
    扑克游戏类
 */
public class PokerGame {
    // 首先定义一个静态的集合,用于存储组合好的牌(牌盒)
    static ArrayList<String> cards = new ArrayList<>();

    // 定义4个集合,分别用于存储:底牌、玩家1、玩家2、玩家3的牌
    // 底牌(地主牌)
    ArrayList<String> lordCards = new ArrayList<>();
    // 玩家1
    ArrayList<String> player1 = new ArrayList<>();
    // 玩家2
    ArrayList<String> player2 = new ArrayList<>();
    // 玩家3
    ArrayList<String> player3 = new ArrayList<>();

    /*
        准备牌:
            可以用静态代码块来写准备牌的逻辑代码
            静态代码块是随着类的加载而加载的,而且只执行一次。
            为什么用静态代码块?
            答:你想啊!那你和两位基友斗地主的时候,每打完一局,是不是需要重新洗牌、发牌..
               不可能说打完一局,再打一局的时候,再买一副牌吧?
               所以,用静态代码块,只执行一次准备牌的程序。
        花色:"♦", "♣", "♥", "♠"
        牌号:"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
     */
    static {
        // 1.定义两个数组,分别用于存储牌的花色、号码
        String[] cardColor = {"♦", "♣", "♥", "♠"};
        String[] cardNumber = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        // 2.组合牌:花色+号码
        // 外循环:遍历牌花色的数组,依次获取每一种花色
        for (String c : cardColor) {
            // 内循环:遍历牌号码的数组,依次获取每一个号码
            for (String n : cardNumber) {
                // 组合牌:花色+号码
                // ♦3 ♦4 ..
                String card = c + n;
                // 将每张组合好的牌放进牌盒中
                cards.add(card);
            }
        }

        // 3.将大小王放进牌盒中
        Collections.addAll(cards, "小王", "大王");
    }

    public PokerGame() {
        // 洗牌:打乱牌的顺序
        Collections.shuffle(cards);

        // 发牌
        sendCards();

        // 看牌:遍历
        lookCards("底牌", lordCards);
        lookCards("钢脑壳", player1);
        lookCards("大帅比", player2);
        lookCards("蛋筒", player3);
    }

    /**
     * 看牌
     * @param playerName    玩家昵称
     * @param list          每个玩家的牌的集合
     */
    public void lookCards(String playerName, ArrayList<String> list) {
        System.out.print(playerName + "——> ");
        // 遍历当前玩家的牌的集合,依次获取每张牌
        for (String card : list) {
            // 打印牌到控制台,每张牌之间用空格隔开
            System.out.print(card + " ");
        }
        // 当前玩家的所有牌打印完毕后,打印个换行
        System.out.println();
    }


    /**
     * 发牌
     */
    public void sendCards() {
        // 2.遍历牌盒,依次获取每张牌
        for (int i = 0; i < cards.size(); i++) {
            // i: 索引(牌序)
            // 获取当前这张牌
            String card = cards.get(i);

            // a.先将3张底牌拿出
            // 判断i是否小于等于2
            if (i <= 2) { // i: 0 1 2
                // 是,则将当前这张牌放进底牌集合中
                lordCards.add(card);
                // 结束当次循环的执行,进入下一次循环
                continue;
            }

            // b.轮流给三个玩家发牌(求余法)
            // 判断i%3是否等于0
            if (i % 3 == 0) {
                // 是,则给玩家1发牌
                player1.add(card);
            } else if (i % 3 == 1) { // 判断i%3是否等于1
                // 是,则给玩家2发牌
                player2.add(card);
            } else {
                // 否,说明以上两种情况都不符合,则给玩家3发牌
                player3.add(card);
            }
        }
    }
}

程序启动入口类
package com.app.comprehensive12.doudizhu.start;

import com.app.comprehensive12.doudizhu.entity.PokerGame;

public class App {
    public static void main(String[] args) {
        // 程序启动入口
        new PokerGame();
    }
}

测试结果
底牌——> ♠K ♦6 ♠7 
钢脑壳——> ♥5 小王 ♣4 ♥2 ♣9 ♠3 ♦J ♠Q ♣3 ♥3 ♥A ♠J ♦Q ♣K ♠5 ♥J ♥K 
大帅比——> ♥10 ♣6 ♥9 ♠2 ♥4 ♠9 ♦A ♥Q ♦8 ♣5 ♣8 ♥8 ♠4 ♣Q ♦7 ♠10 ♦2 
蛋筒——> ♠6 ♦10 ♦3 ♦9 ♣A ♦4 ♦5 ♣10 ♣J ♠A 大王 ♦K ♠8 ♣7 ♥6 ♥7 ♣2 

Process finished with exit code 0



分析2

  • 那很多人打牌都有一个习惯,那就是给自己的牌进行排序!

    在这里插入图片描述


  • 因此分析1中的做法,是不符合的,发完牌,底牌和每个玩家的牌都是乱的!


1、准、洗、发、看牌
方式一:利用序号进行排序
  • 如果原始数据的规律非常复杂,我们可以先手动排序让每一个数据跟唯一的序号产生对应关系。
  • 序号就是数字,规律非常简单,后续的所有操作,我们以序号为准。
  • 当真正需要操作原始数据的时候,再通过序号找到原始数据即可。

扑克游戏类
package com.app.comprehensive12.doudizhu2.entity;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

/*
    扑克游戏类
 */
public class PokerGame {
    /*
        首先定义一个静态的HashMap集合,用于存储组合好的扑克牌(牌盒)
        键:序号,值:扑克牌
        此时我们只要把扑克牌与序号产生对应(键值对)关系就可以了,不需要按照序号进行排序,所以用HashMap集合即可!
     */
    static HashMap<Integer, String> pokerList = new HashMap<>();
    // 定义一个静态的ArrayList集合,用于存储每张扑克牌的序号
    static ArrayList<Integer> serialNumberList = new ArrayList<>();

    /*
        定义4个TreeSet集合,分别用于存储:底牌、玩家1、玩家2、玩家3的所有扑克牌的序号
        TreeSet集合默认会将数据进行升序排列
     */
    TreeSet<Integer> lordCards = new TreeSet<>();
    TreeSet<Integer> player1 = new TreeSet<>();
    TreeSet<Integer> player2 = new TreeSet<>();
    TreeSet<Integer> player3 = new TreeSet<>();

    /*
        准备牌:
            可以用静态代码块来写准备牌的逻辑代码
            静态代码块是随着类的加载而加载的,而且只执行一次。
            为什么用静态代码块?
            答:你想啊!那你和两位基友斗地主的时候,每打完一局,是不是需要重新洗牌、发牌..
               不可能说打完一局,再打一局的时候,再买一副牌吧?
               所以,用静态代码块,只执行一次准备牌的程序。
        花色:"♦", "♣", "♥", "♠"
        牌号:"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
     */
    static {
        // 1.定义两个数组,分别用于存储扑克牌的所有花色、号码
        String[] pokerColor = {"♦", "♣", "♥", "♠"};
        String[] pokerNumber = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        /*
            2.组合扑克牌:花色+号码
              细节:先遍历号码数组,再遍历花色数组
                   为什么?
                   举例:比如用外循环先遍历号码数组,此时遍历到数字3,
                        然后再用内循环遍历花色数组,此时遍历到♦,拼接时,就会得到 ♦3,
                        此时内循环再次循环,就会得到♣,拼接时,就会得到♣3,
                        此时内循环再次循环,就会得到♥,拼接时,就会得到♥3,
                        此时内循环再次循环,就会得到♠,拼接时,就会得到♠3,
                        此时内循环结束,依次得到了 ♦3 ♣3 ♥3 ♠3 这四张扑克牌
                        然后外循环再遍历下一个数字,再拼接花色,依次类推!
         */
        // 扑克牌的序号,从1开始
        int serialNumber = 1;
        // 外循环:遍历号码数组,依次获取每一个数字
        for (String n : pokerNumber) {
            // 内循环:遍历花色数组,依次获取每一种花色
            for (String c : pokerColor) {
                // 按照键值对关系,将 序号=扑克牌,添加到扑克牌盒中
                pokerList.put(serialNumber, c + n);
                // 将当前这张扑克牌的序号添加到序号集合中
                serialNumberList.add(serialNumber);
                // 序号+1,表示下一张扑克牌的序号
                serialNumber++;
            }
        }

        // 3.循环结束!52张扑克牌已准备好!
        // 按照键值对关系将小王放进扑克牌盒中
        pokerList.put(serialNumber, "小王");
        // 将小王的序号添加到序号集合中
        serialNumberList.add(serialNumber);
        // 序号+1,表示下一张扑克牌的序号
        serialNumber++;
        
        // 按照键值对关系将大王放进扑克牌盒中
        pokerList.put(serialNumber, "大王");
        // 将大王的序号添加到序号集合中
        serialNumberList.add(serialNumber);
    }

    public PokerGame() {
        // 洗牌:打乱扑克牌的所有序号
        Collections.shuffle(serialNumberList);

        // 发牌
        sendCards();

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

    /**
     * 看牌
     * @param playerName    玩家名字
     * @param ts            每个玩家的扑克牌序号集合
     */
    public void lookCards(String playerName, TreeSet<Integer> ts) {
        System.out.print(playerName + ": ");
        // 遍历当前玩家的扑克牌序号的集合,依次获取每个序号
        for (int serialNumber : ts) {
            // 根据当前的序号(键)获取到对应的扑克牌(值)
            String poker = pokerList.get(serialNumber);
            // 打印扑克牌到控制台,每张扑克牌之间用空格隔开
            System.out.print(poker + " ");
        }
        // 当前玩家的所有扑克牌都打印完之后,打印个换行
        System.out.println();
    }


    /**
     * 发牌
     */
    public void sendCards() {
        // 1.遍历序号集合,依次获取每个序号
        for (int i = 0; i < serialNumberList.size(); i++) {
            // i: 索引
            // serialNumberList.get(i): 扑克牌的序号
            // 获取当前这张扑克牌的序号
            int serialNumber = serialNumberList.get(i);

            // a.先将3张底牌的序号拿出
            // 判断i是否小于等于2
            if (i <= 2) { // i: 0 1 2
                // 是,则将当前这张扑克牌的序号放进底牌集合中
                lordCards.add(serialNumber);
                // 结束当次循环的执行,进入下一次循环
                continue;
            }

            // b.轮流给三个玩家发扑克牌的序号(求余法)
            // 判断i%3是否等于0
            if (i % 3 == 0) {
                // 是,则给玩家1发
                player1.add(serialNumber);
            } else if (i % 3 == 1) { // 判断i%3是否等于1
                // 是,则给玩家2发
                player2.add(serialNumber);
            } else {
                // 否,说明以上两种情况都不符合,则给玩家3发
                player3.add(serialNumber);
            }
        }
    }
}

程序启动入口类
package com.app.comprehensive12.doudizhu2.start;

import com.app.comprehensive12.doudizhu2.entity.PokerGame;

public class App {
    public static void main(String[] args) {
        // 程序启动入口
        new PokerGame();
    }
}

测试结果
底牌: ♥3 ♦8 ♦9 
钢脑壳: ♠3 ♦4 ♣5 ♦7 ♣7 ♠7 ♣8 ♥8 ♣9 ♥9 ♦10 ♣10 ♦J ♣J ♦Q ♠2 大王 
大帅比: ♦3 ♣3 ♣4 ♦5 ♠5 ♦6 ♣6 ♠6 ♠8 ♠10 ♣Q ♥Q ♦A ♣A ♥A ♥2 小王 
蛋筒: ♥4 ♠4 ♥5 ♥6 ♥7 ♠9 ♥10 ♥J ♠J ♠Q ♦K ♣K ♥K ♠K ♠A ♦2 ♣2 

Process finished with exit code 0



分析3

1、准、洗、发、看牌
方式二:给每一张牌计算价值

在这里插入图片描述


扑克游戏类
package com.app.comprehensive12.doudizhu3.entity;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

/*
    扑克游戏类
 */
public class PokerGame {
    /*
        键:扑克牌,值:价值
        因此,需要定义Map集合来存储键值对关系的数据
        扑克牌 = 价值
     */
    static HashMap<String, Integer> pokerValueList = new HashMap<>();
    // 扑克牌盒
    static ArrayList<String> pokerList = new ArrayList<>();
    // 定义4个ArrayList集合,分别用于存储:底牌、玩家1、玩家2、玩家3的所有扑克牌
    ArrayList<String> lordPoker = new ArrayList<>();
    ArrayList<String> player1 = new ArrayList<>();
    ArrayList<String> player2 = new ArrayList<>();
    ArrayList<String> player3 = new ArrayList<>();

    // 准备扑克牌
    static {
        // 将扑克牌的花色和号码用数组存储起来
        String[] pokerColor = {"♦", "♣", "♥", "♠"};
        String[] pokerNumber = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        // 将花色+号码组合起来,得到的就是扑克牌
        for (String n : pokerNumber) {
            for (String c : pokerColor) {
                pokerList.add(c + n);
            }
        }

        // 将大小王放进扑克牌盒中
        Collections.addAll(pokerList, "小王", "大王");

        // 定义扑克牌的价值
        // 数字3~10的价值直接使用数字本身就好了!
        pokerValueList.put("J", 11);
        pokerValueList.put("Q", 12);
        pokerValueList.put("K", 13);
        pokerValueList.put("A", 14);
        pokerValueList.put("2", 15);
        pokerValueList.put("小王", 50);
        pokerValueList.put("大王", 100);
    }

    public PokerGame() {
        // 洗牌:打乱
        Collections.shuffle(pokerList);

        // 发牌
        sendPokers();

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

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

    /**
     * 排序
     *
     * @param list 玩家的所有扑克牌的集合
     */
    public void order(ArrayList<String> list) {
        // 自定义比较规则
        Collections.sort(list, (o1, o2) -> {
            /*
                o1:表示当前要插入到有序序列中的牌
                o2:表示已经存在有序序列中的牌

                负数:o1小,插入到前面
                正数:o1大,插入到后面
                0:  o1和o2一样大,此时需要按照花色进行排序
             */
            // 1.计算o1的花色和价值
            String color1;
            int value1;
            // 判断o1是否为小王 或 大王
            if (checkPoker(o1)) {
                // 是,则直接将小王或大王赋值给color1
                color1 = o1;
                // 获取扑克牌的价值
                value1 = getValue(o1);
            } else {
                // 否,则从0索引截取到1索引
                // 例如:♦3,从0到1,截取到3的花色:♦
                color1 = o1.substring(0, 1);
                value1 = getValue(o1);
            }

            // 2.计算o2的花色和价值
            String color2;
            int value2;
            // 判断o1是否为小王 或 大王
            if (checkPoker(o2)) {
                // 是,则直接将小王或大王赋值给color2
                color2 = o2;
                value2 = getValue(o2);
            } else {
                // 否,则从0索引截取到1索引
                color2 = o2.substring(0, 1);
                value2 = getValue(o2);
            }

            // 3.比较o1和o2的价值
            int i = value1 - value2;
            // 如果o1和o2的价值一样大,此时需要按照花色进行排序
            return i == 0 ? color1.compareTo(color2) : i;
        });
    }


    /**
     * 获取牌的价值
     *
     * @param poker 扑克牌
     * @return 存在,则返回poker的价值,否则返回poker转换后的本身
     */
    public int getValue(String poker) {
        String number;

        // 判断poker是否为大小王
        if (checkPoker(poker)) {
            // 是大小王,直接赋值给number
            number = poker;
        } else {
            // 否,则说明不是大小王,则从1索引开始截取到结束
            number = poker.substring(1);
        }

        // 判断number是否存在于Map集合中
        if (pokerValueList.containsKey(number)) {
            // 是,说明存在,返回number的价值
            return pokerValueList.get(number);
        } else {
            // 否,说明不存在,则转换类型
            return Integer.parseInt(number);
        }
    }

    /**
     * 判断牌是否为大小王
     *
     * @param poker 牌
     * @return 是大小王,返回true,否则返回false
     */
    public boolean checkPoker(String poker) {
        if (poker.equals("小王") || poker.equals("大王")) {
            return true;
        }
        return false;
    }

    /**
     * 看牌
     *
     * @param playerName 玩家名字
     * @param list       玩家的所有扑克牌的集合
     */
    public void lookPokers(String playerName, ArrayList<String> list) {
        System.out.print(playerName + ": ");
        for (String poker : list) {
            System.out.print(poker + " ");
        }
        System.out.println();
    }

    /**
     * 发牌
     */
    public void sendPokers() {
        // 遍历牌盒,依次获取每张牌
        for (int i = 0; i < pokerList.size(); i++) {
            // i: 索引
            // pokerList.get(i): 每张扑克牌
            String poker = pokerList.get(i);

            // 将底牌拿出来
            if (i <= 2) {
                lordPoker.add(poker);
                continue;
            }

            // 轮流给三个玩家发牌
            if (i % 3 == 0) {
                player1.add(poker);
            } else if (i % 3 == 1) {
                player2.add(poker);
            } else {
                player3.add(poker);
            }
        }
    }
}

程序启动入口类
package com.app.comprehensive12.doudizhu3.start;

import com.app.comprehensive12.doudizhu3.entity.PokerGame;

public class App {
    public static void main(String[] args) {
        // 程序启动入口
        new PokerGame();
    }
}

测试结果
底牌: ♣5 ♦J ♦2 
钢脑壳: ♠3 ♣3 ♦6 ♠8 ♦8 ♥10 ♦10 ♠J ♥J ♠Q ♣Q ♦Q ♥K ♣A ♦A ♠2 ♣2 
大帅比: ♥3 ♣4 ♦4 ♣6 ♣7 ♥7 ♣8 ♠9 ♣9 ♥9 ♦9 ♠10 ♣10 ♣J ♥Q ♦K ♠A 
蛋筒: ♦3 ♠4 ♥4 ♠5 ♥5 ♦5 ♠6 ♥6 ♠7 ♦7 ♥8 ♠K ♣K ♥A ♥2 小王 大王 

Process finished with exit code 0



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值