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入集合即可)

其他總結

針對不同的問題不同的需求,進行不同的實現邏輯數據結構的設計及最優選擇,多加練習多多總結熟能生巧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章