根据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、加入算法后,可以进行打牌,以后会再写一篇