本人水平有限,文章中如果出现什么不正确或者模糊的地方,还请各位小伙伴留下评论,多多指教 : )
题目描述
一副新的扑克牌,除去大小鬼剩下52张牌(这副牌包括梅花、方块、红桃和黑桃4种花色,每种花色又有13种牌,分别是A、2、3、4、5、6、7、8、9、10、J、Q、K)。发牌者把这52张牌随机发给4个玩家,直到把所有牌发完。按上面要求写一个发牌程序,要求把4个玩家手里的牌都打印出来。
要求:
用你最熟悉的计算机语言实现上面程序,并画出UML图。(程序必须完整,可以直接运行)
目的:
1)主要考察面向对象的设计能力。
2)UML知识。
UML 类图
思路概述
根据面向对象的思想,这里实现3个类,分别的卡牌(Card)、玩家(Player)以及游戏规则(GameRule)。可以看出这三个类之间的关系可以描述为Player类和GameRule类中都需要用到Card类。
这里解释一下Card中weight的变量,因为我们牌随机分发的过程是跟这个变量有关的。int weight的值是一个来自于1到1000之间的随机数,我们首先按花色和数字生成52张牌,于此同时给每张拍的weight赋值(一个随机数)。
可以看出每个card在实例化之后都会有一个随机的weight值。然后根据这个weight值从小到大再对52张牌排序。
大家可以看到,现在的ArrayList cards 中的卡牌已经按照weight值从小到大进行了排序这样一来得到的就是一组相对随机的牌。最后我们把这个cards数组中的前13张牌分给第一个玩家,然后下标为14到26的牌分给第二个玩家,27到39的分给第三个,然后最后13张牌分给最后一个玩家。
再通过一些函数将牌进行排序,再对花色与数字进行判断,就能得出如下结果:
重要函数
Class GameRule:
/**
* 产生一随机排序的套牌
* @return ArrayList<Cards>
*/
public ArrayList<Card> MakeCards(){
//实例化ArrayList<Card> cards
cards =new ArrayList<>();
for(int i =0 ;i<4;i++){
//i从0到3,4个数代表花色,j从1到13,代表数字
for (int j =1;j<=13;j++){
//产生一个1到1000的随机数
int r =1+(int)(Math.random()*1000);
//实例化一个Card对象
Card card =new Card(i,j,r);
//把card对象加入到cards的ArrayList当中
cards.add(card);
}
}
//调用了sortCards()方法,返回一套随机排序的卡牌
return sortCards(cards);
}
/**
* 将卡牌随机打乱
* @param cards
* @return cards
*/
public ArrayList<Card> sortCards(ArrayList<Card> cards){
int n =cards.size();
int noswap=1; //每轮扫描有无交换标志,1表示无交换,0表示有交换
//从数组里面的最后一个元素向前扫描
for (int i=0;i<n-1;i++){
noswap=1;
for(int j=n-1;j>i;j--){
Card card1 = cards.get(j);
Card card2 = cards.get(j - 1);
if (card1.weight < card2.weight) {
cards.set(j, card2);
cards.set(j - 1, card1);
noswap=0; //修改交换的标记
}
}
if(noswap==1) //如果某一论没有发生交换,则说明排序完成,冒泡算法终止
return cards;
}
return cards;
}
/**
* 按数字的大小整理手牌
* @param cards 传入手牌
* @return
*/
public ArrayList<Card> trimHand(ArrayList<Card> cards){
int n=cards.size();
int noswap=1;
//花色排序
for (int i=0;i<n-1;i++){
noswap=1;//每轮扫描有无交换标志,1表示无交换,0表示有交换
for(int j=n-1;j>i;j--){
Card card1 = cards.get(j);
Card card2 = cards.get(j - 1);
if (card1.num < card2.num) {
//花色交换
cards.set(j, card2);
cards.set(j - 1, card1);
noswap=0;
}
}
if(noswap==1)//如果某一论没有发生交换,则说明排序完成,冒泡算法终止
return cards;
}
return cards;
}
}
这里重点解释一下按照weight大小进行排序和按照num大小进行排序的区别。
将weight作为排序的依据,目的是模拟一个随机的过程,因为52张牌的weight是随机产生的 ,那么按照weight从小达大排列出来卡牌必然也是随机的。
将num的大小进行排序的依据,只是为了让玩家看到的牌更加舒服而已(在网上斗过地主的小伙伴应该都明白),相当于一个体验优化。
总结
基本上最关键的几个函数都已经在上面讲解了,剩下的内容(例如android界面的显示、数字花色的判断)都是一些小的细节问题,大家可以从完整的代码中的查看。