请设计用于通用扑克牌的数据结构。并说明你会如何建立该数据结构的子类。实现“二十一点”游戏

 

Java 扑克发牌算法实现

利用Random类的对象的链表-随机的顺序存储一副52张的纸牌。用含有两个字符的字符串表明纸牌,例如“1C”表示梅花A,”JD”表示方片J等。从栈中输出4手牌,每手牌有13张纸牌。java

 

 

 

  1. 首先给扑克牌中每张牌设定一个编号,下面算法实现的编号规则以下:  
  2.  /*   红桃按照从小到大依次为:1-13  
  3.   u    方块按照从小到大依次为:14-26  
  4.   u    黑桃按照从小到大依次为:27-39  
  5.   u    梅花按照从小到大依次为:40-52  
  6.   u    小王为53,大王为54 
  7.   算法实现以下:  
  8.   u    首先按照以上编号规则初始化一个包含108个数字的数组  
  9.   u    每次随机从该数组中抽取一个数字,分配给保存玩家数据的数组  */
  10.   实现该功能的代码以下所示:  
  11.     package com.zuidaima;  
  12.   import Java.util.*;  
  13.   /** 
  14.   * 发牌算法的实现 
  15.   * 要求:把2副牌,也就是108张,发给4我的,留6张底牌 
  16. *     @author www.zuidaima.com 
  17. */  
  18. public class Exec{  
  19.     public static void main(String[] args){  
  20.        //存储108张牌的数组  
  21.        int[] total = new int[108];  
  22.        //存储四个玩家的牌  
  23.        int[][] player = new int[4][25];  
  24.        //存储当前剩余牌的数量  
  25.        int leftNum = 108;  
  26.        //随机数字  
  27.        int ranNumber;  
  28.        //随机对象  
  29.        Random random = new Random();  
  30.        //初始化数组  
  31.        for(int i = 0;i < total.length;i++){  
  32.            total[i] = (i + 1) % 54;  
  33.            //处理大小王编号  
  34.            if(total[i] == 0){  
  35.               total[i] = 54;   
  36.            }  
  37.        }  
  38.        //循环发牌  
  39.        for(int i = 0;i < 25;i++){  
  40.            //为每一个人发牌  
  41.            for(int j = 0;j < player.length;j++){  
  42.               //生成随机下标  
  43.               ranNumber = random.nextInt(leftNum);  
  44.               //发牌  
  45.               player[j][i] = total[ranNumber];  
  46.               //移动已经发过的牌  
  47.               total[ranNumber] = total[leftNum - 1];  
  48.               //可发牌的数量减小1  
  49.               leftNum--;     
  50.            }    
  51.        }  
  52.        //循环输出玩家手中的牌  
  53.        for(int i = 0;i < player.length;i++){  
  54.            for(int j = 0;j < player[i].length;j++){  
  55.               System.out.print(" " + player[i][j]);    
  56.            }  
  57.            System.out.println();  
  58.        }  
  59.        //底牌  
  60.        for(int i = 0;i < 8;i++){  
  61.            System.out.print(" " + total[i]);   
  62.        }  
  63.        System.out.println();  
  64.     }  
  65. }  
  66.  

 

 完成一个变形版的纸牌21点游戏。该游戏来源于21点游戏,实现人机对战。算法

游戏说明以下:数组

(1)该游戏须要两副牌,没有Joker,共104张。每张“纸牌”应具备花色数字两个属性。app

(2)游戏在机器与人类玩家之间进行。游戏一开始应先洗牌(将104张牌打乱)。dom

(3)机器永远是庄家,因此永远先给机器发牌,机器的牌不可见,只能看到机器要了几张牌。机器中止要牌后,再给人类玩家发牌。ide

(4)游戏胜利与失败的条件与普通21相同;除此之外,一方在当前牌没有爆掉的前提下,若是下一张牌使得手中有两张彻底同样的牌(同数字、同花色)则马上胜利。函数

(5)游戏结束时机器的牌要所有显示,并提示谁胜利了。学习

程序设计要求以下:测试

(1)程序中应至少有Card类和CardGame类。优化

(2)Card类须要重写Object类的equals(Object o)函数,用于比较两张牌是否彻底同样;重写toString函数,用于输出牌时直接显示牌的花色与数字。

(3)CardGame类应具备shuffle(洗牌)、deal(发牌)、win(胜利判别)等函数。

(4)选择适当的java集合类来实现“发牌牌堆”和“手牌”(不容许都使用数组)。

 

  1. /* 
  2.  * To change this template, choose Tools | Templates 
  3.  * and open the template in the editor. 
  4.  */  
  5. package 21pointgame;  
  6. import java.util.ArrayList;  
  7. import java.util.Scanner;  
  8.   
  9. /** 
  10.  * 
  11.  * @author Soledad 
  12.  */  
  13. public class Main {  
  14.   
  15.     /** 
  16.      * @param args the command line arguments 
  17.      */  
  18.     public static void main(String[] args) {  
  19.         CardGame cg = new CardGame();  
  20.         cg.startGame();  
  21. // TODO code application logic here  
  22.     }  
  23. }  
  24. enum Color{  
  25.     HEARTS, DIAMOND, SPADE, CLUB  //红桃,方块,黑桃,梅花  
  26. }//***************学习点之一***************  
  27. class Card {  
  28.     private Color cardColor;  //牌的花色  
  29.     private int number;         //牌的面值  
  30.   
  31.     public Card(){  
  32.     }  
  33.   
  34.     public Card(Color c, int num) {  
  35.         cardColor = c;  
  36.         number = num;  
  37.     } //至关于C++中的赋值构造函数  
  38.       
  39.     @Override  
  40.     public boolean equals(Object obj) {  
  41.         if (obj == null)  
  42.             return false;  
  43.         else{  
  44.             if (obj instanceof Card){  
  45.                 return ((Card)obj).cardColor == this.cardColor &&((Card)obj).number == this.number ;  
  46.             }  
  47.             else   
  48.                 return false;     
  49.         }        
  50.      }//***************学习点之二***************  
  51.   
  52.     @Override  
  53.     public int hashCode() {  
  54.         int hash = 7;  
  55.         hash = 59 * hash + (this.cardColor != null ? this.cardColor.hashCode() : 0);  
  56.         hash = 59 * hash + this.number;  
  57.         return hash;  
  58.     }//****************学习点之三***************  
  59.     @Override  
  60.     public String toString() {  
  61.         String symbol;  
  62.         String numberString = "";  
  63.   
  64.         if (cardColor == Color.HEARTS)  
  65.             symbol = "红心";  
  66.         else if (cardColor == Color.DIAMOND)  
  67.             symbol = "方块";  
  68.         else if (cardColor == Color.SPADE)  
  69.             symbol = "黑桃";  
  70.         else  
  71.             symbol = "梅花";  
  72.   
  73.         if (number == 11) {  
  74.             numberString += "J";  
  75.         } else if (number == 12) {  
  76.             numberString += "Q";  
  77.         } else if (number == 13) {  
  78.             numberString += "K";  
  79.         } else if (number == 1){  
  80.             numberString += "A";  
  81.         } else{  
  82.             numberString += number;  
  83.         }  
  84.           
  85.         return symbol + "  " + numberString + "  ";  
  86.     }//****************学习点之四****************  
  87.   
  88.     public Color getCardColor() {  
  89.         return cardColor;  
  90.     }  
  91.   
  92.     public void setCardColor(Color cardColor) {  
  93.         this.cardColor = cardColor;  
  94.     }  
  95.   
  96.     public int getNumber() {  
  97.         return number;  
  98.     }  
  99.   
  100.     public void setNumber(int number) {  
  101.         this.number = number;  
  102.     }  
  103. }  
  104.   
  105. class CardGame{  
  106.     private Card[] cardHeap;      //排堆  
  107.     private int cardHeapPos;      //发到第几张牌了  
  108.     private ArrayList<Card>  playerCards ;     //玩家手牌  
  109.     private ArrayList<Card>  computerCards;    //电脑手牌  
  110.     //***************学习点之五***************  
  111.   
  112.     public CardGame() {  
  113.         cardHeap = new Card[104];  
  114.         playerCards = new ArrayList<Card>();  
  115.         computerCards = new ArrayList<Card>();  
  116.   
  117.         for(int i = 0; i < 104; i += 4 ) {  
  118.             for(int j = 0; j < 4; j ++) {  
  119.                 switch(j){  
  120.                     case 0:  
  121.                         cardHeap[i + j] = new Card(Color.HEARTS, i % 13 + 1);  
  122.                         break;  
  123.                     case 1:  
  124.                         cardHeap[i + j] = new Card(Color.DIAMOND, i % 13 + 1);  
  125.                         break;  
  126.                     case 2:  
  127.                         cardHeap[i + j] = new Card(Color.CLUB, i % 13 + 1);  
  128.                         break;  
  129.                     default:  
  130.                         cardHeap[i + j] = new Card(Color.SPADE, i % 13 + 1);  
  131.                         break;  
  132.                 }  
  133.             }  
  134.         }//经过两个循环分配给牌组两副牌(去除Jokers)  
  135.     }  
  136.   
  137.     void showCards(ArrayList<Card> cards) {  
  138.         for(Card element:cards) {  
  139.             System.out.print(element);  
  140.         }//****************学习点之六***************  
  141.         System.out.println();  
  142.     }  
  143.       
  144.     void shuffle(){  
  145.         cardHeapPos = 0; //归零  
  146.         Card[] tempHeap = new Card[104];  
  147.         int pos;  
  148.   
  149.         for(int i = 0 ; i < 104; i ++) {  
  150.             pos = (int)(Math.random() * 104);//**************学习点之七****************  
  151.             for(int j = 0; j < 104; j ++){  
  152.                 if(null == tempHeap[pos]) { //表示该空位没有分配值  
  153.                     tempHeap[pos] = new Card( cardHeap[i].getCardColor(), cardHeap[i].getNumber());  
  154.                     break;  
  155.                 } else {  
  156.                     pos = (pos + 1) % 104;  
  157.                 }  
  158.             }  
  159.         }//随机发牌堆到tempHeap中  
  160.   
  161.           
  162.         for(int i = 0; i < 104; i ++) {  
  163.             cardHeap[i].setCardColor(tempHeap[i].getCardColor());  
  164.             cardHeap[i].setNumber(tempHeap[i].getNumber());  
  165.         }//复制回原数组  
  166.     }  
  167.   
  168.     void deal(ArrayList<Card> cards) {  
  169.         cards.add(cardHeap[++cardHeapPos]);  
  170.     }  
  171.   
  172.     void gameOver(){  
  173.         System.out.println("庄家的牌");  
  174.         showCards(computerCards);  
  175.         System.out.println("庄家的总点数为 :" + getValue(computerCards));  
  176.         System.out.println("你的牌");  
  177.         showCards(playerCards);  
  178.         System.out.println("你的总点数为 :" + getValue(playerCards));  
  179.     }  
  180.   
  181.     int getValue(ArrayList<Card> cards) {  
  182.         int value = 0;  
  183.   
  184.         for(Card e:cards) {  
  185.             if (e.getNumber() >= 10)  
  186.                 value += 10;  
  187.             else if (e.getNumber() == 1)  
  188.                 value += 11;         //抽到“A”的时候是加1或加11, 这里先把加11  
  189.             else  
  190.                 value += e.getNumber();  
  191.         }  
  192.   
  193.         if(value > 21) {  
  194.             for(Card e:cards) {  
  195.                 if (e.getNumber() == 1){  
  196.                     value -= 10;  
  197.                     if (value < 21) break;  //若是小于21就跳出了  
  198.                 }  
  199.             }  
  200.         }  
  201.   
  202.         if(value > 21)  return -1;  
  203.         return value;  
  204.   
  205.     }  
  206.   
  207.    
  208.     boolean haveSame(ArrayList<Card> cards) {  
  209.         for(int i = 0; i < cards.size(); i ++) {  
  210.             for(int j = i + 1; j < cards.size(); j ++) {  
  211.                 if (cards.get(i).equals(cards.get(j))) {  
  212.                     return true;  
  213.                 }  
  214.             }  
  215.         }  
  216.         return false;  
  217.     }//return true表示cards中出现彻底重复的牌  
  218.   
  219.     void startGame() {  
  220.         boolean finish = false;  
  221.         Scanner in = new Scanner(System.in);//****************学习点之八****************  
  222.         String playerInput = "";         
  223.   
  224.         while(!finish) {  
  225.             playerCards.clear();  
  226.             computerCards.clear();  
  227.             shuffle();  
  228.             //庄家摸牌  
  229.             System.out.println("庄家摸牌...");  
  230.             int computerValue = 0;  
  231.             boolean getWinner = false;  
  232.             try {  
  233.                     Thread.sleep(3000);  
  234.             }  
  235.             catch(InterruptedException e) {  
  236.                     e.printStackTrace();  
  237.             }  
  238.             //若是庄家的总点数等于或少于16点,则必须拿牌,不然停牌  
  239.             while(computerValue <= 16) {  
  240.                 deal(computerCards);  
  241.                 getWinner = haveSame(computerCards);  
  242.                 if (getWinner) {  
  243.                     System.out.println("庄家摸到了彻底相同的牌,赢得了胜利!!!");  
  244.                     gameOver();  
  245.                     break;  
  246.                 }  
  247.                 computerValue = getValue(computerCards);  
  248.                 if (computerValue == -1) {  
  249.                     System.out.println("你赢了, 庄家牌摸爆了!!!");  
  250.                     gameOver();  
  251.                     getWinner = true;  
  252.                     break;  
  253.                 }  
  254.             }  
  255.   
  256.             if(!getWinner) {  
  257.                 System.out.println("庄家共有 " + computerCards.size() + " 张牌");  
  258.   
  259.                 while(!playerInput.equals("n")) {  
  260.                     deal(playerCards);  
  261.   
  262.                     getWinner = haveSame(playerCards);  
  263.                     if (getWinner) {  
  264.                         System.out.println("你摸到了彻底相同的牌,赢得了胜利!!!");  
  265.                         gameOver();  
  266.                         break;  
  267.                     }  
  268.                     System.out.println("你的牌:");  
  269.                     showCards(playerCards);  
  270.                     int playerValue = getValue(playerCards);  
  271.                      if (playerValue == -1) {  
  272.                         System.out.println("庄家赢了, 你牌摸爆了!!!");  
  273.                         gameOver();  
  274.                         getWinner = true;  
  275.                         break;  
  276.                     }  
  277.                     System.out.println("总点数为 " + getValue(playerCards));  
  278.                     System.out.println("是否继续要牌(y/n)?");  
  279.                     playerInput = in.nextLine();  
  280.                 }  
  281.             }  
  282.   
  283.             if(!getWinner) {  
  284.                 switch(win()) {  
  285.                     case 1: //玩家胜利  
  286.                         System.out.println("你胜利了!!!");  
  287.                         gameOver();  
  288.                         break;  
  289.                     case 2:  
  290.                         System.out.println("平局!!!");  
  291.                         gameOver();  
  292.                         break;  
  293.                     case 3:  
  294.                         System.out.println("庄家获胜!!!");  
  295.                         gameOver();  
  296.                         break;  
  297.                 }  
  298.             }  
  299.   
  300.             System.out.println("是否继续游戏(y/n)?");  
  301.             playerInput = in.nextLine();  
  302.               
  303.             if(playerInput.equals("n"))  
  304.                 finish = true;  
  305.         }  
  306.     }  
  307.     //若是是用户再也不摸牌而调用win, 则finish 设置为ture  
  308.     //返回1,说明玩家胜利  
  309.     //返回2,说明平局  
  310.     //返回3,说明电脑胜利  
  311.     int win() {  
  312.         //havaSame和双方是否爆牌已经在以前判断了(一旦有相同牌则获胜,一旦爆牌则失败,可见这两种情形优先级较高)  
  313.   
  314.         int playerValue = getValue(playerCards);  
  315.         int computerValue = getValue(computerCards);//获取玩家和电脑的总点数  
  316.   
  317.         if (playerValue > computerValue)  
  318.             return 1;  
  319.         else if (playerValue == computerValue)  
  320.             return 2;  
  321.         else  
  322.             return 3;  
  323.     }  
  324. }  

 

· 学习点之一:用enum枚举

enum通常用来枚举一组相同类型的常量。如性别、日期、月份、颜色等。对这些属性用常量的好处是显而易见的,不只能够保证单例,且要做比较的时候能够用”== ”来替换”equals”,是一种好的习惯(如本例中第45行)。

用法:如:

性别:

 

[java] view plain copy

print?

  1. publicenum SexEnum {  
  2.   male, female;  
  3. }  

 

本例中的花色:

[java] view plain copy

print?

  1. enum Color{  
  2.     HEARTS, DIAMOND, SPADE, CLUB  //红桃,方块,黑桃,梅花  
  3. }  

须要注意的是,枚举对象里面的值都必须是惟一的,特别的,咱们能够还经过enum类型名直接引用该常量,好比本例中的121,124,127等行经过类型名直接引用。

除此以外,咱们还能够往enum中添加新方法,这里就不加介绍了。

 

 

· 学习点之二:重写equals函数进行比较

      equals(Object o)函数本来是Object类下面的函数,我查了一下JAVA的API,截图以下:

 

简而言之,若是JAVA中默认的equals方法跟实际不符的话,就须要重写equals方法。咱们这里要对牌是否相同做比较,所以须要重写该方法(第40~50行):

[java] view plain copy

print?

  1. public boolean equals(Object obj) {  
  2.         if (obj == null)  
  3.             return false;//若是参数为空直接返回false  
  4.         else{  
  5.             if (obj instanceof Card){  
  6.                 return ((Card)obj).cardColor == this.cardColor &&((Card)obj).number == this.number ;//若是花色数字均相同则返回true不然false  
  7.             }  
  8.             else   
  9.                 return false;  //类型不一致返回false   
  10.         }        
  11.      }  

 

另外咱们注意到API里面写着:

“注意:当此方法被重写时,一般有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具备相等的哈希码。”这也就是咱们下面要学习的第三点。

· 学习点之三:重写hashcode()

问:也许上面的话有些晦涩难懂啊,咱们为何要重写hashcode()方法呢?

答: object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true;

 

注意:当此方法被重写时,一般有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具备相等的哈希码。以下:

(1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true

(2)当obj1.hashCode() ==obj2.hashCode()为false时,obj1.equals(obj2)必须为false

若是不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写以后目的是为了比较两个对象的value值是否相等。特别指出利用equals比较八大包装对象(如int,float等)和String类(由于该类已重写了equals和hashcode方法)对象时,默认比较的是值,在比较其它自定义对象时都是比较的引用地址。

hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。

 

总而言之,这样若是咱们对一个对象重写了equals,意 思是只要对象的成员变量值都相等那么equals就等于true,但不重写hashcode,那么咱们再new一个新的对象,当原对象.equals(新 对象)等于true时,二者的hashcode倒是不同的,由此将产生了理解的不一致,如在存储散列集合时(如Set类),将会存储了两个值同样的对 象,致使混淆,所以,就也须要重写hashcode()。

更通俗的说:

Object中的hashcode()方法在咱们建立对象的时候为每一个对象计算一个散列码,这个散列码是惟一的,因此若是2个对象的散列码相同,那他们必定是同一个对象。

本身定义的类也能够重写hashCode()方法,按照本身定义的算法计算散列码的生成。

Object中的equals()方法,比较的是2个对象的引用地址,包括他们各自的散列码,若是不一样,就认为是不一样的对象。

String类中重写了equals方法,比较的是他们字符串的内容。

在咱们这里本身定义的算法是(第53~58行):

[java] view plain copy

print?

  1. public int hashCode() {  
  2.         int hash = 7;  
  3.         hash = 59 * hash + (this.cardColor != null ? this.cardColor.hashCode() : 0);  
  4.         hash = 59 * hash + this.number;  
  5.         return hash;  
  6.     }  

 

· 学习点之四:重写toString()函数

由于它是Object里面已经有了的方法,而全部类都是继承Object,因此“全部对象都有这个方法”。

它一般只是为了方便输出,好比System.out.println(xx),括号里面的“xx”若是不是String类型的话,就自动调用xx的toString()方法。然而对于默认的toString()方法每每不能知足需求,须要重写覆盖这个方法。

比较易懂,就不具体说明了,见代码60~86行。

 

·学习点之五:动态数组ArrayList

      动态数组,便可以将 ArrayList想象成一种“会自动扩增容量的Array”。它的优势是能够动态地插入和删除元素,但牺牲效率。

有关使用ArrayList的例子,参考ArrayList用法,里面介绍的很详细。在咱们这题中,因为电脑和玩家的手牌都会由于抽牌而增长,所以将两者均设为ArrarList(第114,115行),方便动态插入。

 

· 学习点之六:加强for循环

      见代码138~140行,不少人没看懂for(Card element:cards) 这段,其实这是JDK5.0的新特性,做用是遍历数组元素。其语法以下:

 

  1. for(type element: array){  
  2. System.out.println(element);  
  3.   }   

 

 

· 学习点之七:善于使用随机数

      直接调用Math.random()能够产生一个[0,1)之间的随机数,注意区间是前闭后开的。本题当中由于共有104张牌,那么咱们直接用(int)Math.random()*104便可以产生[0,104)之间的随机数,对应一下数组的下标前闭后开恰好知足。

 

· 学习点之八:利用Scanner进行输入

      咱们都知 道,JAVA里输入输出函数十分的麻烦,尤为是输入。可喜的是,从SDK1.5开始,新增了Scanner类,简化了输入函数。如本题的221 行:Scanner in=new Scanner(System.in) 首先建立了一个in对象,而后in对象能够调用下列方法,读取用户在命令行输入的各类数据类型: nextDouble(), nextFloat, nextInt(),nextLine(),nextLong()等,上述方法执行时都会形成堵塞,等待用户在命令行输入数据回车确认,例如本题中的第 279行,在系统问询是否继续要牌(y/n)后,用in.nextLine()来接受玩家输入的值。

 

 

说了这么多,咱们来运行下程序:

e….我什么都没干 输了- -;

再来一次。。。

平局。。。行,就这样了,不要欺负电脑了。

咱们再回到题目和代码:

 

· 完成一个变形版的纸牌21点游戏。该游戏来源于21点游戏,实现人机对战。

游戏说明以下:

(1)该游戏须要两副牌,没有Joker,共104张。每张“纸牌”应具备花色数字两个属性。--直接对应代码24~37,60~102,117~134行

(2)游戏在机器与人类玩家之间进行。游戏一开始应先洗牌(将104张牌打乱)。--直接对应代码144~166行

(3)机器永远是庄家,因此永远先给机器发牌,机器的牌不可见,只能看到机器要了几张牌。机器中止要牌后,再给人类玩家发牌。--直接对应代码224~280行

(4)游戏胜利与失败的条件与普通21相同;除此之外,一方在当前牌没有爆掉的前提下,若是下一张牌使得手中有两张彻底同样的牌(同数字、同花色)则马上胜利。--直接对应代码181~205,208~217,311~323行

(5)游戏结束时机器的牌要所有显示,并提示谁胜利了。--直接对应代码172~179,283~297行

程序设计要求以下:

(1)程序中应至少有Card类和CardGame类。

(2)Card类须要重写Object类的equals(Object o)函数,用于比较两张牌是否彻底同样;重写toString函数,用于输出牌时直接显示牌的花色与数字。

(3)CardGame类应具备shuffle(洗牌)、deal(发牌)、win(胜利判别)等函数。

(4)选择适当的java集合类来实现“发牌牌堆”和“手牌”(不容许都使用数组)。

21点游戏是一个古老的扑克游戏,游戏的规则是:各个参与者设法使本身的牌达到总分21而不超过这个数值。扑克牌的分值取它们的面值,A充当1或者11分,J,Q和K人头牌都是10分。庄家VS1~7个玩家。在开局时,包括庄家在内的全部参与者都有两张牌。玩家能够看到他们的全部牌以及总分,而庄家有一张牌暂时是隐藏的。接下来,只要愿意,各个玩家都有机会依次再拿一张牌。若是是玩家的总分超过了21(称为引爆),那么这个玩家就输了。在全部玩家都拿了额外的牌后,庄家将显示隐藏的牌。只要庄家的总分等于或小于16,那么他就必须再拿牌。若是庄家引爆了,那么尚未引爆的全部玩家都将获胜,引爆的玩家打成平局。不然,将余下的各玩家的总分与庄家的总分作比较,若是玩家的总分大于庄家的总分,则玩家获胜。若是两者的总分相同,则玩家与庄家打成平局中。

 

 

游戏功能描述

  1. 建立一副扑克牌:
    包括四种花色:黑桃,红桃,梅花,方片
    包括十三种点数:2-10,J,Q,K,A
  2. 建立两名玩家(or多名)
    玩家至少要有ID,姓名,手牌等属性,手牌为扑克牌的集合
  3. 将建立好的扑克牌进行随机洗牌
  4. 从洗牌后的扑克牌的第一张开始,发给每一个玩家,按照一人一张的方式,每人发两张(or多张)
  5. 比较两名玩家手中的扑克牌,比较规则为:取两人各自手中点数最大的牌进行比较,点数大的赢;若两人各自的点数最大的牌相等,则再按照花色比较。

代码

//Card.Java

package card;

public class Card{
    private String color;
    private String number;

    public Card(String color, String number) {
        this.color = color;
        this.number = number;
    }

    public String getColor() {
        return color;
    }

    public String getNumber() {
        return number;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (!(obj instanceof Card))
            return false;
        Card other = (Card) obj;
        if (color == null) {
            if (other.color != null)
                return false;
        } else if (!color.equals(other.color))
            return false;
        if (number == null) {
            if (other.number != null)
                return false;
        } else if (!number.equals(other.number))
            return false;
        return true;
    }

}

 

//Cards.java

package card;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Cards {
    private List<Card> list = new ArrayList<Card>();

    //建立一副扑克牌
    public Cards(){
        System.out.println("-----------------建立扑克牌------------------");
        String[] color = {"黑桃", "红桃", "梅花", "方片"};
        String[] number = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J","Q","K", "A"};
        for(int i=0;i<color.length;i++)
            for(int j=0;j<number.length;j++){
                list.add(new Card(color[i], number[j]));
            }   
        System.out.println("----------------扑克牌建立成功!---------------");
    }

    //获取一副扑克牌
    public List<Card> getList() {
        return list;
    }

    //洗牌(打乱)
    public void shufCards(){
        System.out.println("----------------开始洗牌------------------------");
        Collections.shuffle(list);
        System.out.println("----------------洗牌结束------------------------");
    }

    //展现一副扑克牌
    public void showCards(){
        System.out.print("当前的扑克牌为:");
        System.out.print("[ ");
        for(int i=0;i<list.size();i++){
            System.out.print(list.get(i).getColor() + list.get(i).getNumber()+ " ");
        }
        System.out.println(" ]");
    }

}

 

//Player.java

package card;

import java.util.ArrayList;
import java.util.List;

public class Player {
    private int id;
    private String name;
    private List<Card> handCards = new ArrayList<Card>();

    public Player(int id, String name){
        this.id = id;
        this.name = name;
    }

    public List<Card> getHandCards() {
        return handCards;
    }

    public void setHandCards(Card card) {
        handCards.add(card);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

 

//CardComparator.java(自定义排序规则)

package card;

import java.util.Comparator;

public class CardComparator implements Comparator<Card> {

    @Override
    public int compare(Card c1, Card c2) {
        // 构建花色和牌值数组,经过比对,计算获得某张牌的价值(大小)
        String[] color = {"方片", "梅花", "红桃", "黑桃"};
        String[] number = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J","Q","K", "A"};

        //因为比较规则是先比较牌值,若是相等再比较花色(黑红梅方),因此将牌值赋予较高的权值
        int valueOfC1 = 0;
        int valueOfC2 = 0;
        for(int i=0;i<number.length;i++){
            if(c1.getNumber().equals(number[i])) valueOfC1 += i*10;
            if(c2.getNumber().equals(number[i])) valueOfC2 += i*10;
        }
        for(int i=0;i<color.length;i++){
            if(c1.getColor().equals(color[i])) valueOfC1 += i;
            if(c2.getColor().equals(color[i])) valueOfC2 += i;
        }

        if( valueOfC1 > valueOfC2 ) return -1;
        if( valueOfC1 < valueOfC2 ) return 1;

        return 0;
    }

}

 

//PlayDemo.java

package card;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class PlayDemo {

    //建立玩家
    //要对玩家ID的异常处理,要求用户只能输入整数ID,不然须要从新输入
    public Player setPlayer(){
        int id=0;
        String name="";
        Scanner console = new Scanner(System.in);
        boolean ready = true;
        do{
            try{
                System.out.println("输入ID:");
                id = console.nextInt();
                ready = true;
            }catch(Exception e){
                System.out.println("请输入整数类型的ID!");
                ready = false;
                console.nextLine();
            }
        }while(ready==false);

        System.out.println("输入姓名:");
        name = console.next();      
        return new Player(id, name);
    }

    public static void main(String[] args) {
        //测试简易扑克牌程序
        PlayDemo game = new PlayDemo();
        //(1)建立一副牌
        Cards cards = new Cards();
        //(2)展现新的扑克牌
        cards.showCards();
        //(3)洗牌
        cards.shufCards();
        //(4)建立玩家
        System.out.println("--------------建立两个(or多个)玩家就能够开始游戏啦!-------------");
        List<Player> p = new ArrayList<Player>();
        for(int i=0;i<2;i++)
        {
            System.out.println("请输入第"+(i+1)+"位玩家的ID和姓名:");
            p.add(game.setPlayer());
        }
        for(int i=0;i<p.size();i++)
        {
            System.out.println("欢迎玩家:"+p.get(i).getName());
        }
        //(5)扑克牌比大小游戏开始啦~
        int count = 0;
        System.out.println("------------------开始发牌---------------------");
        //设定每人分别拿两张(or多张)
        for(int i=0; i<2;i++){
            //玩家轮流拿牌
            for(int j=0; j< p.size(); j++){
                System.out.println(">玩家"+p.get(j).getName()+"拿牌");
                p.get(j).setHandCards(cards.getList().get(count));
                count++;
            }
        }
        System.out.println("------------------发牌结束!--------------------");
        System.out.println("------------------开始游戏 ---------------------");
        for(int i=0;i<p.size();i++){
            System.out.print("玩家"+p.get(i).getName()+"的手牌为:[ ");
            for(int j=0;j<p.get(i).getHandCards().size();j++){
                Card cur = p.get(i).getHandCards().get(j);
                System.out.print(cur.getColor()+cur.getNumber()+" ");
            }
            System.out.println(" ]");
        }

        //排序获得每一个玩家最大的手牌(排序规则自定义)
        for(int i=0;i<p.size();i++){
            Collections.sort(p.get(i).getHandCards(), new CardComparator());
        }
        List<Card> maxCard = new ArrayList<Card>();
        for(int i=0;i<p.size();i++){
            Card maxCur = p.get(i).getHandCards().get(0);
            System.out.println("玩家"+p.get(i).getName()+"最大的手牌为:"+ maxCur.getColor()+maxCur.getNumber());
            maxCard.add(maxCur);
        }

        //获得最后的胜者
        List<Card> temp = new ArrayList<Card>();
        temp.addAll(maxCard);
        Collections.sort(temp, new CardComparator());
        for(int i=0;i<p.size();i++){
            if(maxCard.get(i).equals(temp.get(0))) System.out.println("恭喜玩家:"+p.get(i).getName()+"获胜!"); 
        }

    }

}

 

游戏运行截图

这里写图片描述
这里写图片描述 还有一个地方须要优化,即不能输入重复的ID和姓名,能够重写Player的equals方法,将用户的输入与已有的输入相比较,不知足要求则须要从新输入,

相关文章
相关标签/搜索