Java实现扑克牌比大小 (项目分析&代码呈现)

一、项目介绍

该项目的主要功能是实现扑克牌比大小,输入参与游戏的人数,各自选择相应的操作,有看牌、弃牌、下注等等,每一回合有相应的底注,结束时得出获胜玩家,并结算各个玩家剩余的金币总数。

二、项目框架与目的

开发流程

目的:希望同学们在写项目的同时,对不同类之间的数据交互的过程中,更加深刻地掌握Java中类与对象的应用,同时去学习一个项目从无到有的实现过程,以及过程中出现的bug的调试技巧。

三、具体实现

1. 封装输出语句

输出样式:1. ********************
                  hello,Java!
                ********************
              2. hello,Java!
              3.********************
                1.Java
                2.Python
                3.Swift
               ********************

import java.util.Scanner;

/**
 *工具类
 */
public class Utils {
    //如果不需要保存数据 没有成员变量
    //提供静态方法 访问方便
/**
     * 封装输出语句
     * @param hasStar    是否需要****分割符
     * @param LineBreak   是否需要换行
     * @param contents    输出的内容
     */
    public static void showText(boolean hasStar,boolean LineBreak,String...contents){
        //判断是否需要显示分割线
        System.out.print(hasStar?"************************\n":"");//三目运算
        //判断输出的内容是一行还是多行
        if (contents.length == 1){
            System.out.print(contents[0]);

            //有分割线的时候需要换行
            System.out.print(hasStar?"\n":"");
        }else {
            //输出带编号的多行数据
            for (int i = 0;i < contents.length;i++){
                System.out.println((i+1)+". "+contents[i]);
            }
        }

        System.out.println(hasStar?"************************\n":"");//三目运算

        //判断是否需要换行
        System.out.print(LineBreak?"\n":"");
    }
}

2. 创建Poker类

  • 创建Constant类管理一些常量

public class Constant {
    //用数组来保存牌的点数
    //常量一般使用大写
    public static final String[] DOTS = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
}
  • 定义PokerType类管理牌的花色和ID号

/**
 * 管理牌的图案和比较图案的大小
 */
public class PokerType {
    public static final PokerType SPADES = new PokerType("♠",4);
    public static final PokerType HEARTS = new PokerType("♥",3);
    public static final PokerType CLUBS = new PokerType("♣",2);
    public static final PokerType DIAMONDS = new PokerType("♦",1);

    private String picture;
    private int id;

    //外部可以调用
    public PokerType(){}

    //提供一个自定义的构造方法
    //默认的构造方法就被屏蔽了
    public PokerType(String picture,int id){
        //this.setPicture(picture);
        this.picture = picture;
        this.id = id;
    }


    public String getPicture() {
        return picture;
    }

    public void setPicture(String picture) {
        this.picture = picture;
    }

    public int getId() {
        return id;
    }

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

  • 定义Poker类

import java.util.Arrays;

public class Poker {
    private String dot;
    private PokerType type;


    public Poker(){

    }

    public Poker(String dot,PokerType type){
        this.dot = dot;
        this.type = type;
    }


    //setter/getter方法
    public void setDot(String dot){
        this.dot = dot;
    }
    public String getDot(){
        return dot;
    }

    public PokerType getType() {
        return type;
    }

    public void setType(PokerType type) {
        this.type = type;
    }
}
  • 创建PokerManager类管理牌的操作

    • 生成一副牌


/**
 * 管理牌的相关操作
 * 生成一副牌 洗牌 发牌  牌的比较
 */
public class PokerManager {
    //保存一副牌
    private ArrayList<Poker> pokers = new ArrayList<Poker>();

    //创建静态变量
    public static final PokerManager manager = new PokerManager();
    //私有化构造方法
    private PokerManager(){

    }

    //定义一个方法生成一副牌
    public void generate(){
        //遍历整个数组的点数
        for (int i = 0;i < Constant.DOTS.length;i++){
            //获取对应的点数
            String dot = Constant.DOTS[i];

            //生成四种花色
            for (int j = 0;j < Constant.TYPES.length;j++){
                //创建一张牌
                Poker poker = new Poker(dot,Constant.TYPES[j]);
                //将这张牌保存起来
                pokers.add(poker);

            }
        }

        //洗牌
        Collections.shuffle(pokers);
    }
    //显示一副牌
    public void show(){
        for (Poker poker:pokers){
            System.out.print(poker.getDot()+poker.getType().getPicture()+" ");
        }
        System.out.println();
    }

    /**
     * 给每个玩家发牌
     * @param players 所有参与的玩家
     */
    public void deal(ArrayList<Player> players){
        for (int i = 0;i < players.size();i++){
            Player player = players.get(i);

            //将数组里面对应的扑克牌给对应的玩家
            player.poker = pokers.get(i);

        }
    }


}

  • 为Poker类和PokerType类提供自定义构造方法

     //提供一个自定义的构造方法
    //默认的构造方法就被屏蔽了
    public PokerType(String picture,int id){
        //this.setPicture(picture);
        this.picture = picture;
        this.id = id;
    }
  • 创建花色,在PokerType⾥面提供4个静态常量 对象

    public static final PokerType SPADES = new PokerType("♠",4);
    public static final PokerType HEARTS = new PokerType("♥",3);
    public static final PokerType CLUBS = new PokerType("♣",2);
    public static final PokerType DIAMONDS = new PokerType("♦",1);
  • 在Constant⾥面提供数组保存这4个常量

    //保存固定的几个花色
    public static final PokerType[] TYPES = {PokerType.SPADES,PokerType.HEARTS,PokerType.CLUBS,PokerType.DIAMONDS};
 
  • 实现功能

 //定义一个方法生成一副牌
    public void generate(){
        //遍历整个数组的点数
        for (int i = 0;i < Constant.DOTS.length;i++){
            //获取对应的点数
            String dot = Constant.DOTS[i];

            //生成四种花色
            for (int j = 0;j < Constant.TYPES.length;j++){
                //创建一张牌
                Poker poker = new Poker(dot,Constant.TYPES[j]);
                //将这张牌保存起来
                pokers.add(poker);

            }
        }

        //洗牌
        Collections.shuffle(pokers);
    }
  • 提供一个方法输出 这副牌 :拼接每张牌的输出格式

//显示一副牌
    public void show(){
        for (Poker poker:pokers){
            System.out.print(poker.getDot()+poker.getType().getPicture()+" ");
        }
        System.out.println();
    }
  • 使用

        // 生成一副牌
         PokerManager.manager.generate();
         //显示一副牌
        PokerManager.manager.show();
  • 创建玩家类Player


/**
 * 管理玩家的信息
 */
public class Player {
    public String name;
    public int id;
    public int money;
    public Poker poker;  //记录手上的牌
    public boolean hasDiscard;  //是否弃牌

    public Player(){

    }

    public Player(String name,int id,int money){
        this.name = name;
        this.id = id;
        this.money = money;
    }
}
  • 创建玩家管理器PlayerManager 管理玩家信息

    • Constant⾥面添加常量量 保存默认提供的姓名和 金币数

//保存默认的玩家姓名
    public static final String[] DEFAULT_NAMES = {"周润发","周星驰","梁朝伟","陈冠希","张家辉"};

    //设置默认的金币
    public static final int MONEY = 1000;

    //每局消耗的金币数 底注
    public static final int BASE = 10;
  • 初始化玩家信息

 //初始化玩家
    public void initPlayer(int count){
        for (int i = 0;i < count;i++){
            //创建一个玩家
            String name = Constant.DEFAULT_NAMES[i];
            Player player = new Player(name,i+1,Constant.MONEY);

            //保存玩家
            players.add(player);
        }
    }
  • 实现toString⽅法 ⽅便打印

 @Override
    //当打印一个对象的时候 就会默认去调用对象的toString方法
    //如果当前类里面没有实现这个方法 就会到父类里面去查找
    // Object 里面的默认实现就是打印这个对象的首地址
    public String toString(){
        String pkString = "";
        if (poker != null){
            pkString = poker.getDot()+poker.getType().getPicture();
        }
        return id+"号玩家: "+name+" 筹码"+money + " "+getPokerString();

    }
  • 输出玩家信息

//输出玩家信息
    public void show(){
        for (Player player:players){
            System.out.println(player);
        }
    }
  • 游戏中心管理游戏

    • PlayerManager和PokerManager 提供单例对象

 public static final PlayerManager manager = new PlayerManager();
    private PlayerManager(){

    }

 public static final PokerManage = new PokerManage ();
    private PokerManage (){

    }
  • PlayerManager实现打底注的方法

/**
     *打底注
     * @param count  每局消耗的金币
     * @return   -1 :失败
     *            >0: 成功
     */
    public int betAll(int count){
        for (Player player:players){
            int result = player.bet(count);
            if (result == -1){
                return -1;
            }
        }
        //返回总共下注的金额
        return count*players.size();
    }
  • Player实现下注⽅法

/**
     * 打底  &  下注
     * @param count  下注金额
     * @return  -1   失败
     *           >0   成功
     */
    public int bet(int count){
        //判断自己的金币是否大于下注金额
        if (money >= count){
            money -= count;
            return count;
        }else {
            return -1;
        }
    }
  • Gamecenter 开始游戏

public class GameCenter {
    //记录这局的筹码
    private int totalMoney;

    //开始游戏
    public void start(){
        System.out.println("游戏开始,请打底:");
        //扣除底注
        PlayerManager.manager.betAll(Constant.BASE);
        PlayerManager.manager.show();
    }
}
  • 开始发牌

    • 在Player类⾥面添加Poker对象 每个⼈有一张牌

          public Poker poker;
    • PokerManager类添加发牌⽅法

 /**
     * 给每个玩家发牌
     * @param players 所有参与的玩家
     */
    public void deal(ArrayList<Player> players){
        for (int i = 0;i < players.size();i++){
            Player player = players.get(i);

            //将数组里面对应的扑克牌给对应的玩家
            player.poker = pokers.get(i);

        }
    }

  • GameCenter的start⽅法调用发牌

        //发牌
        System.out.println("开始发牌");
        PokerManager.manager.deal(PlayerManager.manager.players);
  • 开始下注

    • 获得当前下注玩家

/**
     * 获取当前下注的玩家
     * @return  玩家对象
     */
    public Player currrentPlayer(){
        return players.get(currentPlayerIndex);
    }
  • 当前剩余的玩家

/**
     * 当前剩余玩家数
     * @return
     */
    public int leftPlayerCount(){
        int total = 0;
        for (int i = 0;i < players.size();i++){
            Player player = players.get(i);
            //没弃牌并且有钱
            if (player.hasDiscard == false && player.money > 0){
                total++;
            }
        }
        return total;
    }
  • 查找下一个下注的玩家

/**
     * 查找下一个下注的人
     */
    public void changeNext(){
        int i = currentPlayerIndex;
        if (i == players.size()-1){
            i = 0;
        }else{
            i++;
        }
        // 查找下一个可以参与的玩家
        for (;i < players.size();i++){
            Player player = players.get(i);
            if (player.hasDiscard == false && player.money > 0){
                currentPlayerIndex = i;
                return;
            }
        }
    }

  • GameCenter实现

 int time = 0;  //记录如果是两个人的次数
        boolean isFirst = true;
        int betMoney = 0;


        while (true){
            //获取当前玩家
            Player player = PlayerManager.manager.currrentPlayer();

            //提示选择操作
            System.out.println("请"+player.id+"号玩家选择操作:");
            Utils.showText(true,true,new String[]{"看牌","弃牌",isFirst?"下注":"跟注"});

            int choice = Utils.getInput();

            boolean flag = false;
            switch (choice){
                case 1:
                    //看牌
                    System.out.println(player.getPokerString());
                    flag = true;
                    break;
                case 2:
                    //弃牌
                    System.out.println(player.id+"号玩家弃牌");
                    player.hasDiscard = true;
                    break;
               default:
                   //下注
                   if (isFirst){
                       while (true) {
                           System.out.print("请输入下注金额:");
                           betMoney = Utils.getInput();

                           int result = player.bet(betMoney);
                           if (result == -1) {
                               //下注不成功
                               System.out.print("余额不足 ");
                           } else {
                               //下注成功
                               isFirst = false;
                               totalMoney += betMoney;
                               break;
                           }
                       }
                   }else{
                       //跟注
                       int result = player.bet(betMoney);
                       if (result == -1){
                           player.hasDiscard = true;
                       }else{
                           System.out.println("下注成功!");
                           totalMoney += betMoney;
                       }
                   }
                    break;
            }

            if (flag == false){
                //计算当前还有多少人参与
                int available = PlayerManager.manager.leftPlayerCount();

                if (available == 1){
                    //本局结束
                    break;
                }

                if (available == 2){
                    time++;
                    if (time == 4){
                        //两个回合结束
                        break;
                    }
                }

                //切换到下一个人
                PlayerManager.manager.changeNext();

                PlayerManager.manager.show();

            }
        }
        PlayerManager.manager.awardWinner(totalMoney);
    }
  • 奖励赢家

/**
     * 奖励赢家
     */
    public void awardWinner(int total){
        Player winner;
        int available = leftPlayerCount();
        if (available == 1){
            //只有一个玩家 这就是赢家
            changeNext();
            winner = currrentPlayer();
        }else{
            //需要比较这两个玩家的牌
            Player w1 = null;
            Player w2 = null;
            for (int i = 0;i < players.size();i++){
                Player player = players.get(i);
                if (player.hasDiscard == false){
                    if (w1 == null){
                        w1 = player;
                    }else{
                        w2 = player;
                    }
                }
            }

            boolean result = w1.poker.biggerThan(w2.poker);
            if (result){
                winner = w1;
            }else{
                winner = w2;
            }
        }

        System.out.println(winner.id+"号玩家赢得"+total+"金币");
        winner.addMOney(total);
    }

  • 两张牌的比较

 public boolean biggerThan(Poker poker){
        int mIndex = Arrays.binarySearch(Constant.DOTS,this.dot);
        int oIndex = Arrays.binarySearch(Constant.DOTS,poker.dot);

        if (mIndex != oIndex) {
            //点数不同  直接比较
            return mIndex > oIndex;
        }else{
            //点数相同 比较花色
            return this.type.getId() > poker.type.getId();
        }
    }
  • Player类实现赢钱 就加金币的方法

public void addMOney(int count){
        money += count;
    }

项目源码:

四、心得体会

  跟着写这个项目,不难发现单个知识点容易学,但是和项目结合起来要考虑的东西就很多,类与类,方法与方法等等之间的联系。自己对于代码的逻辑结构还是不够清晰,需要不断加强训练。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容