Bootstrap

JAVA实现梭哈游戏(初级版本)

JAVA实现梭哈游戏(初级版本)

最近在学习JAVA的集合,写了一个梭哈游戏实践一下
里面包含List,Set,Map等集合的常见用法
以后会逐渐在这个程序的基础上加入多线程和网络编程等方面的细节
此处该初级版本并未实现下注功能,日后会在加入多线程时加入下注功能

首先介绍一下梭哈游戏的规则:
各家一张底牌,底牌要到决胜负时才可翻开。从发第二张牌开始,每发一张牌,以牌面大者为先,进行下注。 有人下注,想继续玩下去的人,选择跟,跟注后会下注到和上家相同的筹码,或可选择加注,各家如果觉得自己的牌况不妙,不想继续,可以选择放弃,认赔等待牌局结束,先前跟过的筹码,亦无法取回。
最后一轮下注是比赛的关键,在这一轮中,玩家可以进行梭哈,所谓梭哈是押上所有未放弃的玩家所能够跟的最大筹码。等到下注的人都对下注进行表态后,便掀开底牌一决胜负。这时,牌面最大的人可赢得桌面所有的筹码。

代码如下:

package ShowHand_Package;


import java.util.*;

class card{
    public String suit;//花色
    public String rank;//点数

    public card(String suit , String rank){
        this.suit=suit;
        this.rank=rank;
    }
    @Override
    public String toString() {
        return "(" + suit + " " + rank +  ")";
    }
}

public class ShowHand {
    //定义该游戏最多个玩家
    private final int PLAY_NUM=5;
    //定义扑克牌的所有花色和数值
    private String[] types={"黑桃","红桃","梅花","方片"};
    private String[] values={"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
    //cards是一局游戏中剩下的扑克牌
    private List<card> cards=new LinkedList<>();
    //定义所有的玩家
    private String[] players=new String[PLAY_NUM];
    //所有玩家手上的扑克牌
    private List<card>[] playersCards=new List[PLAY_NUM];

    /**
     * 牌型分类
     */
    //无对 Zilch 不能排成以上组合的牌,以点数决定大小。
    private static final int Zilch = 1;
    //一对One Pair  两张相同点数的牌。
    private static final int OnePair = 2;
    //两对 Two Pairs  两张相同点数的牌,加另外两张相同点数的牌
    private static final int TwoPairs = 3;
    //三条 ThreeOfAKind  有三张同一点数的牌。
    private static final int ThreeOfAKind = 4;
    //顺子 Straight  五张顺连的牌。
    private static final int Straight = 5;
    //同花 Flush  五张同一花色的牌。
    private static final int Flush = 6;
    //满堂红 FullHouse  三张同一点数的牌,加一对其他点数的牌
    private static final int FullHouse = 7;
    //四条 FourOfAKind  有四张同一点数的牌。
    private static final int FourOfAKind = 8;
    //同花顺 Straight Flush  同一花色,顺序的牌。
    private static final int straightFlush = 9;
    //同花大顺 Royal Flush 最高为Ace(一点)的同花顺
    private static final int royalFlush = 10;

    /**
     * 初始化扑克牌,放入52张扑克牌
     * 并且使用shuffle方法将它们按随机顺序排列
     */
    public void initCard(){
        for (int i = 0; i < 4; i++) {
            for (int j = 2; j <= 10; j++) {
                cards.add(new card(types[i],String.valueOf(j)));
            }
            cards.add(new card(types[i] , "J"));
            cards.add(new card(types[i] , "Q"));
            cards.add(new card(types[i] , "K"));
            cards.add(new card(types[i] , "A"));
        }
        //随机排列
        Collections.shuffle(cards);
    }
    /**
     *初始化玩家,为每个玩家分派用户名
     */
    public void initPlayer(String... names){
        try{
            if (names.length>PLAY_NUM || names.length<2){
                System.out.println("玩家数量不对");
            }
            //初始化玩家用户名
            for (int i=0; i<names.length ;i++){
                players[i]=names[i];
            }
        } catch (Exception e){
            System.out.println("创建玩家时出现错误");
        }
    }
    /**
     * 初始化玩家手上的扑克牌,开始游戏时每个玩家手上的扑克牌为空
     * 程序使用一个长的为0的LinkedList来表示
     */
    public void initPlayerCards(){
        for (int i=0 ; i<players.length ; i++){
            if (players[i]!=null && !players[i].equals(""))
                playersCards[i]=new LinkedList<card>();
        }
    }

    /**
     * 分派扑克牌
     */
    public void deliverCard(String first){
        //查询出指定元素在数组中的索引
        int firstPos=Arrays.asList(players).indexOf(first);
        //依次给位于该指定玩家之后的每个玩家派扑克牌
        for (int i=firstPos ; i<PLAY_NUM ; i++){
            if (players[i]!=null){
                playersCards[i].add(cards.get(0));
                cards.remove(0);
            }
        }
        //依次给位于该指定玩家之前的每个玩家派扑克牌
        for (int i=0 ; i<firstPos ; i++){
            if (players[i]!=null){
                playersCards[i].add(cards.get(0));
                cards.remove(0);
            }
        }
    }

    /**
     * 创建一个玩家的点数数组
     */
    public int[] getRankArray(List<card> playCard){
        int[] rankArray=new int[15];
        for (int i=0 ; i<5 ; i++){
            int temp=getRank(playCard.get(i).rank);
            rankArray[temp]++;
        }
        return rankArray;
    }
    /**
     * 创建一个玩家的花色数组
     */
    public int[] getSuitArray(List<card> playCard){
        int[] suitArray=new int[5];
        for (int i=0 ; i<5 ; i++){
            int temp=getSuit(playCard.get(i).suit);
            suitArray[temp]++;
        }
        return suitArray;
    }
    /**
     * 获得玩家牌中的花色和点数
     */
    public int getRank(String str){
        for (int i=2 ; i<=10 ; i++){
            if ((String.valueOf(i)).equals(str)){
                return i;
            }
        }

        if ("A".equals(str)){
            return 14;
        }else if ("J".equals(str)){
            return 11;
        }else if ("Q".equals(str)){
            return 12;
        }else if ("K".equals(str)){
            return 13;
        } else {
            return 0;
        }
    }
    public int getSuit(String str){
        if ("方片".equals(str)){
            return 1;
        }else if ("梅花".equals(str)){
            return 2;
        }else if ("红桃".equals(str)){
            return 3;
        }else if ("黑桃".equals(str)){
            return 4;
        }else {
            return 0;
        }
    }

    /**
     * 判断玩家手中是哪副牌,并返回牌型相对应的静态常量的值
     */
    public int pokerType(int[] rankArray , int[] suitArray) {
        //创建两个ArrayList用来保存扑克牌的花色数量和点数数量
        //同时利用size和contains功能来对牌型进行判断
        List<Integer> aRank = new ArrayList<>();
        List<Integer> aSuit = new ArrayList<>();
        if (rankArray[14] > 0) {
            //如果A存在,则让第一个下标元素也存A,方便后面排序比较
            rankArray[1] = rankArray[14];
        }
        for (int i = 1; i <= 13; i++) {
            if (rankArray[i] != 0) {
                aRank.add(rankArray[i]);
            }
        }
        for (int i = 1; i <= 4; i++) {
            if (suitArray[i] != 0) {
                aSuit.add(suitArray[i]);
            }
        }

        //比较牌型
        //五张牌中只有两种点数
        if (aRank.size() == 2) {
            if (aRank.contains(4)) {
                //四条:有四张同一点数的牌
                return FourOfAKind;
            } else {
                //满堂红:三张同一点数的牌,加一对其他点数的牌
                return FullHouse;
            }
        }
        //五张牌中有三种点数
        else if (aRank.size() == 3) {
            if (aRank.contains(3)) {
                //三条:有三张同一点数的牌
                return ThreeOfAKind;
            } else {
                //两对:两张相同点数的牌,加另外两张相同点数的牌
                return TwoPairs;
            }
        }
        //五张牌有四种点数
        else if (aRank.size() == 4) {
            //一对:两张相同点数的牌
            return OnePair;
        }
        //五种牌中有五种点数
        else if (aRank.size() == 5) {
            int aSort = 0;//记录连队张数
            //从2号下标开始到13号下标,比较是否连续
            for (int i = 2; i < rankArray.length - 1; i++) {
                if (rankArray[i - 1] == 1 && rankArray[i] == 1) {
                    aSort++;
                }
            }
            if (aSort == 4 && aSuit.contains(5)) {
                //同花顺:同一花色,顺序的牌
                return straightFlush;
            } else if (aSort == 4 && aSuit.contains(5) && rankArray[1] == 1 && rankArray[13] == 1) {
                //同花大顺
                return royalFlush;
            } else if (aSuit.contains(5)) {
                //同花:五张花色一样的牌
                return Flush;
            } else if (aSort == 4) {
                //顺子:五张顺连的牌
                return Straight;
            } else {
                return Zilch;
            }
        }
        return 0;
    }
    /**
     * 根据数据打印牌型
     */
    public void printType(int key){
        if (key == 1) {
            System.out.println("无对儿");
        } else if (key == 2) {
            System.out.println("一对儿");
        } else if (key == 3) {
            System.out.println("两对儿");
        } else if (key == 4) {
            System.out.println("三条儿");
        } else if (key == 5) {
            System.out.println("顺子");
        } else if (key == 6) {
            System.out.println("同花");
        } else if (key == 7) {
            System.out.println("满堂红");
        } else if (key == 8) {
            System.out.println("四条");
        } else if (key == 9) {
            System.out.println("同花顺");
        } else if (key == 10) {
            System.out.println("同花大顺");
        } else {
            System.out.println("无牌型");
        }
    }

    /**
     * 输出玩家手上的扑克牌
     * 实现该方法时,应该控制每个玩家看不到别人的第一张牌
     */
    public void showPlayerCards(){
        for (int i=0 ; i<PLAY_NUM ; i++){
            //当玩家不为空时
            if (players[i]!=null){
                //输出玩家
                System.out.println(players[i] + ": ");
                //遍历输出玩家手上的扑克牌
                ListIterator lit=playersCards[i].listIterator(1);//让其他人看不到第一张牌
                while (lit.hasNext()){
                    card pc=(card) lit.next();
                    System.out.println(pc);
                }
            }
        }
    }
    /**
     * 通过摇骰子决定哪位玩家先派发牌
     */
    public String dicePlayer(){
        Map diceMap=new HashMap();
        ArrayList diceNum=new ArrayList(5);
        int flag=0;
        while(flag<5){
            int number=(int)(1+Math.random()*6);
            if (!diceNum.contains(number)) {
                diceNum.add(number);
                flag++;
            }
        }

        for (int i=0 ; i<PLAY_NUM ; i++) {
            if (players[i] != null) {
                //将每个玩家的骰子数添加进HashMap中
                diceMap.put(players[i], diceNum.get(i));
            }
        }
            List<Map.Entry<String,Integer>> list=new ArrayList<Map.Entry<String,Integer>>(diceMap.entrySet());
            list.sort(new Comparator<Map.Entry<String, Integer>>() {
                @Override
                public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                    return o2.getValue().compareTo(o1.getValue());
                }
            });
            for (Map.Entry<String,Integer> player_diceNum : list){
                System.out.println(player_diceNum.getKey() + "骰子数: " + player_diceNum.getValue());
            }
            System.out.println("最大的玩家为: " + list.get(0).getKey());
            return list.get(0).getKey();
    }

    public static void main(String[] args){
        ShowHand showHand=new ShowHand();
        //初始化五名玩家
        showHand.initPlayer("徐蔚","张留成","段周明","张亚欧","樊子靖");
        //洗牌
        showHand.initCard();
        //初始化玩家手上的扑克牌
        showHand.initPlayerCards();
        //通过摇骰子决定从哪一个玩家先开始派发(第一次派发)
        String first_deliver_player=showHand.dicePlayer();
        //第一次发牌
        showHand.deliverCard(first_deliver_player);
        //第一次发牌为暗牌,不用展示
        //按原顺序进行第二次发牌

        //比较牌面大小,下注功能(未实现)

        //玩家展示手中的牌,循环4次
        for (int i=2 ; i<=5 ; i++){
            showHand.deliverCard(first_deliver_player);
            if (i==5){
                System.out.println("第"+ i +"次发牌后,各玩家手中的牌为:");
                showHand.showPlayerCards();
            }
        }
        //展示暗牌
        System.out.println("各位玩家手中的暗牌为:");
        for (int i=0 ; i<5 ; i++){
            System.out.println(showHand.players[i] + "的暗牌为: " + showHand.playersCards[i].get(0));
        }
        //比较牌型,决出胜负

        //新建玩家的花色表和点数表


        System.out.println("徐蔚最后的牌型为: " + showHand.playersCards[0]);
        System.out.println("张留成最后的牌型为: " + showHand.playersCards[1]);
        System.out.println("段周明最后的牌型为: " + showHand.playersCards[2]);
        System.out.println("张亚欧最后的牌型为: " + showHand.playersCards[3]);
        System.out.println("樊子靖最后的牌型为: " + showHand.playersCards[4]);

        int[] RankOfPlayer1 = showHand.getRankArray(showHand.playersCards[0]);
        /*
        for (int n=0 ; n<15 ; n++){
            System.out.print(RankOfPlayer1[n]+ " ");
        }
        System.out.println();
         */
        int[] SuitOfPlayer1 = showHand.getSuitArray(showHand.playersCards[0]);
        /*
        for (int n=0 ; n<5 ; n++){
            System.out.print(SuitOfPlayer1[n]+  " ");
        }
        System.out.println();

         */
        int[] RankOfPlayer2 = showHand.getRankArray(showHand.playersCards[1]);
        /*
        for (int n=0 ; n<15 ; n++){
            System.out.print(RankOfPlayer2[n]+ " ");
        }
        System.out.println();
         */
        int[] SuitOfPlayer2 = showHand.getSuitArray(showHand.playersCards[1]);
        /*
        for (int n=0 ; n<5 ; n++){
            System.out.print(SuitOfPlayer2[n]+  " ");
        }
        System.out.println();
         */
        int[] RankOfPlayer3 = showHand.getRankArray(showHand.playersCards[2]);
        /*
        for (int n=0 ; n<15 ; n++){
            System.out.print(RankOfPlayer3[n]+ " ");
        }
        System.out.println();
         */
        int[] SuitOfPlayer3 = showHand.getSuitArray(showHand.playersCards[2]);
        /*
        for (int n=0 ; n<5 ; n++){
            System.out.print(SuitOfPlayer3[n]+  " ");
        }
        System.out.println();
         */
        int[] RankOfPlayer4 = showHand.getRankArray(showHand.playersCards[3]);
        /*
        for (int n=0 ; n<15 ; n++){
            System.out.print(RankOfPlayer4[n]+ " ");
        }
        System.out.println();
         */
        int[] SuitOfPlayer4 = showHand.getSuitArray(showHand.playersCards[3]);
        /*
        for (int n=0 ; n<5 ; n++){
            System.out.print(SuitOfPlayer4[n]+  " ");
        }
        System.out.println();
         */
        int[] RankOfPlayer5 = showHand.getRankArray(showHand.playersCards[4]);
        /*
        for (int n=0 ; n<15 ; n++){
            System.out.print(RankOfPlayer5[n]+ " ");
        }
        System.out.println();
         */
        int[] SuitOfPlayer5 = showHand.getSuitArray(showHand.playersCards[4]);
        /*
        for (int n=0 ; n<5 ; n++){
            System.out.print(SuitOfPlayer5[n]+  " ");
        }
        System.out.println();
         */

        //计算出各玩家的牌型
        int typeOfPlayer1=showHand.pokerType(RankOfPlayer1,SuitOfPlayer1);
        int typeOfPlayer2=showHand.pokerType(RankOfPlayer2,SuitOfPlayer2);
        int typeOfPlayer3=showHand.pokerType(RankOfPlayer3,SuitOfPlayer3);
        int typeOfPlayer4=showHand.pokerType(RankOfPlayer4,SuitOfPlayer4);
        int typeOfPlayer5=showHand.pokerType(RankOfPlayer5,SuitOfPlayer5);

        System.out.println(typeOfPlayer1);
        System.out.println(typeOfPlayer2);
        System.out.println(typeOfPlayer3);
        System.out.println(typeOfPlayer4);
        System.out.println(typeOfPlayer5);

        //用冒泡排序将五位玩家的牌型比较大小
        int[] typeOfCardArray={typeOfPlayer1,typeOfPlayer2,typeOfPlayer3,typeOfPlayer4,typeOfPlayer5};
        int temp;
        String[] playersTemp={"徐蔚","张留成","段周明","张亚欧","樊子靖"};
        String tempName;
        for (int i=0 ; i<4 ; i++){
            for (int j=0 ; j<4-i ; j++){
                if (typeOfCardArray[j] > typeOfCardArray[j+1]){
                    temp=typeOfCardArray[j+1];
                    typeOfCardArray[j+1]=typeOfCardArray[j];
                    typeOfCardArray[j]=temp;

                    tempName=playersTemp[j+1];
                    playersTemp[j+1]=playersTemp[j];
                    playersTemp[j]=tempName;
                }

                if (typeOfCardArray[j] == typeOfCardArray[j+1]){
                    int subOfCard1=0;
                    int subOfCard2=0;
                    for (int k=0 ; k<5 ; k++){
                        subOfCard1=showHand.getRank(showHand.playersCards[j].get(k).rank) + subOfCard1;
                    }
                    for (int l=0 ; l<5 ; l++){
                        subOfCard2=showHand.getRank(showHand.playersCards[j+1].get(l).rank) + subOfCard2;
                    }
                    if (subOfCard1 > subOfCard2){
                        temp=typeOfCardArray[j+1];
                        typeOfCardArray[j+1]=typeOfCardArray[j];
                        typeOfCardArray[j]=temp;

                        tempName=playersTemp[j+1];
                        playersTemp[j+1]=playersTemp[j];
                        playersTemp[j]=tempName;
                    }
                }
            }
        }

        System.out.println("最后的玩家是:");
            System.out.println(playersTemp[4]);
        }
    }


运行结果示意图:
在这里插入图片描述
在这里插入图片描述


编写程序过程中值得注意的问题

  • 查询出指定元素在数组中的索引
        //查询出指定元素在数组中的索引
        int firstPos=Arrays.asList(players).indexOf(first);

将players数组转换为List集合,使用List集合的indexOf方法查询索引

为什么不用Arrays.binarySearch?
当使用Arrays.binarySearch方法时,需要先调用Arrays.sort方法对数组进行排序,否则认为数组是未定义的,可能无法找到。但调用sort方法对字符串数组排序后,会导致数组顺序发生变化,所以不能使用

  • 遍历List集合要使用Iterator接口
//遍历输出玩家手上的扑克牌
                ListIterator lit=playersCards[i].listIterator(1);//让其他人看不到第一张牌
                while (lit.hasNext()){
                    card pc=(card) lit.next();
                    System.out.println(pc);
                }
  • 将Map集合封装进List集合中,用List集合的方法对Map的value进行排序
List<Map.Entry<String,Integer>> list=new ArrayList<Map.Entry<String,Integer>>(diceMap.entrySet());
            list.sort(new Comparator<Map.Entry<String, Integer>>() {
                @Override
                public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                    return o2.getValue().compareTo(o1.getValue());
                }
            });
            for (Map.Entry<String,Integer> player_diceNum : list){
                System.out.println(player_diceNum.getKey() + "骰子数: " + player_diceNum.getValue());
            }
;