2019-08-09Day10 单例设计模式,扑克牌比大小游戏(Java)

目的

学习了解单例设计模式的相关知识,并在前几天Java学习的基础上,完善所学的知识,完成扑克牌比大小的游戏,能实现的功能有,游戏显示页面,玩家信息页面(包括玩家姓名 编号 所持有的资金),生成一副扑克牌并随机发给玩家一张,玩家可选择弃牌,下注,跟注,具体功能可自己完善。

基础饿汉式单例设计模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。
优点:
类加载时就去初始化,没有线程安全问题,不能通过new创建实例
缺点:
类加载时就创建好对象,可能会创建出来用不到的实例对象,这样对内存是种浪费

代码示例

public class Text {
    public static  void main(String[] args){
        //1.正常情况下创建一个对象
      Poker.shared.text();
      

     
    }
}
class Poker{
    //default sharedInstance,manager
    //2.定义一个静态的成员变量 记录这个单例对象
    //饿汉式
    public static final Poker shared = new Poker();
    //1.默认构造函数
    private Poker(){}
    public void text(){

    }

扑克牌游戏

实现步骤

理清楚逻辑结构和大致需要的功能

结构图

封装游戏开始界面

创建一个Utils类,在里面封装所需要的输入语句。包括是否输入星号和换行

public class Utils {
    //如果不需要保存数据 没有成员变量
    //提供静态方法 访问方便
    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.print(hasStar?"**********************\n":"");
        //判断是否需要换行
        System.out.print(lineBreak?"\n":"");

    }
}

创建Poker类

Poker类用于定义牌的点数和类型

定义一个Constant类(常量类,用于保存常量 数字 花色,人数等等常数 )

public class Constant {
    //用数组保存牌的点数
    public static final String[] DOTS = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
    //保存固定的几个花色
    public static final PokerType[] TYPES = {PokerType.SPADES,PokerType.HEARTS,PokerType.CLUBS,PokerType.DIAMANDS};

    //保存默认的玩家姓名
    public static final String[] DEFAULT_NAMES = {"刘德华","周润发","张家辉","周星驰"};
    //默认的资金
    public static final int MONEY = 1000;
    //每局消耗的金币
    public  static  final  int BASE = 10;


}


}

定义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 DIAMANDS = new PokerType("■",1);
    private String pic;
    private  int id;

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

    public void setPic(String pic) {
        this.pic = pic;
    }

    public int getId() {
        return id;
    }

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

创建PokerManager类来管理牌的相关操作 发牌洗牌

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

/**
 * 管理牌的相关操作
 * 生成一副牌 洗牌 发牌 牌的比较
 */
public class PokerManager {

    //保存一副牌
    private ArrayList<Poker> pokers = new ArrayList<>();
    //创建静态的变量
    public static final PokerManager manager = new PokerManager();
    //私有化 构造方法
    private PokerManager(){

    }
    //生成一副牌
    public void deal(){
        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().getPic()+" ");

        }
        System.out.println();

    }

    /**
     * 给每个玩家发牌
     * @param players 所有参与的玩家
     */
    public void dealCards(ArrayList<Player> players){
        for(int i = 0 ; i < players.size();i++){
            Player player = players.get(i);
            //将数组里面对应的扑克牌给对应的玩家
            player.poker = pokers.get(i);
            //
        }
}

}

此时已经能将一副牌打乱后完整的发出来,接下来开始管理玩家的信息

创建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;
    }

    @Override
    //当打印一个对象的时候 就会默认去调用对象的toString方法
    //如果当前类里面没有实现这个方法 就到父类里面去查找
    //object里面默认实现就是打印对象的首地址
    public String toString() {
        //一号玩家:xxx 金币 1000

        return id+"号玩家: "+name+" 金币"+money ;
    }
    public String getPokerString(){
        String pkString = "";
        if(poker != null){
            pkString = poker.getDot() +poker.getType().getPic();
        }
        return pkString;
    }
    //下注
    public int bet(int count){
        //判断自己的金币是否大于下注金额
        if(money >= count){
            money-=count;
            return count;
        }else{
            return -1;
        }
    }
 public void add(int count){
        money += count;
 }
}

创建PlayerManager管理 玩家的相关操作

import java.util.ArrayList;

public class PlayerManager {
    //记录当前下注的玩家编号
    public int currentPlayerIndex = 0;
    //保存所有的玩家
    public  ArrayList<Player> players = new ArrayList<>();
    public static final PlayerManager manager = new PlayerManager();
    private PlayerManager(){

    }

    //初始化玩家
    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);
        }
    }
    //输出玩家的信息
    public void show(){
        for(Player player:players){
            System.out.println(player);
        }
    }
    //底注 count 每局消耗的金币  -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();
    }

    /**
     * 获取当前下注的玩家
     * @return 玩家对象
     */
    public Player currentPlayer(){

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

        }
    }
    public void awardWinner(int total){
        Player winner;
        int available = leftPlayerCount();
        if(available == 1){
            changeNext();
            winner = currentPlayer();
        }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.bigerThan(w2.poker);
            if(result == true ){
                winner = w1;
            }else{
                winner = w2;
            }
        }
        System.out.println(winner.id+"号玩家赢得"+total+"金币");
        winner.add(total);
    }
}

创建GameCenter类 管理游戏进行的相关操作

public class GameCenter {
    //记录这局的筹码
    public int totalMoney;
    public void start(){
        System.out.println("游戏开始 请下底注");

        //扣除底注
        PlayerManager.manager.betAll(Constant.BASE);
        PlayerManager.manager.show();
        //发牌
        System.out.println("开始发牌");
        PokerManager.manager.dealCards(PlayerManager.manager.players);
        PlayerManager.manager.show();
        int time = 0;//如果是两个人的次数
        boolean isFirst = true;
        int betMoney = 0;
        while(true){
            //获取当前玩家信息
            Player player = PlayerManager.manager.currentPlayer();
            //提示选择操作
            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.awardWinner(totalMoney);
    }

接口类

public class Myclass {
    public static void main(String[] args){
    //欢迎界面
        Utils.showText(true,true,new String[]{"欢迎加入游戏"});


        PokerManager.manager.deal();
        //显示一副牌
        PokerManager.manager.show();

        //输入玩家人数
        Utils.showText(false,false,new String[]{"输入玩家人数"});

        int count = Utils.getInput();
        //初始化玩家
       PlayerManager.manager.initPlayer(count);
        //显示玩家信息
        PlayerManager.manager.show();

        GameCenter center = new GameCenter();
        center.start();
  }
}

程序展示

1.png
2.png
3.png

小结

今天打的代码很多,虽然打代码能跟的上节奏,但是长时间下来很累,脑子慢慢就转不动了,今天就这样吧。

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

推荐阅读更多精彩内容