Java -- 斗地主(后台版)

@[TOC](Java – 斗地主(后台版))

总纲

在这里插入图片描述

前期准备

  1. 创建程序启动入口App
public class App {
    public static void main(String[] args) {
        /*
            完成控制台的三步:
                准备牌
                发牌
                洗牌

            "♦", "♣", "♥", "♠"
            "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
         */
    }
}
  1. 创建PokerGame
public class PokerGame {

}
  1. PokerGame类中添加空参构造器
public class PokerGame {

    public PokerGame() {
        // 准备牌
        // 洗牌
        // 发牌
        // 看牌
    }
}
  1. 创建App中引用(创建)PokerGame进入程序
// 进入程序
new PokerGame();

1.准备牌

在这里插入图片描述

1.1 准备牌思路

  1. 创建连个数组,分别存储花色和数字
  2. 创建一个集合,作为牌盒,后期会抽取为成员变量
  3. 遍历花色数组
  4. 遍历数字数组
  5. 将遍历获得的花色和数字拼接起来,添加到集合(牌盒)中
  6. 向牌盒中添加小王和大王

1.2 代码实现

  1. 准备一副牌,然后多次使用,此时可以用静态代码块进行编写.
    静态代码块的特点: 随着类的加载而加载,并且只执行一次
static {
        // 准备牌:
        // 1.创建数组存储花色   "♦", "♣", "♥", "♠"
        String[] color = {"♦", "♣", "♥", "♠"};
        // 2.创建数组存储数字   "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
        String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
        // 3.创建一个集合作为牌盒
        ArrayList<String > list = new ArrayList<>();
        // 4.循环花色数组,获取每一种花色
        for (String c : color) {
            // 5.循环数字数组,获取每一个数字
            for (String n : number) {
                // 6.将遍历获得的 花色 和 数字 拼接起来,并添加到集合中
                list.add(c + n);
            }
        }
        // 7.添加大小王
        list.add("小王");
        list.add("大王");
    }
  1. 由于牌盒list需要在构造方法内使用,所以将list集合定义为成员变量
// 3.创建一个集合作为牌盒
// 添加static关键字,因为静态只能访问静态资源
static ArrayList<String > list = new ArrayList<>();

2.洗牌

在这里插入图片描述

2.1 思路

在构造方法中,直接使用Collections工具类的shuffle方法即可

// 洗牌
Collections.shuffle(list);
System.out.println(list);

3.发牌

在这里插入图片描述

3.1 发牌思路

  1. 创建四个集合,分别存储 底牌 玩家1,玩家2,玩家3 的牌
  2. 遍历集合
  3. 将获取的前三张牌作为底牌,存储 底牌(lord) 中
  4. 将剩下的牌轮流发给三位玩家

3.2 代码实现

// 1.创建四个结合分别存储 底牌 ,玩家1,玩家2,玩家3
        ArrayList<String> lord = new ArrayList<>();
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();
        // 2.遍历集合,获取每一张牌,将前三张作为底牌,后面的牌轮流发给三个玩家
        // 2.1 遍历集合
        for (int i = 0; i < list.size(); i++) {
            String poker = list.get(i);
            
            // 2.2 将前三张牌作为底牌存起来
            if (i <= 2){
                lord.add(poker);
                continue;
            }

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

4.看牌(可省略 – 只做验证使用)

4.1 思路

定义一个方法,实现看牌功能

  1. 打印玩家名字
  2. 遍历集合,获取每一张牌
  3. 将每一张牌进行打印
  4. 打印一个回车换行

4.2 代码实现

  1. 定义方法
/**
     * 看牌
     * @param name 每位玩家的名字
     * @param list 每一位玩家的牌
     */
    private void lookPoker(String name, ArrayList<String> list) {

        // 1.打印玩家名字
        System.out.print(name + ": ");
        // 2.遍历集合,拼接字符串
        for (String poker : list) {
            System.out.print(poker + " ");
        }
        System.out.println();
    }
  1. 调用方法
// 看牌
lookPoker("底牌",lord);
lookPoker("玩家1",player1);
lookPoker("玩家2",player2);
lookPoker("玩家3",player3);

5.排序(两种方式)

在这里插入图片描述

5.1 第一种方式(利用序号进行排序)

5.1.1 分析

在这里插入图片描述
在这里插入图片描述
先把牌进行手动排列,再让排列后的牌和1,2,3…进行对应,对应的数字越大,牌也就越大.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.1.2 思路

1.准备牌思路
  1. 创建Map集合,让序号和每一张牌产生联系
  2. 创建list集合,存储生成的序号
  3. 创建两个集合,分别存储 花色 和 数字
  4. 创建 初始序号
  5. 循环数字数组
  6. 循环花色数组
  7. 把获取到的 数字 和 花色 进行拼接,并添加到Map集合中
  8. 让序号自增
  9. 将序号添加到list集合中
  10. 添加小王,序号自增,再添加大王
2.洗牌思路
  1. 利用Collections工具类的shuffle方法进行洗牌
3.排序(发牌)思路
  1. 利用TreeSet集合进行优化,因为TreeSet集合会进行自动排序
  2. 创建四个TreeSet集合
  3. 遍历list序号集合
  4. 向四个集合中添加元素
4.看牌思路

定义方法,实现看牌功能
1.创建 StringJoiner对象,设置分隔符
2. 遍历list集合,通过键找值的方式,获取每一张牌的牌面
3. 将每一张面通过sj对象进行拼接
4. 将获得牌面进行拼接

5.1.3 代码实现

1.前期准备
  1. 创建程序的启动入口
  2. 创建程序类PokerGame
public class PokerGame {

    // 牌盒 Map
    static {
        // 1.创建数组存储花色   "♦", "♣", "♥", "♠"
        String[] color = {"♦", "♣", "♥", "♠"};
        // 2.创建数组存储数字   "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
        String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
    }

    public PokerGame() {

    }
}
2.准备牌
// 牌盒 Map
    static HashMap<Integer, String> hm = new HashMap<>();
    // 序号
    static ArrayList<Integer> list = new ArrayList<>();

    static {
        // 1.创建数组存储花色   "♦", "♣", "♥", "♠"
        String[] color = {"♦", "♣", "♥", "♠"};
        // 2.创建数组存储数字   "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
        String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        // 3.定义一个变量,存储初始序号
        int serialNumber = 1;
        // 4.循环数字数组
        for (String n : number) {
            // 5.循环花色数组
            for (String c : color) {
                // 6.让序号和牌之间产生联系,并存入Map集合中
                hm.put(serialNumber, c + n);
                // 7.将序号存入list集合中,然后让序号自增
                list.add(serialNumber);
                serialNumber++;
            }
        }
        // 8.将小王存入Map集合,将小王的序号添加到list集合中,让序号自增
        hm.put(serialNumber,"小王");
        list.add(serialNumber);
        serialNumber++;
        // 9.将小王存入Map集合,将小王的序号添加到list集合中
        hm.put(serialNumber,"大王");
        list.add(serialNumber);
3.洗牌
// 洗牌
Collections.shuffle(list);
4.排序(发牌)
// 发牌
        // 1.创建四个TreeSet集合
        TreeSet<Integer> lord = new TreeSet<>();
        TreeSet<Integer> player1 = new TreeSet<>();
        TreeSet<Integer> player2 = new TreeSet<>();
        TreeSet<Integer> player3 = new TreeSet<>();
        // 2.遍历list序号集合
        for (int i = 0; i < list.size(); i++) {
            // i : 表示元素的索引
            // list.get(i) : 每一张牌的序号
            Integer serialNumber = list.get(i);
            // 3.向四个集合中添加元素
            if (i <= 2){ // 地主
                lord.add(serialNumber);
                continue;
            }

            if (i % 3 == 0){ // 玩家1
                player1.add(serialNumber);
            }else if (i % 3 == 1){ // 玩家2
                player2.add(serialNumber);
            }else { // 玩家3
                player3.add(serialNumber);
            }
        }
5.看牌
/**
     * 看牌功能
     *
     * @param name 玩家的名字
     * @param list 发到的牌
     */
    private void lookCards(String name, TreeSet<Integer> list) {

        // 1.遍历集合,获取每一张的序号,通过键找值的方式获取对应的牌面
        StringJoiner sj = new StringJoiner(", ", "", "");
        // 1.1 遍历集合,获取每一张的序号
        for (Integer number : list) {
            // 1.2 通过键找值的方式获取对应的牌面,并进行拼接
            String poker = hm.get(number);
            sj.add(poker);
        }
        // 2.拼接成字符串进行打印
        System.out.println(name + " : " + sj);
    }
  1. 调用看牌功能
// 看牌
lookCards("地主", lord);
lookCards("玩家1", player1);
lookCards("玩家2", player2);
lookCards("玩家3", player3);

5.2 第二种方式(给每张牌计算价值)

5.2.1 分析

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

5.2.2 思路

1.排序思路
  1. 在成员位置创建一个HashMap集合,作为牌的价值容器
  2. 在静态代码块中为每张牌添加对应的价值
  3. 定义一个方法,对发牌进行排序
  • 使用list集合调用sort方法进行排序
  • 使用的是添加排序器(Comparator)的方式
  • 在排序器中指定比较规则
  • 先取出两张牌的花色
  • 再定义一个方法去获取每张牌的价值
  • 比较规则为: 如果价值相同,就去比较花色的值
  1. 在定义的getValue方法中,对传递过来的poker进行截取
  • 截取方式为: 从索引为1的字符开始截取,直到末尾
  • 对截取的数字进行判断,判断其是否存在于hm集合中
  • 如果存在,则从集合中取出价值进行返回
  • 如果不存在,则将其本身作为价值进行返回
  1. 注意: 由于是从索引1开始截取,而牌盒中有两张特殊的牌,大王和小王,如果按照原来添加的字符串进行截取,则会截取到字符 “王”.而我们在存储每张牌的价值的时候,并没有存储字符"王",我们存储的是"大王"和"小王".此时,我们采取的解决方案是:**在添加价值的时候,在字符串"大王"和"小王"的时候,在两个字符串前面添加一个空格,添加完成后的字符串为 " 小王" 和 " 大王".**到此,此问题得以解决.

5.2.3 代码实现

1.前期准备
  1. 程序入口APP
  2. 准备牌,洗牌,发牌
public class PokerGame {

    // 3.创建一个集合作为牌盒
    // 添加static关键字,因为静态只能访问静态资源
    static ArrayList<String > list = new ArrayList<>();

    // 准备牌
    // 静态代码块:
    //  特点: 随着类的加载而加载,并且只执行一次
    static {
        // 准备牌:
        // 1.创建数组存储花色   "♦", "♣", "♥", "♠"
        String[] color = {"♦", "♣", "♥", "♠"};
        // 2.创建数组存储数字   "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
        String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};

        // 4.循环花色数组,获取每一种花色
        for (String c : color) {
            // 5.循环数字数组,获取每一个数字
            for (String n : number) {
                // 6.将遍历获得的 花色 和 数字 拼接起来,并添加到集合中
                list.add(c + n);
            }
        }
        // 7.添加大小王
        list.add("小王");
        list.add("大王");
    }

    public PokerGame() {

        // 洗牌
        Collections.shuffle(list);
        System.out.println(list);
        // 发牌
        // 1.创建四个结合分别存储 底牌 ,玩家1,玩家2,玩家3
        ArrayList<String> lord = new ArrayList<>();
        ArrayList<String> player1 = new ArrayList<>();
        ArrayList<String> player2 = new ArrayList<>();
        ArrayList<String> player3 = new ArrayList<>();
        // 2.遍历集合,获取每一张牌,将前三张作为底牌,后面的牌轮流发给三个玩家
        // 2.1 遍历集合
        for (int i = 0; i < list.size(); i++) {
            String poker = list.get(i);

            // 2.2 将前三张牌作为底牌存起来
            if (i <= 2){
                lord.add(poker);
                continue;
            }

            // 2.3 将后面的牌轮流发给三个玩家
            if (i % 3 == 0){ // 发给玩家1
                player1.add(poker);
            }else if (i % 3 == 1){ // 发给玩家2
                player2.add(poker);
            }else{ // 发给玩家3
                player3.add(poker);
            }
        }
    }
}
2.指定牌的价值
  1. PokerGame中添加成员变量hm,用于添加牌的价值
//创建一个集合,用来添加牌的价值
static HashMap<String, Integer> hm = new HashMap<>();
  1. 在静态代码块中添加牌的价值
//指定牌的价值
//牌上的数字到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);
3.排序(Order)
/**
     * 定义方法,完成排序功能
     *
     * @param list 发给玩家的牌的集合
     */
    private void order(ArrayList<String> list) {

        // 1.使用Collections工具类调用sort方法,并指定排序规则
        // 1.1 调用sort方法
        // sort 的底层采用的是 二分查找 和 插入排序 的方式进行排序的
        Collections.sort(list, new Comparator<String>() {
            @Override
            // o1 : 表示要插入到前面有序序列里面的牌
            // o2 : 已存在的有序序列中的牌

            // 正数 : o1大  插入到后面
            // 负数 : o1小  插入到前面
            // 0 : o1跟o2的价值是一样的,需要再根据花色进行排序

            public int compare(String o1, String o2) {
                // 1.2 指定排序规则
                // 1.2.1 获取花色
                String color1 = o1.substring(0, 1);
                String color2 = o2.substring(0, 1);
                // 1.2.2 获取价值,定义方法
                int value1 = getValue(o1);
                int value2 = getValue(o2);
                // 指定排序规则
                int i = value1 - value2;
                return i == 0 ? color1.compareTo(color2) : i;
            }
        });
    }
4.获取价值方法(getValue)
/**
     * 获取每张牌的价值
     *
     * @param poker 牌
     * @return 价值
     */
    public int getValue(String poker) {

        // 1.从索引1开始截取字符串
        String number = poker.substring(1);
        // 2.通过截取的字符串进行判断,判断截取的字符串是否存在于hm集合中
        if (hm.containsKey(number)) {
            // 2.1 如果存在,则需要从集合中取出对应的价值,进行返回
            return hm.get(number);
        } else {
            // 2.2 如果不存在,则直接把截取的字符串本身作为价值进行返回,但需要进行强制转换
            return Integer.parseInt(number);
        }
    }

6.面向对象的设计

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值