Java實(shí)現(xiàn)撲克牌比大小 (項(xiàng)目分析&代碼呈現(xiàn))

一溅呢、項(xiàng)目介紹

該項(xiàng)目的主要功能是實(shí)現(xiàn)撲克牌比大小澡屡,輸入?yún)⑴c游戲的人數(shù)猿挚,各自選擇相應(yīng)的操作,有看牌驶鹉、棄牌绩蜻、下注等等,每一回合有相應(yīng)的底注室埋,結(jié)束時(shí)得出獲勝玩家办绝,并結(jié)算各個(gè)玩家剩余的金幣總數(shù)。

二姚淆、項(xiàng)目框架與目的

開發(fā)流程

目的:希望同學(xué)們?cè)趯戫?xiàng)目的同時(shí)孕蝉,對(duì)不同類之間的數(shù)據(jù)交互的過(guò)程中,更加深刻地掌握J(rèn)ava中類與對(duì)象的應(yīng)用肉盹,同時(shí)去學(xué)習(xí)一個(gè)項(xiàng)目從無(wú)到有的實(shí)現(xiàn)過(guò)程昔驱,以及過(guò)程中出現(xiàn)的bug的調(diào)試技巧。

三上忍、具體實(shí)現(xiàn)

1. 封裝輸出語(yǔ)句

輸出樣式:1. ********************
? ? ? ? ? ? ? ? ? hello,Java!
? ? ? ? ? ? ? ? ********************
? ? ? ? ? ? ? 2. hello,Java!
? ? ? ? ? ? ? 3.********************
? ? ? ? ? ? ? ??1.Java
? ? ? ? ? ? ? ??2.Python
? ? ? ? ? ? ? ??3.Swift
? ? ? ? ? ? ? ?********************

import java.util.Scanner;

/**
 *工具類
 */
public class Utils {
    //如果不需要保存數(shù)據(jù) 沒(méi)有成員變量
    //提供靜態(tài)方法 訪問(wèn)方便
/**
     * 封裝輸出語(yǔ)句
     * @param hasStar    是否需要****分割符
     * @param LineBreak   是否需要換行
     * @param contents    輸出的內(nèi)容
     */
    public static void showText(boolean hasStar,boolean LineBreak,String...contents){
        //判斷是否需要顯示分割線
        System.out.print(hasStar?"************************\n":"");//三目運(yùn)算
        //判斷輸出的內(nèi)容是一行還是多行
        if (contents.length == 1){
            System.out.print(contents[0]);

            //有分割線的時(shí)候需要換行
            System.out.print(hasStar?"\n":"");
        }else {
            //輸出帶編號(hào)的多行數(shù)據(jù)
            for (int i = 0;i < contents.length;i++){
                System.out.println((i+1)+". "+contents[i]);
            }
        }

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

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

2. 創(chuàng)建Poker類

  • 創(chuàng)建Constant類管理一些常量

public class Constant {
    //用數(shù)組來(lái)保存牌的點(diǎn)數(shù)
    //常量一般使用大寫
    public static final String[] DOTS = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
}
  • 定義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 picture;
    private int id;

    //外部可以調(diào)用
    public PokerType(){}

    //提供一個(gè)自定義的構(gòu)造方法
    //默認(rèn)的構(gòu)造方法就被屏蔽了
    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;
    }
}
  • 創(chuàng)建PokerManager類管理牌的操作

    • 生成一副牌


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

    //創(chuàng)建靜態(tài)變量
    public static final PokerManager manager = new PokerManager();
    //私有化構(gòu)造方法
    private PokerManager(){

    }

    //定義一個(gè)方法生成一副牌
    public void generate(){
        //遍歷整個(gè)數(shù)組的點(diǎn)數(shù)
        for (int i = 0;i < Constant.DOTS.length;i++){
            //獲取對(duì)應(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().getPicture()+" ");
        }
        System.out.println();
    }

    /**
     * 給每個(gè)玩家發(fā)牌
     * @param players 所有參與的玩家
     */
    public void deal(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);

        }
    }


}

  • 為Poker類和PokerType類提供自定義構(gòu)造方法

     //提供一個(gè)自定義的構(gòu)造方法
    //默認(rèn)的構(gòu)造方法就被屏蔽了
    public PokerType(String picture,int id){
        //this.setPicture(picture);
        this.picture = picture;
        this.id = id;
    }
  • 創(chuàng)建花色,在PokerType?面提供4個(gè)靜態(tài)常量 對(duì)象

    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?面提供數(shù)組保存這4個(gè)常量

    //保存固定的幾個(gè)花色
    public static final PokerType[] TYPES = {PokerType.SPADES,PokerType.HEARTS,PokerType.CLUBS,PokerType.DIAMONDS};
 
  • 實(shí)現(xiàn)功能

 //定義一個(gè)方法生成一副牌
    public void generate(){
        //遍歷整個(gè)數(shù)組的點(diǎn)數(shù)
        for (int i = 0;i < Constant.DOTS.length;i++){
            //獲取對(duì)應(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);
    }
  • 提供一個(gè)方法輸出 這副牌 :拼接每張牌的輸出格式

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

        // 生成一副牌
         PokerManager.manager.generate();
         //顯示一副牌
        PokerManager.manager.show();
  • 創(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;
    }
}
  • 創(chuàng)建玩家管理?PlayerManager 管理玩家信息

    • Constant?面添加常量量 保存默認(rèn)提供的姓名和 金幣數(shù)

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

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

    //每局消耗的金幣數(shù) 底注
    public static final int BASE = 10;
  • 初始化玩家信息

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

            //保存玩家
            players.add(player);
        }
    }
  • 實(shí)現(xiàn)toString?法 ?便打印

 @Override
    //當(dāng)打印一個(gè)對(duì)象的時(shí)候 就會(huì)默認(rèn)去調(diào)用對(duì)象的toString方法
    //如果當(dāng)前類里面沒(méi)有實(shí)現(xiàn)這個(gè)方法 就會(huì)到父類里面去查找
    // Object 里面的默認(rèn)實(shí)現(xiàn)就是打印這個(gè)對(duì)象的首地址
    public String toString(){
        String pkString = "";
        if (poker != null){
            pkString = poker.getDot()+poker.getType().getPicture();
        }
        return id+"號(hào)玩家: "+name+" 籌碼"+money + " "+getPokerString();

    }
  • 輸出玩家信息

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

    • PlayerManager和PokerManager 提供單例對(duì)象

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

    }

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

    }
  • PlayerManager實(shí)現(xiàn)打底注的方法

/**
     *打底注
     * @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實(shí)現(xiàn)下注?法

/**
     * 打底  &  下注
     * @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("游戲開始,請(qǐng)打底:");
        //扣除底注
        PlayerManager.manager.betAll(Constant.BASE);
        PlayerManager.manager.show();
    }
}
  • 開始發(fā)牌

    • 在Player類?面添加Poker對(duì)象 每個(gè)?有一張牌

    ? ? ? public Poker poker;
    • PokerManager類添加發(fā)牌?法

 /**
     * 給每個(gè)玩家發(fā)牌
     * @param players 所有參與的玩家
     */
    public void deal(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);

        }
    }

  • GameCenter的start?法調(diào)用發(fā)牌

        //發(fā)牌
        System.out.println("開始發(fā)牌");
        PokerManager.manager.deal(PlayerManager.manager.players);
  • 開始下注

    • 獲得當(dāng)前下注玩家

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

/**
     * 當(dāng)前剩余玩家數(shù)
     * @return
     */
    public int leftPlayerCount(){
        int total = 0;
        for (int i = 0;i < players.size();i++){
            Player player = players.get(i);
            //沒(méi)棄牌并且有錢
            if (player.hasDiscard == false && player.money > 0){
                total++;
            }
        }
        return total;
    }
  • 查找下一個(gè)下注的玩家

/**
     * 查找下一個(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 == false && player.money > 0){
                currentPlayerIndex = i;
                return;
            }
        }
    }

  • GameCenter實(shí)現(xiàn)

 int time = 0;  //記錄如果是兩個(gè)人的次數(shù)
        boolean isFirst = true;
        int betMoney = 0;


        while (true){
            //獲取當(dāng)前玩家
            Player player = PlayerManager.manager.currrentPlayer();

            //提示選擇操作
            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.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){
                //計(jì)算當(dāng)前還有多少人參與
                int available = PlayerManager.manager.leftPlayerCount();

                if (available == 1){
                    //本局結(jié)束
                    break;
                }

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

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

                PlayerManager.manager.show();

            }
        }
        PlayerManager.manager.awardWinner(totalMoney);
    }
  • 獎(jiǎng)勵(lì)贏家

/**
     * 獎(jiǎng)勵(lì)贏家
     */
    public void awardWinner(int total){
        Player winner;
        int available = leftPlayerCount();
        if (available == 1){
            //只有一個(gè)玩家 這就是贏家
            changeNext();
            winner = currrentPlayer();
        }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.biggerThan(w2.poker);
            if (result){
                winner = w1;
            }else{
                winner = w2;
            }
        }

        System.out.println(winner.id+"號(hào)玩家贏得"+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) {
            //點(diǎn)數(shù)不同  直接比較
            return mIndex > oIndex;
        }else{
            //點(diǎn)數(shù)相同 比較花色
            return this.type.getId() > poker.type.getId();
        }
    }
  • Player類實(shí)現(xiàn)贏錢 就加金幣的方法

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

項(xiàng)目源碼:

四纳本、心得體會(huì)

??跟著寫這個(gè)項(xiàng)目窍蓝,不難發(fā)現(xiàn)單個(gè)知識(shí)點(diǎn)容易學(xué),但是和項(xiàng)目結(jié)合起來(lái)要考慮的東西就很多繁成,類與類吓笙,方法與方法等等之間的聯(lián)系。自己對(duì)于代碼的邏輯結(jié)構(gòu)還是不夠清晰巾腕,需要不斷加強(qiáng)訓(xùn)練面睛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市尊搬,隨后出現(xiàn)的幾起案子叁鉴,更是在濱河造成了極大的恐慌,老刑警劉巖佛寿,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幌墓,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡冀泻,警方通過(guò)查閱死者的電腦和手機(jī)常侣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弹渔,“玉大人胳施,你說(shuō)我怎么就攤上這事≈ǎ” “怎么了舞肆?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵您没,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我胆绊,道長(zhǎng)氨鹏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任压状,我火速辦了婚禮仆抵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘种冬。我一直安慰自己镣丑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布娱两。 她就那樣靜靜地躺著莺匠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪十兢。 梳的紋絲不亂的頭發(fā)上趣竣,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音旱物,去河邊找鬼遥缕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宵呛,可吹牛的內(nèi)容都是我干的单匣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼宝穗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼户秤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起逮矛,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸡号,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后橱鹏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膜蠢,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年莉兰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了挑围。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡糖荒,死狀恐怖杉辙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捶朵,我是刑警寧澤蜘矢,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布狂男,位于F島的核電站,受9級(jí)特大地震影響品腹,放射性物質(zhì)發(fā)生泄漏岖食。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一舞吭、第九天 我趴在偏房一處隱蔽的房頂上張望泡垃。 院中可真熱鬧,春花似錦羡鸥、人聲如沸蔑穴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)存和。三九已至,卻和暖如春衷旅,著一層夾襖步出監(jiān)牢的瞬間捐腿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工芜茵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叙量,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓九串,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親寺鸥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猪钮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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