查看完整版本: 樸克牌之黑傑克
頁: [1]

csihcs 發表於 2009-6-6 08:48 PM

樸克牌之黑傑克


package poker;
public class Card {
    // 定義牌面數字
    public enum Rank {ACE(1), 二(2), 三(3), 四(4), 五(5), 六(6), 七(7), 八(8), 九(9), 十(10), JACK(11), QUEEN(12), KING(13);
        public final int num;
        private Rank(int num) {
            this.num = num;
        }
    }
    // 定義牌面花色
    public enum Suit { 梅花, 方塊, 紅心, 黑桃 }
    private final Rank rank;
    private final Suit suit;
    protected Card(Rank rank, Suit suit) {
        this.rank = rank;
        this.suit = suit;
    }
    public int getNum() { return rank.num; }
    public Rank rank() { return rank; }
    public Suit suit() { return suit; }
    public String toString() {
        return suit + " " + rank;
    }
}


package poker;
import java.util.*;
public class Deck {
    private static final List<Card> protoDeck = new ArrayList<Card>();
    private List<Card> currentDeck;
    private int size;
    public Deck() {
        reflash();
    }
    // 抽出一張牌
    public Card getNext() {
        Card c = currentDeck.get((int)(Math.random()*size));
        currentDeck.remove(c);
        size--;
        return c;
    }
    // 補滿所有的牌
    public void reflash() {
        currentDeck = newDeck();
        size = currentDeck.size();
    }

    // 建立樸克牌模型
    static {
        for (Card.Suit suit : Card.Suit.values())
            for (Card.Rank rank : Card.Rank.values())
                protoDeck.add(new Card(rank, suit));
    }
    // 建立新的一副樸克牌
    private static ArrayList<Card> newDeck() {
        return new ArrayList<Card>(protoDeck);
    }
}


package poker.game;
import poker.*;
import java.util.*;
import javax.swing.JOptionPane;  //引入JOptionPane類別
class BlackJack {
    private Deck deck = new Deck();
    private HandCards[] players;
    private int winnerPoint;
    private int numPlayers;
    public BlackJack(int numPlayers) throws IllegalArgumentException {
        if(numPlayers < 1) {
            throw new IllegalArgumentException("numPlayers 小於 1.");
        }
        this.numPlayers = numPlayers;
        players = new HandCards;
        String name;
        int input;
        // 輸入名字建立玩家,詢問是否為電腦玩家
        for(int i = 0 ; i < numPlayers ; i++) {
            name = JOptionPane.showInputDialog("請輸入名字:");
            if(name.equals("")) {
                name = "Player " + (i+1);
            }
            input = JOptionPane.showConfirmDialog(null,name + " 是一個電腦玩家嗎??","詢問",JOptionPane.YES_NO_OPTION);
            players = new HandCards(name,input == JOptionPane.YES_OPTION);
        }
    }
    // 初始化牌堆與手牌
    public void reflash() {
        deck.reflash();
        winnerPoint = 0;
        for(int i = 0 ; i < numPlayers ; i++) {
            players.clear();
        }
    }
    // 開始進行遊戲
    public void startGame() {
        reflash();
        int point;
        for(int i = 0 ; i < players.length ; i++) {
            point = players.getFromDeck();
            System.out.println(players.listCards() + "\t" + point);
            if(point < 22) {
                winnerPoint = Math.max(winnerPoint,point);
            }
        }
        System.out.println(showWinner());
    }
    // return 勝利者名字
    public String showWinner() {
        StringBuilder sb = new StringBuilder("\n  Winner :\n");
        for(int i = 0 ; i < players.length ; i++) {
            if(winnerPoint == players.getHandCardNum()) {
                sb.append(players.getName()+"\n");
            }
        }
        return sb.toString();
    }
    // 手牌類別
    public class HandCards {
        private ArrayList<Card> handCards = new ArrayList<Card>();
        private boolean hasAce = false,isStart = false;
        private int num = 0;
        private final String name;
        private final boolean isAI;
        private HandCards(String name,boolean ai) {
            this.name = name;
            this.isAI = ai;
        }
        public String getName() {
            return name;
        }
        // 清空手牌
        private void clear() {
            handCards.clear();
            hasAce = false;
            num = 0;
            isStart = false;
        }
        // return 現在持有的牌
        public String listCards() {
            Card[] cards = new Card;
            handCards.toArray(cards);
            StringBuilder sb = new StringBuilder(name+":\n");
            for(int i = 0 ; i < cards.length ; i++)
                sb.append("\t"+cards+"\n");
            return sb.toString();
        }
        // return 現在持有的牌之數字和
        public int getHandCardNum() {
            return num + (num < 12 && hasAce ? 10 : 0);
        }

        // 由 ai 判定是否取牌
        private void aiGetFromDeck() {
            while(this.getHandCardNum() < 17) {
                getFromDeck(1);
            }
        }
        // 由 使用者 判定是否取牌
        private void userGetFromDeck() {
            int input;
            boolean canGetNext;
            do {
                input = JOptionPane.showConfirmDialog(null,this.listCards() + this.getHandCardNum() + "\n還要一張嗎?","詢問",JOptionPane.YES_NO_OPTION);
                if(input == JOptionPane.YES_OPTION) {
                    canGetNext = this.getFromDeck(1);
                } else {
                    canGetNext = false;
                }
            } while(canGetNext && input == JOptionPane.YES_OPTION);
        }
        // 只有在從未取過牌時能夠取牌,根據是否為 ai 決定由誰取牌
        public synchronized int getFromDeck() {
            if(!isStart) {
                isStart = true;
                getFromDeck(2);
                if(isAI)
                    aiGetFromDeck();
                else
                    userGetFromDeck();
            }
            return getHandCardNum();
        }
        // 取 size 量的牌,若牌堆沒牌了就不取了,若取牌前中後數字和就不能再取了
        private synchronized boolean getFromDeck(int size) {
            Card c;
            int n;
            if(num > 21) {
                return false;
            }
            for(int i = 0 ; i < size ; i++) {
                c = deck.getNext();
                if(c == null) {
                    return false;
                }
                handCards.add(c);
                n = c.getNum();
                num += (n > 9 ? 10 : n);
                if(n == 1) {
                    hasAce = true;
                }
                if(num > 21) {
                    return false;
                }
            }
            if(num > 21) {
                return false;
            }
            return true;
        }
    }
}


package poker.game;
import javax.swing.JOptionPane;  //引入JOptionPane類別
public class BlackJackLoader {
    public static void main(String [] argv) {
        BlackJack bj = null;
        int input = 0;
        String str;
        // 取得玩家人數
        do {
            str = JOptionPane.showInputDialog("請輸入玩家人數:");
            try {
                input = Integer.parseInt(str) ;
            } catch(NumberFormatException e) {}
            if(input > 0) {
                bj = new BlackJack(input);
                break;
            }
        } while(input < 1);
        // 開始進行遊戲,結束後詢問是否再玩一次
        do {
            bj.startGame();
            input = JOptionPane.showConfirmDialog(null,"還要再來一場嗎?","詢問",JOptionPane.YES_NO_OPTION);
        } while (input == JOptionPane.YES_OPTION);
    }
}
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><div></div>

csihcs 發表於 2009-6-7 12:00 AM


package poker;
import java.util.*;
public class Deck {
    private static final List<Card> 牌堆模型 = new ArrayList<Card>();
    private List<Card> 現有的牌;
    private int 數量;
    public Deck() {
        洗牌();
    }
    // 抽出一張牌
    public Card 抽出一張牌() {
        Card c = 現有的牌.get((int)(Math.random()*數量));
        現有的牌.remove(c);
        數量--;
        return c;
    }
    // 補滿所有的牌
    public void 洗牌() {
        現有的牌 = 新牌堆();
        數量 = 現有的牌.size();
    }

    // 建立樸克牌模型
    static {
        for (Card.Suit suit : Card.Suit.values())
            for (Card.Rank rank : Card.Rank.values())
                牌堆模型.add(new Card(rank, suit));
    }
    // 用牌堆模型建立新的一副牌堆
    private static ArrayList<Card> 新牌堆() {
        return new ArrayList<Card>(牌堆模型);
    }
}

package poker.game;
import poker.*;
import java.util.*;
import javax.swing.JOptionPane;  //引入JOptionPane類別
class BlackJack {
        private Deck 牌堆 = new Deck();
        private 手 莊家;
        private int 莊家點數;
        private 手[] 閒家;
        private int[] 閒家點數;
        public BlackJack(int 閒家數量) throws IllegalArgumentException {
                if(閒家數量 < 1)
                        throw new IllegalArgumentException("閒家數量 小於 1.");
                莊家 = new 手("莊家",true);
                閒家 = new 手[閒家數量];
                閒家點數 = new int[閒家數量];
                String 名字;
                int input;
                // 輸入名字建立閒家,詢問是否為電腦控制
                for(int i = 0 ; i < 閒家數量 ; i++) {
                        名字 = JOptionPane.showInputDialog("請輸入名字:");
                        if(名字.equals(""))
                                名字 = "閒家 " + (i+1);
                        input = JOptionPane.showConfirmDialog(null,名字 + " 是否電腦控制嗎??","詢問",JOptionPane.YES_NO_OPTION);
                        閒家 = new 手(名字,input == JOptionPane.YES_OPTION);
                }
        }
        public void 洗牌() {
                牌堆.洗牌();
                莊家.清空手牌();
                for(int i = 0 ; i < 閒家.length ; i++)
                        閒家.清空手牌();
        }
        public void 發牌(手 玩家,int 張數) {
                for(int i = 0 ; i < 張數 ; i++ ) {
                        if(玩家.可以拿牌())
                                玩家.拿牌(牌堆.抽出一張牌());
                        else {
                                JOptionPane.showMessageDialog(null,玩家.get名字()+"已經爆炸了!!!");
                                break;
                        }
                }
        }
        public void 開始進行遊戲() {
                洗牌();
                this.發牌(莊家,2);
                for(int i = 0 ; i < 閒家.length ; i++) {
                        this.發牌(閒家,2);
                        JOptionPane.showMessageDialog(null,莊家.列出手牌());
                        閒家點數 = 閒家.開始要牌();
                }
                莊家點數 = 莊家.開始要牌();
                JOptionPane.showMessageDialog(null,結果());
        }
        public String 結果() {
                StringBuilder 結果 = new StringBuilder(莊家.列出手牌() + "\t" + 莊家點數 + " " + (莊家點數 > 21 ? "爆牌" : "")+"\n");
                StringBuilder 贏家 = new StringBuilder("\n  贏莊家 :\n");
                StringBuilder 輸家 = new StringBuilder("\n  輸莊家 :\n");
                StringBuilder 平手 = new StringBuilder("\n  平 手 :\n");
                StringBuilder 爆牌 = new StringBuilder("\n  爆 牌 :\n");
                莊家點數 = 莊家點數 > 21 ? -1 : 莊家點數;
                for(int i = 0 ; i < 閒家.length ; i++) {
                        結果.append(閒家.列出手牌() + "\t" + 閒家點數 + " " + (閒家點數 > 21 ? "爆牌" : "")+"\n");
                        (閒家點數 > 21 ? 爆牌 : (莊家點數 == 閒家點數 ? 平手 : (莊家點數 < 閒家點數 ? 贏家 : 輸家))).append("\t"+閒家.get名字()+ " : " + 閒家點數 +"\n");
                }
                return 結果.append(贏家).append(輸家).append(平手).append(爆牌).toString();
        }

        private class 手 {
                private final String 名字;
                private final boolean isAI;
                private ArrayList<Card> 手牌 = new ArrayList<Card>();
                private boolean hasAce = false;
                private int 總和 = 0;
                private 手(String 名字,boolean isAI) {
                        this.名字 = 名字;
                        this.isAI = isAI;
                }
                public String get名字() {
                        return 名字;
                }
                private void 清空手牌() {
                        手牌.clear();
                        hasAce = false;
                        總和 = 0;
                }
                public String 列出明牌() {
                        Card[] cards = new Card[手牌.size()];
                        手牌.toArray(cards);
                        StringBuilder sb = new StringBuilder();
                        for(int i = 1 ; i < cards.length ; i++)
                                sb.append("\t"+cards+"\n");
                        return sb.toString();
                }
                public String 列出手牌() {
                        return 名字 + ":\n\t" + ((手牌.size() > 0) ? (手牌.get(0) + "\n" + 列出明牌()) : "沒有牌");
                }

                // 由 電腦 判定是否取牌
                private void 電腦要牌() {
                        while(可以拿牌() && this.算點數() < 17)
                                BlackJack.this.發牌(this,1);
                }
                // 由 使用者 判定是否取牌
                private void 使用者要牌() {
                        int input;
                        while(可以拿牌()) {
                                input = JOptionPane.showConfirmDialog(null,this.列出手牌() + this.算點數() + "\n還要一張嗎?","詢問",JOptionPane.YES_NO_OPTION);
                                if(input == JOptionPane.YES_OPTION)
                                        BlackJack.this.發牌(this,1);
                        }
                }
                // 只有在從未取過牌時能夠取牌,根據是否為 ai 決定由誰取牌
                public synchronized int 開始要牌() {
                        if(isAI)
                                電腦要牌();
                        else
                                使用者要牌();
                        return 算點數();
                }
                private synchronized boolean 拿牌(Card 牌) {
                        int 數字 = 牌.getNum();
                        手牌.add(牌);
                        總和 += (數字 > 9 ? 10 : 數字);
                        hasAce = 數字 == 1 ? true : hasAce;
                        return 可以拿牌();
                }
                // 判斷能否拿牌
                private boolean 可以拿牌() {
                        return (總和 <= 21);
                }
                // return 現在手牌的點數和
                public int 算點數() {
                        return 總和 + (總和 < 12 && hasAce ? 10 : 0);
                }
        }
}
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

jimpig1227 發表於 2009-6-8 07:45 AM

這就是21點的遊戲嗎?謝謝大大分享,之前看到有人問,就很好奇程式碼是如何寫的,現在有可以多一個學習的機會了 ,謝謝

s800310 發表於 2009-6-9 02:49 AM

QQ編譯不出來  為何有CLASS相同PACKAGE也相同的檔案

要如何編譯呢?  望高手解答

q1rtpj5c 發表於 2009-6-9 12:30 PM

感謝大大分享~~
JAVA新手正在努力學習中^^~<br><br><br><br><br><div></div>
頁: [1]