在实现扑克牌斗牛项目前,我们先了解什么是斗牛?
1. 斗牛规则
斗牛规则:在纸牌斗牛规则里:大小王除外,52张牌,K最大,A最小,J,Q,K都是10点,然后点数依次排列最后A是1点。牌局开始每个人抓五张牌,玩家需要将手中三张牌10点的倍数,称为"牛"。其余的两张牌加起来算点数,去掉十位只留个位数来进行比较,如果剩下两张正好是10点,根据纸牌斗牛规则,这副牌就是"斗牛"。
2. Card类
由于我们Java语言是面向对象的语言,我们首先要做的就是将扑克牌抽象出一种类,让计算机可以读懂。那么我们该如何描述一个卡牌类呢??
我们发现扑克牌有点数和花色之分,我们就从这个方向来定义:
java
public String suit;//花色
public int rank;//点数
public String rankFace;//花牌
其中比较特别的有J、Q、K、A、鬼牌,那么我们应该特殊照顾
普通牌的初始化(构造方法)如下:
java
//初始化2~10的牌
public Card(String suit, int rank) {
this.suit = suit;
this.rank = rank;
}
花牌(J、Q、K、A)的初始化(构造方法)如下:
java
public Card(String suit,String rankFace,int rank) {
this.suit = suit;
this.rankFace = rankFace;
}
鬼牌(大小王)的初始化(构造方法)如下:
java
public Card(String suit) {
this.suit = suit;
}
其次我们还需要对各种花色和特殊的花牌进行定义:
java
public static String[] SUITS={"♥","♠","♦","♣"};
public static String[] RANKFACES={"J","Q","K","A"};
我们为了更好的测验我们的牌,重写了一个打印方法如下:
java
@Override
public String toString() {
if(this.suit=="BigKing"||this.suit=="SmallKing"){
return "{"+this.suit+"}";
}
if(this.rankFace=="J"||this.rankFace=="Q"||this.rankFace=="K"||this.rankFace=="A"){
return "{"+this.suit+rankFace+"}";
}
return "{"+this.suit+rank+"}";
}
完整的Card类如下:
java
package democard;
public class Card {
public String suit;//花色
public int rank;//点数
public String rankFace;//花牌
public static String[] SUITS={"♥","♠","♦","♣"};
public static String[] RANKFACES={"J","Q","K","A"};
/**
* 初始化2~10的牌
* @param suit
* @param rank
*/
public Card(String suit, int rank) {
this.suit = suit;
this.rank = rank;
}
/**
* 初始化大小王
* @param suit
*/
public Card(String suit) {
this.suit = suit;
}
/**
* 初始化花牌 J、Q、K、A
* @param suit
* @param rankFace
*/
public Card(String suit,String rankFace,int rank) {
this.suit = suit;
this.rankFace = rankFace;
}
@Override
public String toString() {
if(this.suit=="BigKing"||this.suit=="SmallKing"){
return "{"+this.suit+"}";
}
if(this.rankFace=="J"||this.rankFace=="Q"||this.rankFace=="K"||this.rankFace=="A"){
return "{"+this.suit+rankFace+"}";
}
return "{"+this.suit+rank+"}";
}
}
在完成了对扑克牌的抽象定义后,我们需要对其中的玩法进行实现,我们创建一个新的类Game
3. Game类
3.1 创建一个扑克牌
java
public List<Card> createCard(){
List<Card> cardList=new ArrayList<>();
//2~10的牌
for (int i = 0; i <Card.SUITS.length ; i++) {
for (int j = 2; j <= 10; j++) {
Card card=new Card(Card.SUITS[i],j);
cardList.add(card);
}
}
//J、Q、K的牌
for (int i = 0; i <Card.SUITS.length ; i++) {
for (int j = 0; j <Card.RANKFACES.length; j++) {
Card card=new Card(Card.SUITS[i],Card.RANKFACES[j],10);
cardList.add(card);
}
}
//A的牌
for (int i = 0; i < Card.SUITS.length; i++) {
Card card=new Card(Card.SUITS[i],Card.RANKFACES[3],1);
}
//大小王
Card cardBigKing=new Card("BigKing",10);
cardList.add(cardBigKing);
Card cardSmallKing=new Card("SmallKing",10);
cardList.add(cardSmallKing);
return cardList;
3.2 洗牌
玩牌最重要的就是让每一张牌都成为随机 的,所以此时我们要调用一个Java中提供的随机方法Random()
特别注意Random方法中的参数必须是大于0的
java
Random random=new Random();
实现的逻辑:
让Random随机找一个数,让cardList数组的下标进行随机交换,最后实现洗牌的效果
java
public List<Card> shuffleCard(List<Card> cardList){
Random random=new Random();
for (int i = 0; i < cardList.size(); i++) {
int randIndex=random.nextInt(i+1);//bound的值必须大于0
Card tmp=cardList.get(i);
cardList.set(i,cardList.get(randIndex));
cardList.set(randIndex,tmp);
}
return cardList;
}
3.3 发牌
洗完牌后,我们要将洗过的牌发给每一位玩家,并开始游戏
我们是如何实现发牌的呢??
我们一直将牌的顶部的牌进行抽取,类似与链表中的头删,我们对其进行一定次数的头删,就可以实现将牌堆中的牌发给玩家的效果
那么我们又该如何对各位玩家的牌进行管理呢??
此时,我们创建一个二维数组,里面存放每一位玩家的手牌地址,对其访问就可以找到对应玩家的牌
java
public List<List<Card>> dealCard(List<Card> cardList){
//创建一个二维数组,里面存放每一位玩家的手牌地址,实现管理所有玩家牌的效果
List<List<Card>> hand=new ArrayList<>();
//分别创建玩家一、二、三的一维数组,用于存放手牌
List<Card> hand1=new ArrayList<>();
List<Card> hand2=new ArrayList<>();
List<Card> hand3=new ArrayList<>();
//将每一位玩家的地址存储在二维数组中,实现管理效果
hand.add(hand1);
hand.add(hand2);
hand.add(hand3);
//头删,实现玩家取牌的效果
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
Card card= cardList.remove(0);
hand.get(i).add(card);
}
}
return hand;
}
3.4 展示玩家手牌
java
//将二维数组传递过来,即可实现查看玩家手牌的效果
public void display(List<List<Card>> hand){
//遍历循环打印三位玩家手牌
for (int i = 0; i <3 ; i++) {
System.out.println("第"+(i+1)+"个人的牌是:"+hand.get(i));
}
}
3.5 计算各位玩家的比赛成绩,并打印比赛结果
注意点,引用类型不能直接用于计算,我们计算点数时,只要用对象调用对象成员中的成员变量即可,
例如:调用玩家一的第一张手牌的点数hand.get(0).get(i).rank,其他玩家的牌点数计算也是如此
java
public void findCow(List<List<Card>> hand){
/**
* 玩家1
*/
int [] everyCow1=new int[5];//五张牌中任何三张牌都有可能组合成10
int point=0;
int ten=0;//是否三张牌和为10
int sumNum=0;//五张牌点数和
//计算五张牌点数和
for (int i = 0; i < 5; i++) {
sumNum=hand.get(0).get(i).rank+sumNum;
}
//找到五张牌中符合三张牌和为10的牌
for (int i = 0; i < 5; i++) {
for (int j = i+2; j < 5; j++) {
ten = hand.get(0).get(i).rank + hand.get(0).get(i+1).rank + hand.get(0).get(j).rank;
if(ten%10==0){
everyCow1[point]=sumNum-ten;
point++;
}
}
}
//找到五张牌中牛最大的
int maxCow1=0;
for (int i = 0; i < everyCow1.length; i++) {
if(everyCow1[i]>maxCow1){
maxCow1=everyCow1[i];
}
}
System.out.print(hand.get(0));
System.out.println("牛"+maxCow1);
System.out.println();
/**
* 玩家2
*/
int [] everyCow2=new int[5];//五张牌中任何三张牌都有可能组合成10
//计算五张牌点数和
for (int i = 0; i < 5; i++) {
sumNum=hand.get(1).get(i).rank+sumNum;
}
//找到五张牌中符合三张牌和为10的牌
for (int i = 0; i < 5; i++) {
for (int j = i+2; j < 5; j++) {
ten=hand.get(1).get(i).rank+ hand.get(1).get(i+1).rank+hand.get(1).get(j).rank;
if(ten%10==0){
everyCow1[point]=sumNum-ten;
point++;
}
}
}
//找到五张牌中牛最大的
int maxCow2=0;
for (int i = 0; i < everyCow1.length; i++) {
if(everyCow2[i]>maxCow2){
maxCow2=everyCow2[i];
}
}
System.out.print(hand.get(1));
System.out.println("牛"+maxCow2);
System.out.println();
/**
* 玩家3
*/
int [] everyCow3=new int[5];//五张牌中任何三张牌都有可能组合成10
//计算五张牌点数和
for (int i = 0; i < 5; i++) {
sumNum=hand.get(2).get(i).rank+sumNum;
}
//找到五张牌中符合三张牌和为10的牌
for (int i = 0; i < 5; i++) {
for (int j = i+2; j < 5; j++) {
ten=hand.get(2).get(i).rank+ hand.get(2).get(i+1).rank+hand.get(2).get(j).rank;
if(ten%10==0){
everyCow1[point]=sumNum-ten;
point++;
}
}
}
//找到五张牌中牛最大的
int maxCow3=0;
for (int i = 0; i < everyCow1.length; i++) {
if(everyCow3[i]>maxCow3){
maxCow3=everyCow2[i];
}
}
System.out.print(hand.get(2));
System.out.println("牛"+maxCow3);
System.out.println();
//结果的判断
if(maxCow1>maxCow2&&maxCow1>maxCow3){
System.out.println("玩家1获胜");
}
if(maxCow2>maxCow1&&maxCow2>maxCow3){
System.out.println("玩家1获胜");
}
if(maxCow3>maxCow1&&maxCow3>maxCow2){
System.out.println("玩家1获胜");
}
}
3.6 完整Game 类
java
package democard;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Game {
/**
* 初始化牌
* @return
*/
public List<Card> createCard(){
List<Card> cardList=new ArrayList<>();
//2~10的牌
for (int i = 0; i <Card.SUITS.length ; i++) {
for (int j = 2; j <= 10; j++) {
Card card=new Card(Card.SUITS[i],j);
cardList.add(card);
}
}
//J、Q、K的牌
for (int i = 0; i <Card.SUITS.length ; i++) {
for (int j = 0; j <Card.RANKFACES.length; j++) {
Card card=new Card(Card.SUITS[i],Card.RANKFACES[j],10);
cardList.add(card);
}
}
for (int i = 0; i < Card.SUITS.length; i++) {
Card card=new Card(Card.SUITS[i],Card.RANKFACES[3],1);
}
//大小王
Card cardBigKing=new Card("BigKing",10);
cardList.add(cardBigKing);
Card cardSmallKing=new Card("SmallKing",10);
cardList.add(cardSmallKing);
return cardList;
}
/**
* 洗牌
* @param cardList
* @return
*/
public List<Card> shuffleCard(List<Card> cardList){
Random random=new Random();
for (int i = 0; i < cardList.size(); i++) {
int randIndex=random.nextInt(i+1);//bound的值必须大于0
Card tmp=cardList.get(i);
cardList.set(i,cardList.get(randIndex));
cardList.set(randIndex,tmp);
}
return cardList;
}
/**
* 发牌
* @param cardList
* @return
*/
public List<List<Card>> dealCard(List<Card> cardList){
List<List<Card>> hand=new ArrayList<>();
List<Card> hand1=new ArrayList<>();
List<Card> hand2=new ArrayList<>();
List<Card> hand3=new ArrayList<>();
hand.add(hand1);
hand.add(hand2);
hand.add(hand3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
Card card= cardList.remove(0);
hand.get(i).add(card);
}
}
return hand;
}
/**
* 展示玩家手牌
* @param hand
*/
public void display(List<List<Card>> hand){
for (int i = 0; i <3 ; i++) {
System.out.println("第"+(i+1)+"个人的牌是:"+hand.get(i));
}
}
/**
* 计算各位玩家的比赛成绩,并打印比赛结果
* @param hand
*/
public void findCow(List<List<Card>> hand){
/**
* 玩家1
*/
int [] everyCow1=new int[5];//五张牌中任何三张牌都有可能组合成10
int point=0;
int ten=0;//是否三张牌和为10
int sumNum=0;//五张牌点数和
//计算五张牌点数和
for (int i = 0; i < 5; i++) {
sumNum=hand.get(0).get(i).rank+sumNum;
}
//找到五张牌中符合三张牌和为10的牌
for (int i = 0; i < 5; i++) {
for (int j = i+2; j < 5; j++) {
ten = hand.get(0).get(i).rank + hand.get(0).get(i+1).rank + hand.get(0).get(j).rank;
if(ten%10==0){
everyCow1[point]=sumNum-ten;
point++;
}
}
}
//找到五张牌中牛最大的
int maxCow1=0;
for (int i = 0; i < everyCow1.length; i++) {
if(everyCow1[i]>maxCow1){
maxCow1=everyCow1[i];
}
}
System.out.print(hand.get(0));
System.out.println("牛"+maxCow1);
System.out.println();
/**
* 玩家2
*/
int [] everyCow2=new int[5];//五张牌中任何三张牌都有可能组合成10
//计算五张牌点数和
for (int i = 0; i < 5; i++) {
sumNum=hand.get(1).get(i).rank+sumNum;
}
//找到五张牌中符合三张牌和为10的牌
for (int i = 0; i < 5; i++) {
for (int j = i+2; j < 5; j++) {
ten=hand.get(1).get(i).rank+ hand.get(1).get(i+1).rank+hand.get(1).get(j).rank;
if(ten%10==0){
everyCow1[point]=sumNum-ten;
point++;
}
}
}
//找到五张牌中牛最大的
int maxCow2=0;
for (int i = 0; i < everyCow1.length; i++) {
if(everyCow2[i]>maxCow2){
maxCow2=everyCow2[i];
}
}
System.out.print(hand.get(1));
System.out.println("牛"+maxCow2);
System.out.println();
/**
* 玩家3
*/
int [] everyCow3=new int[5];//五张牌中任何三张牌都有可能组合成10
//计算五张牌点数和
for (int i = 0; i < 5; i++) {
sumNum=hand.get(2).get(i).rank+sumNum;
}
//找到五张牌中符合三张牌和为10的牌
for (int i = 0; i < 5; i++) {
for (int j = i+2; j < 5; j++) {
ten=hand.get(2).get(i).rank+ hand.get(2).get(i+1).rank+hand.get(2).get(j).rank;
if(ten%10==0){
everyCow1[point]=sumNum-ten;
point++;
}
}
}
//找到五张牌中牛最大的
int maxCow3=0;
for (int i = 0; i < everyCow1.length; i++) {
if(everyCow3[i]>maxCow3){
maxCow3=everyCow2[i];
}
}
System.out.print(hand.get(2));
System.out.println("牛"+maxCow3);
System.out.println();
if(maxCow1>maxCow2&&maxCow1>maxCow3){
System.out.println("玩家1获胜");
}
if(maxCow2>maxCow1&&maxCow2>maxCow3){
System.out.println("玩家1获胜");
}
if(maxCow3>maxCow1&&maxCow3>maxCow2){
System.out.println("玩家1获胜");
}
}
}
4. Test 类
4.1 菜单打印
java
public static void menu() {
System.out.println("----------------------------------");
System.out.println("| 欢迎来到扑克牌游戏! |");
System.out.println("| 1.玩游戏 |");
System.out.println("| 2.游戏规则 |");
System.out.println("| 3.查看手牌 |");
System.out.println("| 4.比赛结果 |");
System.out.println("| 0.退出游戏 |");
System.out.println("----------------------------------");
}
4.2 菜单选择方法
java
public static void select(int choice){
//退出游戏,直接结束程序
if(choice==0){
System.out.println("退出游戏!!");
System.exit(0);
}
Game game=new Game();
switch(choice){
//初始化牌,并为每位玩家发牌
case 1:
System.out.println("初始化牌:"+game.createCard());
System.out.println("洗过的牌:"+game.shuffleCard(game.createCard()));
break;
//打印游戏规则
case 2:
System.out.println("游戏规则:");
System.out.println("三方抓牌,每人抓五张,其中三张牌和为十的倍数");
System.out.println("被认为有'牛',若没有三张牌没有凑到十的倍数,就认为没'牛'");
System.out.println("剩余两张牌个个位数为多少,就是牛几");
System.out.println("最后比谁的牛大,谁就获胜");
System.out.println("若三方都没牛,或者牛一样大,则认为平局");
break;
case 3:
game.display(game.dealCard(game.createCard()));
break;
case 4:
game.findCow(game.dealCard(game.createCard()));
break;
}
}
4.3 主方法调用
java
public static void main(String[] args) {
menu();
int choice=0;
do {
Scanner sc = new Scanner(System.in);
choice= sc.nextInt();
select(choice);
}while(choice!=0);
}
4.4 完整Test类
java
package democard;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Test {
/**
* 菜单展示
*/
public static void menu() {
System.out.println("----------------------------------");
System.out.println("| 欢迎来到扑克牌游戏! |");
System.out.println("| 1.玩游戏 |");
System.out.println("| 2.游戏规则 |");
System.out.println("| 3.查看手牌 |");
System.out.println("| 4.比赛结果 |");
System.out.println("| 0.退出游戏 |");
System.out.println("----------------------------------");
}
/**
* 菜单选择
* @param choice
*/
public static void select(int choice){
//退出游戏,直接结束程序
if(choice==0){
System.out.println("退出游戏!!");
System.exit(0);
}
Game game=new Game();
switch(choice){
//初始化牌,并为每位玩家发牌
case 1:
System.out.println("初始化牌:"+game.createCard());
System.out.println("洗过的牌:"+game.shuffleCard(game.createCard()));
break;
//打印游戏规则
case 2:
System.out.println("游戏规则:");
System.out.println("三方抓牌,每人抓五张,其中三张牌和为十的倍数");
System.out.println("被认为有'牛',若没有三张牌没有凑到十的倍数,就认为没'牛'");
System.out.println("剩余两张牌个个位数为多少,就是牛几");
System.out.println("最后比谁的牛大,谁就获胜");
System.out.println("若三方都没牛,或者牛一样大,则认为平局");
break;
case 3:
game.display(game.dealCard(game.createCard()));
break;
case 4:
game.findCow(game.dealCard(game.createCard()));
break;
}
}
public static void main(String[] args) {
menu();
int choice=0;
do {
Scanner sc = new Scanner(System.in);
choice= sc.nextInt();
select(choice);
}while(choice!=0);
}
}