根据collection集合,模拟斗地主案例

根据Collection集合,模拟斗地主案例

一、案例分析

1、买牌(造牌、存牌)

​ 要实现模拟斗地主的案例,首先需要有牌,所以第一步为买牌。扑克牌共有54张牌,其中有四种花色,13种牌值以及大小王,所以我们需要一个集合来存放扑克,两个String类型的数组来存放花色,牌值。

A.扑克  ArrayList<String > poker = new ArrayList<>();
B.花色  String[] color ={"♠","♥","♣","♦"};
C.牌值  String[] number = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};

2、洗牌(将牌的顺序打乱)

​ 有了牌之后,需要将牌的顺序打乱,也就是将扑克集合中的元素顺序打乱,正好可以利用Collections类中的shuffle方法(Collections为Collection的工具类)

Collections.shuffle(poker);

3、发牌

​ 将牌洗好了之后需要将牌发给三位玩家,而三位玩家需要有东西去接收,所以创建三个集合代表三名玩家,由于斗地主中需要有三张底牌作为地主牌,所以还需要有一个集合用来接收底牌。在分发牌的时候,需要交替进行,所以将索引值取模3,获得的0,1,2分别代表三名玩家,且当剩最后三张牌的时候将牌都交给底牌集合。

A.三名玩家的手牌
	ArrayList<String> play01 = new ArrayList<>();
	ArrayList<String> play02 = new ArrayList<>();
	ArrayList<String> play03 = new ArrayList<>();
B.底牌
	ArrayList<String> DiPai = new ArrayList<>();

4、叫地主及抢地主

​ 斗地主规则中有两名农民及一名地主,为产生地主,我使用两种方法产生:

​ 1、通过随机生成的牌确定:在洗牌后,随机生成一张牌A,然后进行发牌,牌A在哪名玩家手中,那么该名玩家被选为地主,且将底牌添加到该玩家的手牌中。

Random r = new Random();
int localHost = r.nextInt(55);//生成随机索引值

​ 2、通过叫地主及抢地主的方式产生:在进行发牌后,由第一名玩家输入是否叫地主(叫为Y,不叫为N),随后二三名玩家进行输入是否抢地主(抢为Y,不抢为N),根据情况是否进行第四次抢,将四次输入的Y/N存入一个String类的数组中,并将其拼接得到一个字符串,根据这个字符串的情况判断地主给谁,且将底牌添加到该玩家的手牌中。

Scanner sc = new Scanner(System.in);
String[] arr = new String[4];//创建一个长度为4的数组用以存放Y/N

5、代码实现

(一)买牌
ArrayList<String > poker = new ArrayList<>();//创建集合poker
poker.add("JOKER");//将两张大小王存入集合poker中
poker.add("joker");
//创建两个集合分别用来存放花色和牌值
String[] color ={"♠","♥","♣","♦"};
String[] number = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
//将两个数组进行嵌套循环遍历,将生成的52张牌存入poker中
for (String c : color) {
    for (String n : number) {
        //System.out.println(c+n);
        poker.add(c+n);
    }
}

将poker打印输出结果:
[JOKER, joker,2, ♠A, ♠K, ♠Q, ♠J,10,9,8,7,6,5,4,3,2, ♥A, ♥K, ♥Q, ♥J,10,9,8,7,6,5,4,3,2, ♣A, ♣K, ♣Q, ♣J,10,9,8,7,6,5,4,3,2, ♦A, ♦K, ♦Q, ♦J,10,9,8,7,6,5,4,3]
(二)洗牌
Collections.shuffle(poker);//利用Collections类中的shuffle方法将牌的顺序打乱

此时将poker打印输出结果:
[4, ♠K, ♦K,9,2,8, joker,2,9,2, ♠J, ♣K, ♦A,5,8,5,3,7, ♦J,4,6, ♣J,8,3,10,9,3,7, ♠A,3, ♥A, ♥Q, ♥J,6,6,7, JOKER,2,5,8,10, ♦Q,7,4,6,9, ♣A,10, ♣Q, ♥K,10, ♠Q,5,4]
(三)发牌
//创建四个集合,分别代表三个玩家和底牌
ArrayList<String> play01 = new ArrayList<>();
ArrayList<String> play02 = new ArrayList<>();
ArrayList<String> play03 = new ArrayList<>();
ArrayList<String> DiPai = new ArrayList<>();
//发牌步骤,将集合poker进行遍历
for (int i = 0; i < poker.size(); i++) {
            if (i >= 51) {//判断poker 中是否只剩三张了,如果只剩三张发给底牌
                DiPai.add(poker.get(i));
            } else if (i % 3 == 0) {//取模3为0的发给一号玩家
                play01.add(poker.get(i));
            } else if (i % 3 == 1) {//取模3为1的发给二号玩家
                play02.add(poker.get(i));
            } else if (i % 3 == 2) {//取模3为2的发给三号玩家
                play03.add(poker.get(i));
            }
        }

分别打印三个玩家的牌及底牌:
[4,9, joker,2, ♦A,5, ♦J, ♣J,10,7, ♥A,6, JOKER,8,7,9, ♣Q]
[♠K,2,2, ♠J,5,3,4,8,9, ♠A, ♥Q,6,2,10,4, ♣A, ♥K]
[♦K,8,9, ♣K,8,7,6,3,3,3, ♥J,7,5, ♦Q,6,10,10]
[♠Q,5,4]
(四)叫地主/抢地主

第一种方法:随机牌

//产生随机牌
Random r = new Random();
int localHost = r.nextInt(55); //生成一个随机数
while (true) {	//判断随机生成的牌是否在底牌中,如果在重新随机产生
    if (poker.get(localHost).equals(DiPai.get(0)) ||
        poker.get(localHost).equals(DiPai.get(1)) ||
        poker.get(localHost).equals(DiPai.get(2))) {
        localHost = r.nextInt(55);
    } else {  //直至生成的牌不在底牌中,跳出循环
        break;
    }
}
System.out.println("地主牌是:" + poker.get(localHost));

地主牌产生结果:
System.out.println("地主牌是:" + poker.get(localHost));
//根据随机牌判断谁是地主,并将底牌添加到其手牌里
for (int i = 0; i < play01.size(); i++) {
    if (play01.get(i).equals(poker.get(localHost))) {//遍历一号玩家的手牌,并判断该随机牌是否在该玩									家手中,如果是,该玩家为地主,并将底牌放入手牌,二三号玩家同理
        System.out.println("一号玩家是地主");
        play01.add(DiPai.get(0));
        play01.add(DiPai.get(1));
        play01.add(DiPai.get(2));
        break;
    }
}
for (int i = 0; i < play02.size(); i++) {
    if (play02.get(i).equals(poker.get(localHost))) {
        System.out.println("二号玩家是地主");
        play02.add(DiPai.get(0));
        play02.add(DiPai.get(1));
        play02.add(DiPai.get(2));
        break;
    }
}
for (int i = 0; i < play03.size(); i++) {
    if (play03.get(i).equals(poker.get(localHost))) {
        System.out.println("三号玩家是地主");
        play03.add(DiPai.get(0));
        play03.add(DiPai.get(1));
        play03.add(DiPai.get(2));
        break;
    }
}

程序运行结果:
	地主牌是:♦9
	一号玩家是地主
	一号玩家的牌:[4,9, joker,2, ♦A,5, ♦J, ♣J,10,7, ♥A,6, JOKER,8,7,9, ♣Q, ♠Q,5,4]
	二号玩家的牌:[♠K,2,2, ♠J,5,3,4,8,9, ♠A, ♥Q,6,2,10,4, ♣A, ♥K]
	三号玩家的牌:[♦K,8,9, ♣K,8,7,6,3,3,3, ♥J,7,5, ♦Q,6,10,10]
	底牌:[♠Q,5,4]

第二种方法:叫抢地主

//进行叫抢地主
Scanner sc = new Scanner(System.in);
String[] arr = new String[4];//创建一个长度为四的String类型数组,用于接收叫抢地主的情况(Y/N)
for (int i = 0; i < 4; i++) {
    if(i==3){
        if(arr[0].equals("Y")){//第一个玩家叫地主
            if(arr[1].equals("Y")){//第二个玩家抢地主(无论第三位玩家怎么叫情况一样)
                System.out.println("第"+1+"位玩家是否叫地主[Y/N]");
                String next = sc.next();
                arr[i] = next;
            }else{//第二位玩家不抢地主
                if(arr[2].equals("Y")){//第三位抢地主
                    System.out.println("第"+1+"位玩家是否叫地主[Y/N]");
                    String next = sc.next();
                    arr[i] = next;
                }else{//第三位不抢地主
                    arr[i] = "Y";
                }
        }else {//第一个玩家不叫地主
            if(arr[1].equals("Y")){//第二个玩家抢地主
                if(arr[2].equals("Y")){//第三个玩家抢地主
                    System.out.println("第"+2+"位玩家是否叫地主[Y/N]");
                    String next = sc.next();
                    arr[i] = next;
                }else{//第三个玩家不抢地主
                    arr[i] = "Y";
                }
            }else{//都不叫地主,将地主分给一号玩家
                arr[i] ="Y";
            }
    }else{//三位玩家正常叫一轮
        System.out.println("第"+(i+1)+"位玩家是否叫地主[Y/N]");
        String next = sc.next();
        arr[i] = next;
    }
        }
String str = "";//创建一个空字符,用于上步结果的拼接
for (int i = 0; i < arr.length; i++) {//通过遍历,将结果拼接
    str = str + arr[i];
}
//通过switch语句对结果进行判断,地主该分给谁,并将底牌分到其手牌中
switch(str){
    case "YYYY":
    case "YYNY":
    case "YNYY":
    case "YNNY":
    case "NNNY":
        System.out.println("一号玩家是地主");
        play01.add(DiPai.get(0));
        play01.add(DiPai.get(1));
        play01.add(DiPai.get(2));
        break;
    case "YYNN":
    case "NYYY":
    case "NYNY":
        System.out.println("二号玩家是地主");
        play02.add(DiPai.get(0));
        play02.add(DiPai.get(1));
        play02.add(DiPai.get(2));
        break;
    case "YYYN":
    case "YNYN":
    case "NYYN":
    case "NNYY":
        System.out.println("三号玩家是地主");
        play03.add(DiPai.get(0));
        play03.add(DiPai.get(1));
        play03.add(DiPai.get(2));
        break;
}

十六种情况的示意图
十六种情况的示意图

程序运行结果:
第1位玩家是否叫地主[Y/N]
N
第2位玩家是否叫地主[Y/N]
Y
第3位玩家是否叫地主[Y/N]
Y
第2位玩家是否叫地主[Y/N]
Y
二号玩家是地主
一号玩家的牌:[♥6, ♠3, ♠9, ♥2, ♠J, ♦J, ♣4, ♥10, ♣10, joker, ♦8, ♦6, ♦K, ♠8, ♠5, ♥J, ♠4]
二号玩家的牌:[♥3, ♦4, ♦9, ♠K, ♥7, ♣6, ♣5, ♥5, ♥Q, ♦5, ♣A, JOKER, ♣7, ♣Q, ♦Q, ♠2, ♥4, ♣9, ♦2, ♥9]
三号玩家的牌:[♠Q, ♣3, ♣J, ♠A, ♠10, ♥A, ♦3, ♣K, ♦A, ♣2, ♦7, ♣8, ♥K, ♥8, ♦10, ♠6, ♠7]
底牌:[♣9, ♦2, ♥9]

6、未完善地方

本案例实现仍不完善,欢迎在评论区留言,以下是我发现的不够完善的地方:

1、通过叫抢方式产生地主时,1号玩家固定,可以将三名玩家通过索引随机产生1号玩家,然后进行叫抢。

2、还可以将叫抢地主和随机牌方法结合在一起产生一号玩家

3、加入算法后,可以进行打牌,以后会再写一篇

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值