JAVA實驗四:保皇
題目
模擬保皇遊戲開始的發牌過程。規則:4副撲克,5個玩家。1)有一個大王標記為皇上。每次發牌時,所發牌中有該大王的玩家是皇上。2)皇帝選擇侍衛(也叫保兒、腿子,遊戲過程中與皇帝一夥):作為皇上的玩家從自己的牌中選擇一張擁有相同三張(點數和花色都相同)的一張牌(不能是2、3、大小王),其他四個玩家中有這張牌的就是侍衛。例如,皇上有三個紅桃5,其他四個玩家中有紅桃5的玩家就是侍衛。特殊情況是:1)皇上有一套四張牌相同的點數的牌,皇帝可以自己做侍衛;2)皇帝沒有滿足要求的牌,無法獲得侍衛。程式要求:程式啟動後生成5個玩家,並自動給他們發牌。然後輸出:1)皇帝和侍衛的名字及其手裡的牌(每張牌輸出為“花色”+“點數”,如紅桃5,牌之間用“,”分割),並按照大王、小王、2、A、K、Q、J、10、9、8、7、6、5、4、3的順序排列,相同點數但不同花色的牌要把相同花色的牌放在一起;2)那張作為侍衛所特有的牌(“花色”+“點數”)。如果無法得到侍衛,則程式輸出相應的提示。例如,程式執行後輸出如下的結果:
皇帝是:玩家1
皇帝的牌是:[皇上, 小王, 小王, 小王, 小王, 方片2, 黑桃2, 黑桃A,黑桃A, 紅桃A, 方片K, 梅花K, 黑桃K, 紅桃K, 梅花Q, 梅花Q, 黑桃Q, 方片J, 方片J, 方片J, 紅桃J, 梅花9, 黑桃9, 黑桃9, 方片8, 梅花8, 紅桃8, 梅花7, 黑桃7, 黑桃7, 紅桃7, 梅花6, 梅花6, 黑桃6, 黑桃6, 方片5, 梅花5, 黑桃5, 黑桃5, 梅花4, 梅花4, 梅花4, 方片3, 紅桃3]
侍衛對應的牌是:方片J
侍衛是:玩家2
侍衛的牌是:[方片2, 黑桃2, 紅桃2, 方片A, 方片K, 梅花K, 梅花K, 黑桃K, 紅桃K, 紅桃K, 黑桃Q, 紅桃Q, 方片J, 方片10, 黑桃10,紅桃10, 紅桃10, 紅桃10, 方片9, 紅桃9, 方片8, 梅花8, 梅花8, 黑桃8, 黑桃8, 黑桃8, 紅桃8, 紅桃8, 方片7, 黑桃7, 黑桃7, 方片6, 黑桃6, 黑桃5,梅花4, 黑桃4, 紅桃4, 紅桃4, 方片3, 梅花3, 黑桃3, 紅桃3, 紅桃3]
答案
import java.util.*;
import java.util.Map.Entry;
public class BaoHuang
{
private List<Card> list=new ArrayList<Card>();//用於存所有的牌//之所以用介面型別是因為更抽象更符合實際
private Player []players;
private int sumpalyers=5;//沒有直接代數是為了考慮之後改動方便
private int emperor;
private int baozi;
private Card luckcard;
////////////創造4*13+4+3+1張牌
public void creatCard()
{
for(int i=0;i<13;i++)//每副牌從A—K共13種牌
{
for(int j=0;j<4;j++)//每種牌有4個花色
{
for(int k=0;k<4;k++)//一共有4副牌
{
Card c=new Card(j,i);
list.add(c);//j花色的i牌
}
}
}
for(int k=0;k<4;k++)//每副牌中都有1張小王,一共四副牌
{
list.add(new Card(4,16));
}
for(int k=0;k<3;k++)//每副牌中都有1張大王,一共四副牌,但是有一張牌上標有皇帝
{
list.add(new Card(5,17));
}
Card card=new Card(6,18);
list.add(card);
}
//////////創造sumpalyers個玩家
public void creatPlayer()
{
players=new Player[sumpalyers];
for(int i=0;i<sumpalyers;i++)
{
int j=i+1;
players[i]=new Player("玩家"+j);
}
}
///////////之所以用List型別的是為了好洗牌
public void shuffleCard()
{
Collections.shuffle(list);
}
////////////////隨機發牌並標記誰是皇帝
public void randomCard()
{
/*for(int i=0;i<list.size();i++)
{
for(int j=0;j<sumpalyers;j++)
{
if(list.get(i).isEmp()==true)
{
emperor=j;
}
players[j].addCard(list.get(i));
}
}*/
for(int i=0;i<list.size();)/////////////////不知道為什麼上面的發牌方式是錯誤的
{
for(int j=0;j<sumpalyers;j++)
{
if(list.get(i).getCompletecard().equals("皇帝"))
{
emperor=j;
}
players[j].addCard(list.get(i));//玩家j得到牌後,緊緊攥在自己的手裡
i++;
if (i >= list.size())
return;
}
}
}
////////////檢查能否找到保子
public void checkCard()
{
baozi=-1;
luckcard = players[emperor].checkedCard();//儲存皇帝的那張牌
if(luckcard==null)//如果拿到皇帝那張牌的人也就是皇帝找不出一張可以找到保子的牌的話
{
baozi=-1;
return ;
}
for(int i=0;i<sumpalyers;i++)
{
if(i!=emperor)
{
if(players[i].checkAndPick(luckcard)==true)
{
baozi=i;
}
}
}
}
////////////////列印結果
public void showCard()
{
System.out.println("皇帝是:" + players[emperor].getName());
System.out.print("皇帝的牌是:");
players[emperor].showCards();
if(baozi==-1)
{
System.out.println("無法得到侍衛");
}
else
{
System.out.println("侍衛對應的牌是:" + luckcard.getCompletecard());
System.out.println("侍衛是:" + players[baozi].getName());
System.out.print("侍衛的牌是: ");
players[baozi].showCards();
}
}
/////////////不能為了靜態而靜態
public void startGame()
{
creatCard();
creatPlayer();
shuffleCard();
randomCard();
checkCard();
showCard();
}
public static void main(String[] args)
{
BaoHuang game=new BaoHuang();
game.startGame();
}
}
class Card implements Comparable
{
private String color;//花色,每張牌有4種花色
private String type;//牌的種類,每張牌有13+2種
private int comparecolor;//排序時用int型別進行便於compare
private int comparetype;//輸出時用String型別形將數字對應成自己想要代表的字串
private String completecard;//完整輸出的資料
public void setComparecolor(int comparecolor) {
this.comparecolor = comparecolor;
}
public void setComparetype(int comparetype) {
this.comparetype = comparetype;
}
public int getComparecolor()
{
return this.comparecolor;
}
public int getComparetype()
{
return this.comparetype;
}
public String getCompletecard()
{
return completecard;
}
public Card(int comparecolor,int comparetype)
{
if(comparetype==1)
comparetype=13;
if(comparetype==1)
comparetype=14;
if(comparetype==2)
comparetype=15;
this.comparecolor=comparecolor;
this.comparetype=comparetype;
changeColorAndType(comparecolor,comparetype);
}
//////////判斷是否為皇帝
public boolean isEmp()
{
if(this.comparetype==18) return true;
else return false;
}
/*
*將數字轉換為對應的花色和種類;
*/
public void changeColorAndType(int comparecolor,int comparetype)
{
switch(comparecolor)//這裡將小王、大王、皇帝與種類統一處理
{
case 3:
this.color="方片";
break;
case 2:
this.color="梅花";
break;
case 1:
this.color="黑桃";
break;
case 0:
this.color="紅桃";
break;
case 4:
case 5:
case 6:
this.color="";
break;
}
switch(comparetype)//這裡將小王、大王、皇帝對應的種類做特殊的統一處理,不需要單獨處理三者的種類
{
case 11:
this.type="J";
break;
case 12:
this.type="Q";
break;
case 13:
this.type="K";
break;
case 14:
this.type="A";
break;
case 15:
this.type="2";
break;
case 16:
this.type="小王";
break;
case 17:
this.type="大王";
break;
case 18:
this.type="皇帝";
break;
default:
this.type=String.valueOf(comparetype);
break;
}
this.completecard=this.color+this.type;
}
/*
* 輸出皇帝和侍衛對應的牌的時候都是按照順序輸出的
* 皇帝>大王>小王>2>1>A>K>Q>J>9>....>3
* */
public int compareTo(Object o)
{
Card card=(Card)o;
if(this.comparetype>card.comparetype)
return -1;
else if(this.comparetype<card.comparetype)
return 1;
else
{
if(this.comparecolor>card.comparecolor)
return -1;
else if(this.comparecolor<card.comparecolor)
return 1;
else return 0;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((completecard == null) ? 0 : completecard.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Card other = (Card) obj;
if (completecard == null) {
if (other.completecard != null)
return false;
} else if (!completecard.equals(other.completecard))
return false;
return true;
}
}
class Player//每個人都有牌和相對應的張數
{
@SuppressWarnings("unchecked")
private List li=new LinkedList();
private TreeMap<Card,Integer> cards=new TreeMap<Card,Integer>();//用於存所有的牌//之所以用介面型別是因為更抽象更符合實際
private String name;//玩家的名字
public Player(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
/*
* 這裡是發牌的過程,前面每張牌的顏色和對應的字母已經知道了
* 這時可以發牌
* 用Map存,顏色字母——張數
* 如果有重複的,移除然後新增張數再放入
* 如果沒有的話,就直接加入
*/
public void addCard(Card card)
{
if(cards.containsKey(card)==true)
{
int num=cards.get(card);
cards.remove(card);
cards.put(card, num+1);
}
else
{
cards.put(card, 1);
}
}
/*
* 通過keySet方法獲取所有的key值之後
* 看key對應的張數
* 如果有4張一樣的,自己既是保子也是皇帝
* 如果有3張一樣的,那麼有保子
* 如果沒有3/4張一樣的,那麼沒有保子
*/
public Card checkedCard()
{
for(Card key:cards.keySet())//使用keySet()方法獲取所有的key值,返回型別是Card
{
if(cards.get(key)==4)
{
return null;
}
if(cards.get(key)==3)
{
return key;
}
}
return null;
}
/*
* 檢查平民的牌並挑選保子
*/
public boolean checkAndPick(Card luckcard)
{
if(cards.containsKey(luckcard)==true)
{
return true;
}
return false;
}
/////////按照格式輸出相應的牌
public void showCards()
{
int flag=0;
System.out.print("[");
//List<Map.Entry<Card, Integer>> list = new ArrayList<Map.Entry<Card,Integer>>(cards.entrySet());
//Collections.sort(list,new CardsCompare());
Iterator<Card> it=cards.keySet().iterator();
for(int i=0;it.hasNext();i++)
{
Card c=(Card)it.next();
int integer=(Integer)cards.get(c);
if(flag==0)
{
System.out.print(c.getCompletecard());
flag=1;
}
else
{
for(int j=0;j<integer;j++)
{
System.out.print(", "+c.getCompletecard());
}
}
}
/*for (Map.Entry<Card, Integer> entry : cards.entrySet())
{
if(flag==0)
{
System.out.print(entry.getKey().getCompletecard());
flag=1;
}
else
{
System.out.print(", "+entry.getKey().getCompletecard());
}
}*/
System.out.println("]");
}
}