在日常生活中,想必大家都玩过或者听过斗地主吧,斗地主大致分为三个过程:洗牌,发牌,玩家按照规则将手中的牌给打完,谁最先打完,谁就获胜。这听起来挺简单的,但是影响你胜利的因素有很多:洗牌,玩家的水平。在赌场中很多人就是在洗牌跟发牌的过程中作弊的,那么我们可不可以用代码来实现洗牌跟发牌的功能来实现相对公平呢?
要想发牌跟洗牌我们首先需要有扑克牌,每张不同的牌对应不同的花色跟数字,这里就需要我们抽象出一副扑克牌对象,然后进行洗牌,洗牌我们就随机打乱扑克牌的顺序,然后就是发牌,每个人平均分发相同数量的扑克牌。
我们在这里创建一个Poker的包用来包装我们跟扑克牌相关的类。在Poker包中创建三个Java文件:Poker文件用来产生扑克牌,包含花色跟点数;Game文件用来实现创建一套扑克牌、洗牌和发牌的功能;而Test文件则是我们用来测试的。
package poker;
public class Poker {
//扑克牌的点数
private int rank;
//扑克牌的花色
private String suit;
//创建构造方法
public Poker(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
//以下这些方法我们今天暂时用不上
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getSuit() {
return suit;
}
//重写toString方法
@Override
public String toString() {
return "{ "+rank+" "+suit+"}";
}
}
这些花色不能被更改,并且仅在当前类中可以使用,所以我们直接用
private static final修饰保证安全性。
private static final String[] suit = {"♥","♣","♦","♠"};
扑克牌我们用数组来存放
public List<Poker> buyPoker() {
List<Poker> pokers = new ArrayList<>();
for (int i = 0; i < 4; i++) {
for (int j = 1; j <=13 ; j++) {
Poker poker = new Poker(j,suit[i]);
pokers.add(poker);
}
}
return pokers;
}
用Test来看是否创建成功,我们在写代码的时候要养成边写边测试的习惯,这样能及时发现错误。
public class Test {
public static void main(String[] args) {
Game game = new Game();
List<Poker> poker = game.buyPoker();
}
}
洗牌的操作原理是随机两两扑克牌互换,既然是随机的,我们就需要用到Random来产生随机数,我们从数组的后面开始与前面随机位置对应的数互换,因为这样我们容易产生随机数。
public void shuffle(List<Poker> poker) {
for (int i = poker.size()-1; i > 0 ; i--) {
Random random = new Random();
int index = random.nextInt(i);
swap(poker,i,index);
}
}
//创建私有方法来实现交换
private void swap(List<Poker> pokers,int i,int j) {
Poker tmp = pokers.get(i);
pokers.set(i,pokers.get(j));
pokers.set(j,tmp);
}
同样,我们进行一下测试。
我们可以看到:我们的洗牌功能已经实现了,每次生成的扑克牌的顺序都是不一样的。
这里我们创建一个二维数组,分别存放三个玩家所分得的手牌。
public List<List<Poker>> game(List<Poker> pokers) {
List<List<Poker>> hand = new ArrayList<>();
List<Poker> hand1 = new ArrayList<>();
List<Poker> hand2 = new ArrayList<>();
List<Poker> hand3 = new ArrayList<>();
hand.add(hand1);
hand.add(hand2);
hand.add(hand3);
for (int i = 0; i < 3; i++) {
//我们这里测试每人分发五张
for (int j = 0; j < 5; j++) {
//我们默认每次从下标为0的位置分发,并且分发一次就移除这个下表为0的扑克牌,
//移除之后,它后面的数字也会自动补齐到0位置
Poker tmp = pokers.remove(0);
hand.get(i).add(tmp);
}
}
return hand;
}
public class Poker {
private int rank;
private String suit;
public Poker(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getSuit() {
return suit;
}
@Override
public String toString() {
return "{ "+rank+" "+suit+"}";
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Game {
private static final String[] suit = {"♥","♣","♦","♠"};
public List<Poker> buyPoker() {
List<Poker> pokers = new ArrayList<>();
for (int i = 0; i < 4; i++) {
for (int j = 1; j <=13 ; j++) {
Poker poker = new Poker(j,suit[i]);
pokers.add(poker);
}
}
return pokers;
}
//洗牌
public void shuffle(List<Poker> poker) {
for (int i = poker.size()-1; i > 0 ; i--) {
Random random = new Random();
int index = random.nextInt(i);
swap(poker,i,index);
}
}
private void swap(List<Poker> pokers,int i,int j) {
Poker tmp = pokers.get(i);
pokers.set(i,pokers.get(j));
pokers.set(j,tmp);
}
public List<List<Poker>> game(List<Poker> pokers) {
List<List<Poker>> hand = new ArrayList<>();
List<Poker> hand1 = new ArrayList<>();
List<Poker> hand2 = new ArrayList<>();
List<Poker> hand3 = new ArrayList<>();
hand.add(hand1);
hand.add(hand2);
hand.add(hand3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
Poker tmp = pokers.remove(0);
hand.get(i).add(tmp);
}
}
return hand;
}
}
public class Test {
public static void main(String[] args) {
Game game = new Game();
List<Poker> poker = game.buyPoker();
System.out.println(poker);
game.shuffle(poker);
System.out.println(poker);
List<List<Poker>> hand = game.game(poker);
for (int i = 0; i < hand.size(); i++) {
System.out.println("第"+(i+1)+"个人的牌"+hand.get(i));
}
System.out.println("剩下的牌");
System.out.println(poker);
}
}