Java学习——斗地主升级版(玩家手牌和底牌顺序输出)

需求

三个人斗地主,54张牌(包括大王、小王)。每人按顺序摸牌,最后剩3张底牌,请打印分别从大到小顺序输出三个玩家的手牌以及所剩的底牌。

设计

表面上看起来同https://blog.csdn.net/qq_38586378/article/details/104780112的逻辑相同,就是准备牌、洗牌、发牌、牌输出,但是需要注意的是加了一个新需求排序,三名玩家和底牌输出并不是直接输出,而是将摸到的牌按照从大到小的顺序排序后输出,如何排序输出将是这篇博客记录的重点,其他的步骤参考前方链接所给基本步骤即可。

方案一:继续使用ArrayList存储poker,在将54张牌放入到poker中后,定义一个Map<String,Integer>集合来手动定义牌间的大小关系,其中key为牌,value为从0-53的整数值。之后发牌后对三名玩家和底牌集合使用Collections工具类的sort(List,new Comparator<? super T>(){});方法来对四个集合元素进行排序,具体的匿名内部类中重写的compare方法中,需要将集合元素作为key到Map中获取值并进行比较返回return poker.get(player1.get(i))-poker.get(player1.get(i+1))。最后输出四个集合即可实现牌的从大到小输出。

方案二:从方案一中可以看到,多次遍历Map集合,倒不如直接使用Map集合来存储牌,定义Map<String,Integer> poker,一开始就定义好牌的大小顺序,使用Collections工具类的keySet方法获取poker集合中的所有键即牌,对其进行发牌,然后对三名玩家和底牌集合使用Collections的sort方法,使用匿名内部类来重写compare方法,具体方法同方案一。

方案三:可以看到的是方案一和方案二其实是一样的,唯一区别的地方就是方案一中后续才加上Map顺序大小和牌映射的关系,而方案二中一开始就定义了大小和牌的映射关系,并且将Map中的key作为牌的定义。既然这样根据所需知识联想到数据库的索引,数据库中一般都有一个自增的id主键用于查找排序数据,倒不如将方案二中的Map集合的key和value互换,将大小索引作为key,牌作为value。这样的话洗牌、发牌只用操作这个index索引即可,三名玩家和底牌集合中拿到的也是Map中的key子集合。排序直接使用Collections工具类的sort方法即可,参数为key子集合,最后再分别遍历存储index的四个集合并将集合元素作为key在Map中使用get方法获取对应的value即牌。

实现

1.准备牌。使用String类型数组或者String类型的ArrayList集合都可,用来存储花色和数字。用Map<Integer,String>存储牌,用ArrayList<Integer>来存储Map中的key。

//1. 准备牌
        //1.1 准备四种花色到ArrayList中,使用Collections工具类的addAll方法统一添加元素
        List<String> colors = new ArrayList<>();
        Collections.addAll(colors,"♠","♣","♥","♦");
        //1.2 准备13种数字,直接使用String类型数组
        String[] numbers = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
        //1.3 创建Map<Integer,String>存放与索引key一一映射的牌,创建ArrayList<Integer>存储Map集合的key索引
        Map<Integer,String> poker = new HashMap<>();
        ArrayList<Integer> indexs = new ArrayList<>();
        //1.4 准备牌
        //1.4.1 大王和小王
        int index = 0;//封装一个局部变量用于index++作为key
        poker.put(index,"大王");
        indexs.add(index);
        index++;
        poker.put(index,"小王");
        indexs.add(index);
        //1.4.2 存放其他52张牌
        for(String color : colors){
            for(String number : numbers){
                index++;
                poker.put(index,color+number);
                indexs.add(index);
            }
        }

此处注意indexs集合的值也可以通过Map使用keySet方法来获取,但是上面代码段的方法直接在给Map插入元素的时候顺序给indexs插入元素更为方便。

2. 洗牌,对indexs集合使用Collections工具类的shuffle方法。(此处及后续对indexs牌的索引集合进行操作也是对原本牌的顺序进行改变,索引与牌一一对应,拿到索引相当于拿到牌,最后输出的时候再根据索引去找索引对应的牌即可,这样更高效【类似数据库中的索引操作】

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

洗牌结果如下图所示,多次运行结果不同,洗牌成功。(索引顺序打乱,索引对应的牌不变,即牌的顺序也打乱)

3. 发牌,集合索引大于等于51的直接加入底牌集合中,其他的对集合索引i进行%3运算,运算结果只有0 1 2三种可能,对于每一种可能将对应的元素存入玩家集合中。

 //3. 发牌
        ArrayList<Integer> player1 = new ArrayList<>();
        ArrayList<Integer> player2 = new ArrayList<>();
        ArrayList<Integer> player3 = new ArrayList<>();
        ArrayList<Integer> dipai = new ArrayList<>();
        for (int i = 0; i < indexs.size(); i++) {
            if(i>=indexs.size()-3)
            {
                dipai.add(indexs.get(i));
            }else if(i % 3 == 0){
                player1.add(indexs.get(i));
            }else if(i % 3 == 1){
                player2.add(indexs.get(i));
            }else if(i % 3 ==2){
                player3.add(indexs.get(i));
            }
        }

此处注意三名玩家和底牌集合的元素类型要为Integer,用来存储牌对应的索引值。未排序输出结果如下。

4. 排序。分别对四个集合使用Collections工具类的sort方法,将集合中元素排序(Integer类型默认从小到大排列)【Map中索引从小到大对应的value牌从大到小,将集合中index从小到大排列后输出对应Map中的value即为从大到小】

//4. 排序 使用Collections工具类的静态方法sort,参数为List集合
        Collections.sort(player1);
        Collections.sort(player2);
        Collections.sort(player3);
        Collections.sort(dipai);

5. 打印输出牌。分别遍历四个集合中的元素,将元素作为参数调用Map集合的get方法获取Map集合中index索引对应的value即可。

 //5. 展示牌 遍历玩家及底牌集合的元素作为Map集合中的key来输出对应的value
        System.out.println("第一个玩家手牌:");
        showCard(player1,poker);
        System.out.println("\n第二个玩家手牌:");
        showCard(player2,poker);
        System.out.println("\n第三个玩家手牌:");
        showCard(player3,poker);
        System.out.println("\n底牌:");
        showCard(dipai,poker);

 private static void showCard(ArrayList<Integer> player, Map<Integer, String> poker) {
        for(Integer key : player){
            System.out.print(poker.get(key)+" ");
        }
    }

输出结果如下图,实现从大到小输出牌。

总结

知识点总结

1. Collections集合工具类是对Collection集合进行操作,主要有的静态方法有:addAll(List,...element)批量添加元素进入集合List中;shuffle(List)将集合中元素顺序打乱(执行后再遍历List集合顺序被打乱);sort(List)对集合元素按顺序输出(整数:从小到大;字符:字典顺序;自定义:需要自定义类重写接口Comparable的compareTo方法);sort(List,new Comparator<T>(){}));使用匿名内部类重写compare方法

2. 对元素进行排序计数可考虑Map集合,排序对key排序后输出排完序后key对应的value;计数对key计数用value来存储key出现的个数(第一次出现value=1,put入集合;多次出现对key使用map.get(key)方法获取value进行+1操作后再重新将这个键值对put入集合即可)

其他总结

针对不同的问题不同的需求,进行不同的实现逻辑数据结构的设计及最优选择,多加练习多多总结熟能生巧。

发布了41 篇原创文章 · 获赞 9 · 访问量 9753

猜你喜欢

转载自blog.csdn.net/qq_38586378/article/details/104823980
今日推荐