一、前言
本人Java小白,一直想做一个斗地主游戏,正好最近学习到了集合。我们都知道集合分为(Collection(单列集合)家族和Map(双列/映射集合)家族)有着长度可变的特性,用来存储斗地主的卡牌再适合不过了。于是今天从下午五点多写到了晚上,主要是中间有几个地方把我卡住了很长时间。
二、代码
1、创建需要用到的类
按照Java面向对象的设计思想,我首先创建了三个类,People类——用于实例化为玩家、Card类——用于实例化为不同的牌、Room类———模拟斗地主的房间窗口.
1、People类
package com.xiaoxaio.www;
import java.net.IDN;
import java.util.ArrayList;
import java.util.List;
public class People {
private String name; // 用户名
private String ID;
private int HappyBeanNum; // 欢乐豆数量
public List<Card> MyCard;
public People(){
this.MyCard=new ArrayList<>();
};
public People(String name,String ID,int HappyBeanNum){
this.name=name;
this.ID=ID;
this.HappyBeanNum=HappyBeanNum;
this.MyCard=new ArrayList<>();// 引用数据类型,一定要进行初始化,分配内存空间
}
public void setMyCard(Card myCard) {
MyCard.add(myCard);
}
public List<Card> getMyCard() {
return MyCard;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getID(){
return this.ID;
}
public void setID(String ID){
this.ID= ID;
}
public int getHappyBeanNum(){
return HappyBeanNum;
}
public void setHappyBeanNum(int HappyBeanNum){
this.HappyBeanNum=HappyBeanNum;
}
@Override
public String toString(){
return "用户名:"+name+"\t"+"欢乐豆:"+HappyBeanNum+"\n";
}
}
2、Card类
package com.xiaoxaio.www;
// 每一张牌都是一个Card对象
public class Card implements Comparable<Card>{
private String color;
private String number;
private int BigSmall;
public Card(){};
public Card(String color,String number,int BigSmall){
this.number=number;
this.color=color;
this.BigSmall=BigSmall;
}
@Override
public String toString(){
return color+number;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public int getBigSmall() {
return BigSmall;
}
public void setBigSmall(int bigSmall) {
BigSmall = bigSmall;
}
@Override
public int compareTo(Card card_next) {
return this.BigSmall-card_next.BigSmall;
}
}
3、Room类
注意:1、创建一个AllCards数组,用来存放一副完整的扑克牌
2、创建一个arrays数组用来存放玩家
package com.xiaoxaio.www;
import java.util.*;
public class Room {
private List<Card> AllCards =new ArrayList<>(); // 首先存放一个能放一副扑克的列表容器,可以存放多个Card类型的对象
private ArrayList<People> arrays = new ArrayList<>(); // 创建一个用来装People(玩家)的数组
}
里面有很多细节后面会再回头来分析。
三、做一副扑克牌并洗牌
我们在Card类里面定义了number属性和color花色属性,结合数组即可做出一副扑克牌
步骤:1、创建一个numbers数组用来存放所有的数;一个colors数组用来存放四种花色
2、通过for/foreach循环将花色和数值组合在一起,最后别忘了加上大小王!
public class Room {
private List<Card> AllCards =new ArrayList<>(); // 首先存放一个能放一副扑克的列表容器,可以存放多个Card类型的对象
private ArrayList<People> arrays = new ArrayList<>(); // 创建一个用来装People(玩家)的数组
//用实例代码快来实现,每次实例化一个对象的时候就会创建
{ //首先要制作一副扑克牌
String[] numbers={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[] colors={"♣","♦","♥","♠"};
int count=1;
for(String number:numbers)
{count++;
for(String color:colors) {
AllCards.add(new Card(color,number,count));
}}
Collections.addAll(AllCards,new Card("👲","",++count),new Card("🃏","",++count));
System.out.println(AllCards.toString());
}
//ArrayList<People> arrays = new ArrayList<>(); // 创建一个用来装People(玩家)的数组
People peo1 = new People("张三", "1001", 8769);
People peo2 = new People("李四", "1101", 10000);
People peo3 = new People("王五", "3034", 3001);
/*arrays.add(new People("张三","1001",8000));
arrays.add(new People("李四","1101",8000));
arrays.add(new People("王五","3034",8000));*/
arrays.add(peo1);
arrays.add(peo2);
arrays.add(peo3);
System.out.println(arrays);
Tip:玩家类的大篇幅设计与实例化在这篇文章中比较鸡肋,主要是为后续开发一个完整的欢乐斗地主项目做准备,代码附上
洗牌
下面我们开始洗牌------------
这里我设计了两种方法,第一种比较简单,直接调用方法,第二种则是手动交换
// 洗牌
public void MixCard(){
Collections.shuffle(AllCards);
System.out.println("洗过后的牌为:"+AllCards);
}//第二种方法打乱扑克牌,直接调用shuffle
/*public void MixCard(){
int i,temp;
Card tmp;
for(i=0;i<AllCards.size();i++){
temp=(int)(Math.random()*54);
tmp=AllCards.get(i);
AllCards.set(i,AllCards.get(temp));
AllCards.set(temp,tmp);
}
}*/
四、发牌
这一步在开发的时候困扰了我很久,我一直在想怎样让三位玩家接收到我发给他的牌或者说怎样把牌发个玩家,一直没有思路,吃完饭的时候我突然灵光乍现,想到可以在People类里面定义一个
public List<Card> MyCard;的引用类型属性,MyCard是一个泛型为Card的List集合类型,可以通过它把牌add(加入)到集合里面,这样就实现了用户拿到扑克牌的目的,当然仅仅这样做是不够的,在定义MyCard的setter方法时也要进行改动,大家自己看哈
准备条件做完了之后就可以发牌了
public void GiveCard(){
int j;
for(j=0;j<AllCards.size()-3;j++){
int t=j%3;
People people = arrays.get(t);
people.setMyCard(AllCards.get(j));
}
//将三张地主牌发给地主
List<Card> cards = AllCards.subList(AllCards.size() - 3, AllCards.size());// 直接拿到三张牌的集合
int flag;
flag=(int)Math.random()*3;
arrays.get(flag).setMyCard(AllCards.get(51));
arrays.get(flag).setMyCard(AllCards.get(52));
arrays.get(flag).setMyCard(AllCards.get(53));
for(int k=0;k<3;k++){
System.out.println(arrays.get(k).getName()+"的牌为:\t"+arrays.get(k).MyCard);
}
}
可以看出,我采用的是按照生活中例子,三个人轮番发牌,
People people = arrays.get(t);拿到本次要被发牌的玩家
people.setMyCard(AllCards.get(j)); 将牌发给该玩家(牌的顺序已经被打乱)
别忘了三张地主牌,这里我同样想了两种方式,个人觉得
List<Card> cards = AllCards.subList(AllCards.size() - 3, AllCards.size());// 直接拿到三张牌的集合 这条代码更好,虽然我用的不是这种哈哈哈
总结:这种方法虽然最终实现了发牌功能,但是偏晦涩难懂,对了大家也不要忘了在People类里面对MyCard进行初始化,我当时调试了很久不知道为啥报错,最后还是ai帮我找出来的。。
后期的维护成本也比较高,所以虽然这是我写的代码,但我本人觉得这种方法不好,在这里给大家提供另外一种发牌的算法或者说思路,大家可以使用HashMap集合使用name(用户名)和List<Card>作为键和值,本人是后来才在网上查阅到这种方法,改动对原来的代码结构变化太大耗费时间,推荐大家尝试!
五、对玩家拿到手里的牌进行排序
// 系统自动完成对每个人的牌进行排序
// 思路:利用字符串具有索引的方法,可以考虑使用substring或者chartAt方法将数字类型部分取出来再利用包装类方法转换成整型进行比较
// 每个人的牌都要进行排序
public void sorted(){
int m;// m代表每位玩家手里的牌(集合中每个元素)的索引
/*for(m=0;m<3;m++){
List<Card> myCard = arrays.get(m).MyCard;
for(int n=0;n<myCard.size();n++){
//System.out.println(myCard.get(n));//仅仅到这里是不够的,list<Card>类型的变量调用get()方法之后得到的是一个Card对象
int num1 = Integer.valueOf(myCard.get(n).getNumber());
int num2 = Integer.valueOf(myCard.get(n+1).getNumber());
if (num2<num1){
myCard.set(n,myCard.get(n+1))
}// 很明显,这个排序方法是有问题的
}
}*/
for(m=0;m<3;m++){
List<Card> myCard = arrays.get(m).MyCard;
Collections.sort(myCard);
/*Collections.sort(myCard,new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
});*/
}
System.out.println();
System.out.println("----------------------------排序完成------------------------------------------------------");
for(int k=0;k<3;k++){
System.out.println(arrays.get(k).getName()+"的牌为:\t"+arrays.get(k).MyCard);
}
}
这一部分其实没啥好说的,虽然我当时卡了也很久。。上面记录了一些我的错误思路和操作哈哈哈哈,大家只要记得在集合中对自定义的类的对象进行排序时,有两种方式,第一种是为Collections.sort()方法提供一个Comparator的匿名内部类对象或者让父类(Card类)实现Comparable接口。
顺便提一嘴:排序的算法来源于黑马程序员磊哥,为牌注入大小属性,太牛啦!!!!!!!
好啦,本期的分享到此结束!个人觉得这个简单小项目对于初入Java的小白来说如果不看视频的前提下直接开干(me嘿嘿)是一个有一定难度的小项目,很有意思,值得尝试。
我们下期再见!