需求:
- 组装54张扑克牌
- 将54张牌顺序打乱
- 三个玩家参与游戏,三人交替摸牌,每人17张牌,后三张留作底牌。
- 查看三人各自手中的牌、底牌
需求是不是看着很简单,就几行字。建议先对着需求自己想想该如何去实现。
分析:
- 1.java是面向对象编程,当然离不开对象了。如果了没有对象怎么办?new啊。没有类怎么new? 好了问题来了:我们需要从具体的需求中抽象出一个个类。因为扑克牌不但有数字,而且有花色,那么一个变量是否同时表示花色和数字,显然不能吧,所以要有个扑克类。斗地主有三个玩家,是不是应该有个玩家类啊,不然我的牌发给空气吗?第二个类有了玩家类,玩家类应该有一个用于存储17张牌的容器。
- 2.由于用户类的存在,用户类中已经有存储扑克牌的容器了,不妨给用户一个名字。
- 3.54张扑克牌是自己组装的,这个肯定用循环生成,具体怎么生成具体写的时候思考为时未晚,然后用一个集合装起来。
- 4.这个是在写的过程中才思考的,三人交替发牌,使用17次循环,每次循环分三张牌即可
- 5.查看各自手牌这个应该大家都懂吧,把集合拿出来遍历就行了
这里小白需要注意,包括我自己,你千万别认为要构思出所有的实现细节才着手写。我写的过程中像第四第五点都是后面写的过程中才碰到的。有了大概思路就可以尝试了。告诉自己我先写三分钟试试。
首先是Poker类:
public class Poker implements Comparable<Poker> {
// 定义扑克牌数字大小,这里原来使用的是int类型,组装54张牌时发现有J,Q,K,A这些不是int类型的,
// 解决办法是将int改成Object类型
private Object num;
// 定义扑克牌花色
private String type;
private int flag;
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
public Poker() {
super();
}
public Poker(Object num, String type, int flag) {
super();
this.num = num;
this.type = type;
this.flag = flag;
}
/**
* 这里的toString是重写过的,为了控制台能输出花色+数字这样格式的扑克牌,简言之为了美观
*/
@Override
public String toString() {
return type + num;
}
public Object getNum() {
return num;
}
public void setNum(Object num) {
this.num = num;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
/**
* 判断扑克牌对象大小的方法
*/
@Override
public int compareTo(Poker o) {
return -(this.flag - o.flag);
}
}
接着是User类,该类的作用是,将装玩家牌的容器,跟玩家的名字抽象成一个玩家类,并提供读写方法用于最后查看玩家手牌
public class User {
//定义玩家名字
private String name;
//定义存储玩家手牌的集合
private List<Poker> userArray = new ArrayList<Poker>();
public User() {
super();
}
public User(String name, ArrayList<Poker> userArray) {
super();
this.name = name;
this.userArray = userArray;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Poker> getUserArray() {
return userArray;
}
public void setUserArray(List<Poker> userArray) {
this.userArray = userArray;
}
}
重点的来了,这个是我定义的Manage类,该类定义了组装牌的方法,分牌的方法,查看牌的方法。具体细节都在代码里了,都带有注释,建议粘到ide中看,在线看需要拉滚动条
public class Manage {
// 定义一个存储54张扑克牌的集合
private List<Poker> pokerArray = new ArrayList<Poker>();
// 定义存储三张底牌的集合
private List<Poker> thridArray = new ArrayList<Poker>();
/*
* 这个地方本来是新建个对象,再去测试时发现在哪里又新建一个对象不行所以回来查看代码能不能改,直接用this调用即可,最后肯定是使用Manage对象调用方法
* 那么this用在这个地方,我觉得对于初学者来说已经是一个很明智的选择了
*/
// Manage manage = new Manage();
public List<Poker> getThridArray() {
return thridArray;
}
public void setThridArray(List<Poker> thridArray) {
this.thridArray = thridArray;
}
public List<Poker> getPokerArray() {
return pokerArray;
}
public void setPokerArray(List<Poker> pokerArray) {
this.pokerArray = pokerArray;
}
// 定义组装54张扑克牌的方法
/*
* 返回值类型:扑克牌随机生成后就在最大的容器中,要分牌时直接获取就行了。返回值给void 参数列表:随机生成数字,你要个大嘴巴子参数
*
* 1.扑克牌有花色跟数字,一个扑克牌对象只能存一张牌的信息,那么就需要54个扑克牌对象。 2.数字由遍历的i进行赋值,类型(花色)由对象的set方法设置。
* 3.采用循环进行生成,需要套两层循环
*/
public void assemble() {
// 外层的i用来控制给扑克牌对象设置花色
for (int i = 1; i <= 4; i++) {
// 内层13次循环控制生成13个数字,4*13=52
for (int j = 1; j <= 13; j++) {
Poker poker = new Poker();
if (j == 1) {
poker.setNum("A");
poker.setFlag(14);
} else if (j == 11) {
poker.setNum("J");
poker.setFlag(11);
} else if (j == 12) {
poker.setNum("Q");
poker.setFlag(12);
} else if (j == 13) {
poker.setNum("K");
poker.setFlag(13);
} else {
if (j == 2) {
poker.setNum(j);
poker.setFlag(15);
} else {
poker.setNum(j);
poker.setFlag(j);
}
}
if (i == 1) {
poker.setType("♥");
} else if (i == 2) {
poker.setType("♠");
} else if (i == 3) {
poker.setType("♦");
} else if (i == 4) {
poker.setType("♣");
}
this.getPokerArray().add(poker);
}
}
// 大王小王比较特殊,它两是没花色的,所以另外加入集合
this.getPokerArray().add(new Poker("大王", "", 17));
this.getPokerArray().add(new Poker("小王", "", 16));
}
// 定义分牌方法
// 三个玩家参与游戏,三人交替摸牌,每人17张牌,后三张留作底牌。
/*
* 返回值类型:不需要返回值类型,我只要能把牌发到三个玩家手上就行了 参数列表:需要传入三个参数,分别对应三个玩家,我得知道是谁在玩好吧
*
* 分析:1.首先我必须先拿到打乱的54张牌,然后通过54牌集合的get方法来获取Poker对象 2.这里要用到循环,因为分牌是个重复的动作,所以需要用到循环
* 3.循环中做什么呢,就取大容器里的牌给用户 4.这里的牌只能发51张剩下的三张怎么处理。
*/
public void division(User user1, User user2, User user3) {
List<Poker> countArr = this.getPokerArray();
int count = 0;
for (int i = 0; i < 17; i++) {
// 这里的想法是发牌都发第一张牌,这样每发一张牌后,下标为零的地方就会有新的元素补上,但是发现对ArrayList并不了解,且结果不对,所以想出一下策略
user1.getUserArray().add(countArr.get(count));
user2.getUserArray().add(countArr.get(count + 1));
user3.getUserArray().add(countArr.get(count + 2));
count += 3;
}
thridArray.add(countArr.get(count));
thridArray.add(countArr.get(count + 1));
thridArray.add(countArr.get(count + 2));
}
// 定义查看手牌,底牌的方法
/*
* 返回值类型:查看牌,你要个锤子返回值 参数列表:不需要参数就行了
*
* 分析:1.获取到各个用户的对象,展示就完了
*
*/
public void chaKan(User user1, User user2, User user3) {
System.out.println(user1.getName() + "的手牌是:");
List<Poker> arr1 = user1.getUserArray();
Collections.sort(arr1);
for (Poker poker : arr1) {
System.out.print(poker + " ");
}
System.out.println();
System.out.println();
System.out.println(user2.getName() + "的手牌是:");
List<Poker> arr2 = user2.getUserArray();
Collections.sort(arr2);
for (Poker poker : arr2) {
System.out.print(poker + " ");
}
System.out.println();
System.out.println();
System.out.println(user3.getName() + "的手牌是:");
List<Poker> arr3 = user3.getUserArray();
Collections.sort(arr3);
for (Poker poker : arr3) {
System.out.print(poker + " ");
}
System.out.println();
System.out.println();
System.out.println("底牌是:");
List<Poker> thridArr = this.getThridArray();
Collections.sort(thridArr);
for (Poker poker : thridArr) {
System.out.print(poker + " ");
}
}
}
最后是运行类
/*
*需求:
* 1. 组装54张扑克牌
* 2. 将54张牌顺序打乱
* 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,后三张留作底牌。
* 4. 查看三人各自手中的牌、底牌
*
* 分析:
* 1.这里定义一个扑克牌类比较好,因为有两个扑克牌不但有数字,而且扑克牌还有花色,一个变量不足以表示
* 2.由于要进行分牌,所以需要定义一个用户类,用户类中应该有存储扑克牌的集合,再给用户一个名字吧。
* 3.给三个用户分牌后,用一个集合装起来,然后遍历这个集合,输出集合中的所有poker对象
*/
public class DouDiZhuMain {
public static void main(String[] args) {
// 创建对象
Manage manage = new Manage();
// 调用组装54张牌的方法
manage.assemble();
// 这边强转了,后面寻求其他解决办法
// 获取54张牌的集合
ArrayList<Poker> numArray = (ArrayList<Poker>) manage.getPokerArray();
// 将顺序打乱,洗牌
Collections.shuffle(numArray);
// for (Poker poker : numArray) {
// //这里的toString方法在必要时可以进行重写,因为输出的格式不太好看
// System.out.println(poker);
// }
// 定义三个玩家
User user1 = new User("林国滨", new ArrayList<Poker>());
User user2 = new User("君哥", new ArrayList<Poker>());
User user3 = new User("萌姐", new ArrayList<Poker>());
// 调用分牌方法
manage.division(user1, user2, user3);
// 调用查看牌方法
manage.chaKan(user1, user2, user3);
}
}
感谢知乎小伙伴提出的问题:如何排序的?
从源码中可以看出,这里的Poker类实现了Comparable接口,这个接口中就只有一个compareTo方法。这个方法的返回值是用来比较大小的,分为正数,零,负数,对应大于,等于,小于三种可能。
最后上结果图
如果你打出了该结果,恭喜你,离成功又进了一步!