2019-08-09 Day10 單例設(shè)計(jì)模式以及撲克牌demo完善

目的

學(xué)習(xí)和了解單例設(shè)計(jì)模式票编,明白其作用和使用方法,完善Java知識(shí)基礎(chǔ)學(xué)習(xí)卵渴;深入理解數(shù)組知識(shí)慧域,學(xué)好Java基礎(chǔ)知識(shí)中最重要的一部分;經(jīng)過(guò)四天對(duì)Java基礎(chǔ)的學(xué)習(xí)浪读,已經(jīng)對(duì)Java語(yǔ)言有一定了解昔榴,今天便做一個(gè)最基本的撲克牌demo,來(lái)將各類知識(shí)串聯(lián)起來(lái)

單例設(shè)計(jì)模式

概念

java中單例模式是一種常見(jiàn)的設(shè)計(jì)模式碘橘,單例模式分三種:懶漢式單例互订、餓漢式單例、登記式單例三種痘拆;單例模式有以下特點(diǎn): 1仰禽、單例類只能有一個(gè)實(shí)例; 2、單例類必須自己自己創(chuàng)建自己的唯一實(shí)例吐葵;3规揪、單例類必須給所有其他對(duì)象提供這一實(shí)例;
單例模式確保某個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例;在計(jì)算機(jī)系統(tǒng)中温峭,線程池猛铅、緩存、日志對(duì)象凤藏、對(duì)話框奸忽、打印機(jī)、顯卡的驅(qū)動(dòng)程序?qū)ο蟪1辉O(shè)計(jì)成單例;這些應(yīng)用都或多或少具有資源管理器的功能;每臺(tái)計(jì)算機(jī)可以有若干個(gè)打印機(jī)揖庄,但只能有一個(gè)Printer Spooler栗菜,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)中;每臺(tái)計(jì)算機(jī)可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口抠艾,以避免一個(gè)通信端口同時(shí)被兩個(gè)請(qǐng)求同時(shí)調(diào)用;總之苛萎,選擇單例模式就是為了避免不一致?tīng)顟B(tài),避免政出多頭

關(guān)鍵詞
1.整個(gè)程序都操作同一個(gè)對(duì)象
2.不允許用戶創(chuàng)建這個(gè)類的一個(gè)對(duì)象检号,而將類的構(gòu)造方法私有化
3.在自己的類里面提供創(chuàng)建對(duì)象的方法

兩種形式

餓漢式

class Poker{
    //default sharedInstance manager
    //2.定義一個(gè)靜態(tài)的成員變量  記錄這個(gè)單例對(duì)象
    //餓漢式
    public static final Poker sharedInstance = new Poker();

    //1.默認(rèn)構(gòu)造函數(shù)
    private Poker(){

    }

    public void test(){

    }
}

懶漢式

class Player{
    public int count;

    //2.創(chuàng)建靜態(tài)變量
    private static Player shared = null;

    //1.私有化構(gòu)造方法
    private Player(){}

    //3.提供給外部一個(gè)訪問(wèn)的方法
    //懶漢式
    public static Player getInstance(){
        Object b = new Object();
        synchronized (b) {
            if (shared == null) {
                //如果沒(méi)有創(chuàng)建 那么就創(chuàng)建一個(gè)
                shared = new Player();
            }
        }

        return shared;
    }
}

數(shù)組

Java數(shù)組里面保存的都是對(duì)象的引用(指針)腌歉;改變數(shù)組里面對(duì)象的屬性變量,原始對(duì)象的值也跟著改變齐苛,因?yàn)榇蠹叶际峭粋€(gè)內(nèi)存空間

class Test2{
    public static void main(String[] args){
        //泛型
        ArrayList<Person> people = new ArrayList<>();

        //獲取數(shù)組元素個(gè)數(shù)
        people.size();

        //添加數(shù)據(jù)
        Person xw = new Person();
        people.add(xw);

        Person zs = new Person();
        people.add(zs);

        //訪問(wèn)數(shù)據(jù)
        Person xw2 = people.get(0);
        xw2.name = "小王";

        System.out.println(xw2.name);
        System.out.println(xw.name);
    }
}

class Person{
    public String name;
}

情況演示

1.png

撲克牌游戲

設(shè)計(jì)游戲大致思路

2.png

封裝輸出語(yǔ)句

創(chuàng)建一個(gè)Untils類翘盖,專門封裝輸出語(yǔ)句

public class Utils {
    //如果不需要保存數(shù)據(jù) 沒(méi)有成員變量
    //提供靜態(tài)方法 訪問(wèn)方便
    public static void showText(boolean hasStar, boolean lineBreak, String... contents) {
        //判斷是否需要顯示分割線
        System.out.print(hasStar ? "*********************\n" : "");

        //判斷輸出的內(nèi)容是多行還是一行
        if (contents.length == 1) {
            //有分隔線的時(shí)候需要換行
            System.out.print(contents[0] + (hasStar ? "\n" : ""));
        } else {
            //輸出帶編號(hào)的多行數(shù)據(jù)
            //1. 棄牌
            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" : "");

    }
}

調(diào)用這個(gè)類創(chuàng)建歡迎界面

public class MyClass {
    public static void main(String[] args){
        //歡迎界面
        Utils.showText(true,true,new String[]{"歡迎使用撲克游戲"});
       }
}

創(chuàng)建Poker

創(chuàng)建Constant類,管理常量

下面代碼為已完成狀態(tài)

public class Constant {
    //用數(shù)組保存牌的點(diǎn)數(shù)
    public static final String[] dots = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};

    //保存固定的幾個(gè)花色 黑紅梅方
    public static final PokerType[] TYPES = {PokerType.SPADES,PokerType.HEARTS,PokerType.CLUBS,PokerType.DIAMONDS};

    //保存默認(rèn)的玩家姓名
    public static final String[] DEFAULT_NAMES = {"劉德華","周潤(rùn)發(fā)","張家輝","周星馳"};

    //設(shè)置默認(rèn)的金幣
    public static final int MONEY = 1000;

    //底注
    public static final int BASE = 10;
}

定義PokerType類 管理牌的花色和id號(hào)

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 pic;
    private int id;

    public PokerType(){}

    //提供一個(gè)自定義的構(gòu)造方法
    //默認(rèn)的構(gòu)造方法就被屏蔽了
    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;
    }

}

創(chuàng)建PokerManager類 來(lái)管理牌的相關(guān)操作 比如發(fā)牌洗牌

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

/**
 * 管理牌的相關(guān)操作
 * 生成一副牌 洗牌 發(fā)牌 牌的比較
 */
public class PokerManager {
    //保存一副牌
    private ArrayList<Poker> pokers = new ArrayList<>();

    //創(chuàng)建靜態(tài)對(duì)象
    public static final PokerManager manager = new PokerManager();

    //私有化過(guò)程方法
    private PokerManager(){}

    //定義一個(gè)方法 生成一副牌
    public void deal(){
        //遍歷整個(gè)點(diǎn)數(shù)的數(shù)組
        for (int i = 0; i  < Constant.dots.length; i++){
            //獲取相應(yīng)的點(diǎn)數(shù)
            String dot = Constant.dots[i];

            //生成四種花色
            for (int j = 0; j < Constant.TYPES.length; j++){
                //創(chuàng)建一張牌
                Poker poker = new Poker(dot, Constant.TYPES[j]);
                //將這張牌保存起來(lái)
                pokers.add(poker);
            }
        }
        //洗牌
        Collections.shuffle(pokers);
    }
    public void show() {
        for (Poker poker : pokers) {
            System.out.print(poker.getDot() + poker.getType().getPic() + " ");
        }
        System.out.println();
    }

    /**
     * 給每個(gè)玩家發(fā)牌
     * @param players 所有參與玩家
     */
    public void dealCards(ArrayList<Player> players){
        for (int i = 0; i < players.size(); i++){
            Player player = players.get(i);

            //將數(shù)組里面對(duì)應(yīng)的撲克給對(duì)應(yīng)的玩家
            player.poker = pokers.get(i);
        }
    }

}

創(chuàng)建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
    //當(dāng)打印一個(gè)對(duì)象的時(shí)候 就會(huì)默認(rèn)去調(diào)用對(duì)象的toString方法
    //如果當(dāng)前類里面沒(méi)有實(shí)現(xiàn)這個(gè)方法 就到父類里面去找
    //object里面默認(rèn)實(shí)現(xiàn)就是打印對(duì)象的首地址
    public String toString(){
        //1號(hào)玩家:劉德華 金幣1000
        return id+"號(hào)玩家:"+name+" 金幣"+money+" "+getPokerString();
    }

    public String getPokerString(){
        String pkString = "";
        if (poker != null){
            pkString = poker.getDot() + poker.getType().getPic();
        }
        return pkString;
    }

    /**
     * 下底注&下注
     * @param count 下注金額
     * @return -1:失敗  >0: 成功
     */
    public int bet(int count){
        //判斷自己的金幣是否大于下注金額
        if (money >= count){
            money -= count;

            return count;
        }else{
            return -1;
        }
    }
    public void add(int count){
        money += count;
 }
}

創(chuàng)建PlayerManager類 管理玩家的相關(guān)操作

import java.util.ArrayList;

public class PlayManager {
    //記錄當(dāng)前下注的玩家編號(hào)
    public int currentPlayerIndex = 0;

    //保存所有的玩家
    public ArrayList<Player> players = new ArrayList<>();

    public static final PlayManager manager = new PlayManager();

    private PlayManager(){}

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

            //保存玩家
            players.add(player);
        }
    }

    //輸出玩家信息
    public void shows(){
        for (Player player:players){
            System.out.println(player);
        }
    }

    /**
     * 全場(chǎng)下底注
     * @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();
    }

    /**
     * 獲取當(dāng)前下注玩家
     * @return 玩家對(duì)象
     */
    public  Player currentPlayer(){
        return players.get(currentPlayerIndex);
    }

    /**
     * 當(dāng)前剩余玩家數(shù)
     * @return
     */
    public int leftPlayerCount(){
        int total = 0;
        for (int i = 0; i < players.size(); i++){
            Player player = players.get(i);
            if (player.hasDiscard == true && player.money > 0){
                total++;
            }
        }
        return total;
    }

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

    /**
     * 獎(jiǎng)勵(lì)贏家
     */
    public void awardWinner(int total){
        Player winner ;
        int available = leftPlayerCount();
        if (available == 1){
            //只有一個(gè)玩家 即為贏家
            changeNext();
            winner = currentPlayer();
        }else{
            //需要比較這兩個(gè)玩家的牌
            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.bigerThen(w2.poker);
            if (result){
                winner = w1;
            }else {
                winner = w2;
            }
        }
        System.out.println(winner.id+"號(hào)玩家勝利 獲取"+total+"金幣");
        winner.add(total);
    }
}

創(chuàng)建GameCenter類 管理游戲進(jìn)行的相關(guān)操作

public class GameCenter {
    //記錄這局的籌碼
    private int totalMoney;

    //開(kāi)始游戲
    public void start(){
        System.out.println("游戲開(kāi)始 請(qǐng)下底注");
        PlayManager manager = PlayManager.manager;
        //扣除底注
        manager.betAll(Constant.BASE);

        manager.shows();

        //發(fā)牌
        System.out.println("開(kāi)始發(fā)牌");
        PokerManager.manager.dealCards(manager.players);

        manager.shows();

        int time = 0;//記錄如果是兩個(gè)人的次數(shù)
        boolean isFirst = true;
        int betMoney = 0;
        while (true){
            //獲取當(dāng)前玩家信息
            Player player = manager.currentPlayer();

            //提示選擇操作
            System.out.println("請(qǐng)"+player.id+"號(hào)玩家選擇操作;");

            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+"號(hào)玩家棄牌");
                    player.hasDiscard = true;
                    break;
                default:
                    //下注
                    if (isFirst){
                        while (true) {
                            System.out.print("請(qǐng)輸入下注金額:");
                            betMoney = Utils.getInput();

                            int result = player.bet(betMoney);
                            if (result == -1) {
                                //下注不成功
                                System.out.println("余額不足 ");
                            }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){
                //計(jì)算當(dāng)前還有多少人可以參與
                int available = manager.leftPlayerCount();

                if (available > 1){
                    //本劇結(jié)束
                    manager.changeNext();
                    Player winner = manager.currentPlayer();
                    System.out.println(player.id+"號(hào)玩家獲得勝利 獲得金幣:"+totalMoney);
                    break;
                }

                if (available == 2){
                    time++;
                    if (time == 4){
                        //兩個(gè)回合結(jié)束 結(jié)束游戲
                        break;
                    }
                }

                //切換到下一個(gè)人
                manager.changeNext();

            }
        }
    }

整體邏輯

public class MyClass {
    public static void main(String[] args){
        //歡迎界面
        Utils.showText(true,true,new String[]{"歡迎使用撲克游戲"});

        //生成一副牌
        PokerManager.manager.deal();
        //顯示一副牌
        PokerManager.manager.show();

        //顯示玩家人數(shù)
        Utils.showText(false,false,new String[]{"請(qǐng)輸入玩家人數(shù):"});
        int count = Utils.getInput();

        //初始化玩家
        PlayManager.manager.initPlayer(count);
        //顯示玩家信息
        //PlayManager.manager.shows();

        //開(kāi)始游戲
        GameCenter center = new GameCenter();
        center.start();
    }
}

心得體會(huì)

今天是正式地學(xué)習(xí)第一個(gè)完整的demo凹蜂,其中還有很多不懂的馍驯,需要不斷看視頻和學(xué)習(xí),才能將她摸透

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玛痊,一起剝皮案震驚了整個(gè)濱河市汰瘫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌擂煞,老刑警劉巖混弥,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異对省,居然都是意外死亡蝗拿,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門蒿涎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)哀托,“玉大人,你說(shuō)我怎么就攤上這事劳秋〔质郑” “怎么了胖齐?”我有些...
    開(kāi)封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)俗或。 經(jīng)常有香客問(wèn)我市怎,道長(zhǎng),這世上最難降的妖魔是什么辛慰? 我笑而不...
    開(kāi)封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任区匠,我火速辦了婚禮,結(jié)果婚禮上帅腌,老公的妹妹穿的比我還像新娘驰弄。我一直安慰自己,他們只是感情好速客,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布戚篙。 她就那樣靜靜地躺著,像睡著了一般溺职。 火紅的嫁衣襯著肌膚如雪岔擂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天浪耘,我揣著相機(jī)與錄音乱灵,去河邊找鬼。 笑死七冲,一個(gè)胖子當(dāng)著我的面吹牛痛倚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播澜躺,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蝉稳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了掘鄙?” 一聲冷哼從身側(cè)響起耘戚,我...
    開(kāi)封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎操漠,沒(méi)想到半個(gè)月后毕莱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颅夺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛹稍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吧黄。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖唆姐,靈堂內(nèi)的尸體忽然破棺而出拗慨,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布赵抢,位于F島的核電站剧蹂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏烦却。R本人自食惡果不足惜宠叼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望其爵。 院中可真熱鬧冒冬,春花似錦、人聲如沸摩渺。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)摇幻。三九已至横侦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绰姻,已是汗流浹背枉侧。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留龙宏,地道東北人棵逊。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像银酗,于是被迫代替她去往敵國(guó)和親辆影。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容