扑克牌斗牛

在实现扑克牌斗牛项目前,我们先了解什么是斗牛?

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);
    }
}

5. 游戏界面(控制台)

相关推荐
天天扭码31 分钟前
五天SpringCloud计划——DAY1之mybatis-plus的使用
java·spring cloud·mybatis
程序猿小柒36 分钟前
leetcode hot100【LeetCode 4.寻找两个正序数组的中位数】java实现
java·算法·leetcode
不爱学习的YY酱1 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
丁总学Java1 小时前
Maven项目打包,com.sun.tools.javac.processing
java·maven
kikyo哎哟喂1 小时前
Java 代理模式详解
java·开发语言·代理模式
_OLi_2 小时前
力扣 LeetCode 106. 从中序与后序遍历序列构造二叉树(Day9:二叉树)
数据结构·算法·leetcode
duration~2 小时前
SpringAOP模拟实现
java·开发语言
小码ssim2 小时前
IDEA使用tips(LTS✍)
java·ide·intellij-idea
我明天再来学Web渗透2 小时前
【SQL50】day 2
开发语言·数据结构·leetcode·面试
潜洋2 小时前
Spring Boot教程之五:在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序
java·spring boot·后端