跳转至

Java 中的二十一点游戏开发指南

简介

二十一点(Blackjack)是一款经典的纸牌游戏,在世界各地都广受欢迎。在本文中,我们将探讨如何使用 Java 来开发二十一点游戏。我们会涵盖从基础概念到高级实践的内容,帮助你掌握在 Java 中实现二十一点游戏的技能。

目录

  1. 二十一点基础概念
  2. Java 中实现二十一点的使用方法
    • 牌组的表示
    • 玩家和庄家的表示
    • 游戏流程控制
  3. 常见实践
    • 牌的洗牌与发牌
    • 计算手牌点数
    • 判断胜负
  4. 最佳实践
    • 面向对象设计
    • 异常处理
    • 用户界面设计
  5. 小结
  6. 参考资料

二十一点基础概念

二十一点游戏使用标准的 52 张扑克牌。游戏目标是让玩家的手牌点数尽可能接近但不超过 21 点,同时要比庄家的手牌点数大。牌面的点数计算规则如下: - 牌面 2 - 10 的点数就是其牌面数字。 - 花脸牌(J、Q、K)的点数为 10。 - A 牌可以当作 1 点或 11 点,取决于哪种情况对玩家更有利。

Java 中实现二十一点的使用方法

牌组的表示

在 Java 中,我们可以使用一个类来表示牌组。每个牌都有花色(suit)和点数(rank)。

class Card {
    private String suit;
    private String rank;

    public Card(String suit, String rank) {
        this.suit = suit;
        this.rank = rank;
    }

    public String getSuit() {
        return suit;
    }

    public String getRank() {
        return rank;
    }

    @Override
    public String toString() {
        return rank + " of " + suit;
    }
}

class Deck {
    private Card[] cards;
    private int currentCard;

    public Deck() {
        cards = new Card[52];
        String[] suits = {"Hearts", "Diamonds", "Clubs", "Spades"};
        String[] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
        int index = 0;
        for (String suit : suits) {
            for (String rank : ranks) {
                cards[index++] = new Card(suit, rank);
            }
        }
        currentCard = 0;
    }

    public void shuffle() {
        for (int i = cards.length - 1; i > 0; i--) {
            int j = (int) (Math.random() * (i + 1));
            Card temp = cards[i];
            cards[i] = cards[j];
            cards[j] = temp;
        }
        currentCard = 0;
    }

    public Card dealCard() {
        if (currentCard < cards.length) {
            return cards[currentCard++];
        }
        return null;
    }
}

玩家和庄家的表示

我们可以创建一个 Player 类来表示玩家和庄家。

class Player {
    private String name;
    private Hand hand;

    public Player(String name) {
        this.name = name;
        hand = new Hand();
    }

    public String getName() {
        return name;
    }

    public Hand getHand() {
        return hand;
    }

    public void addCard(Card card) {
        hand.addCard(card);
    }
}

class Hand {
    private Card[] cards;
    private int currentCard;

    public Hand() {
        cards = new Card[10];
        currentCard = 0;
    }

    public void addCard(Card card) {
        if (currentCard < cards.length) {
            cards[currentCard++] = card;
        }
    }

    public int calculateValue() {
        int value = 0;
        int aces = 0;
        for (int i = 0; i < currentCard; i++) {
            String rank = cards[i].getRank();
            if (rank.equals("Ace")) {
                value += 11;
                aces++;
            } else if (rank.equals("Jack") || rank.equals("Queen") || rank.equals("King")) {
                value += 10;
            } else {
                value += Integer.parseInt(rank);
            }
        }
        while (value > 21 && aces > 0) {
            value -= 10;
            aces--;
        }
        return value;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < currentCard; i++) {
            sb.append(cards[i]).append(", ");
        }
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 2);
        }
        return sb.toString();
    }
}

游戏流程控制

下面是一个简单的游戏流程示例,展示了如何发牌、让玩家要牌以及判断胜负。

public class Blackjack {
    public static void main(String[] args) {
        Deck deck = new Deck();
        deck.shuffle();

        Player player = new Player("Player");
        Player dealer = new Player("Dealer");

        player.addCard(deck.dealCard());
        dealer.addCard(deck.dealCard());
        player.addCard(deck.dealCard());
        dealer.addCard(deck.dealCard());

        System.out.println("Player's hand: " + player.getHand() + " Value: " + player.getHand().calculateValue());
        System.out.println("Dealer's hand: " + dealer.getHand().getCard(0) + " and one hidden card");

        // 玩家要牌
        while (true) {
            java.util.Scanner scanner = new java.util.Scanner(System.in);
            System.out.println("Do you want to hit (y/n)?");
            String choice = scanner.nextLine();
            if (choice.equalsIgnoreCase("y")) {
                player.addCard(deck.dealCard());
                System.out.println("Player's hand: " + player.getHand() + " Value: " + player.getHand().calculateValue());
                if (player.getHand().calculateValue() > 21) {
                    System.out.println("Player busts! Dealer wins.");
                    return;
                }
            } else {
                break;
            }
        }

        // 庄家要牌
        while (dealer.getHand().calculateValue() < 17) {
            dealer.addCard(deck.dealCard());
        }

        System.out.println("Dealer's hand: " + dealer.getHand() + " Value: " + dealer.getHand().calculateValue());

        if (dealer.getHand().calculateValue() > 21) {
            System.out.println("Dealer busts! Player wins.");
        } else if (player.getHand().calculateValue() > dealer.getHand().calculateValue()) {
            System.out.println("Player wins!");
        } else if (player.getHand().calculateValue() < dealer.getHand().calculateValue()) {
            System.out.println("Dealer wins!");
        } else {
            System.out.println("It's a tie!");
        }
    }
}

常见实践

牌的洗牌与发牌

洗牌是保证游戏公平性的关键步骤。我们使用 Fisher-Yates 洗牌算法来随机打乱牌组顺序。发牌时,我们只需要从牌组中按顺序取出牌并分配给玩家或庄家。

计算手牌点数

计算手牌点数时,需要特别处理 A 牌。我们先将 A 牌当作 11 点计算,如果总点数超过 21 点且有 A 牌,就将 A 牌当作 1 点重新计算。

判断胜负

判断胜负时,首先检查是否有一方 bust(点数超过 21 点)。如果没有 bust,比较双方的点数大小来确定胜负。

最佳实践

面向对象设计

使用类来表示游戏中的各种实体,如牌、牌组、玩家和庄家。这样可以提高代码的可维护性和扩展性。每个类应该有清晰的职责,例如 Card 类负责表示一张牌,Deck 类负责管理牌组等。

异常处理

在代码中添加适当的异常处理,例如当牌组耗尽时发牌方法应该抛出异常。这可以使程序更加健壮,避免在运行时出现意外错误。

用户界面设计

如果要开发一个完整的游戏,良好的用户界面设计是必不可少的。可以使用 Java 的图形库(如 Swing 或 JavaFX)来创建美观、易用的界面,提升玩家的游戏体验。

小结

通过本文,我们学习了在 Java 中实现二十一点游戏的基础概念、使用方法、常见实践和最佳实践。我们从牌组的表示开始,逐步构建了玩家、庄家和游戏流程的逻辑。通过遵循最佳实践,我们可以创建一个高效、健壮且用户体验良好的二十一点游戏。

参考资料

  • 《Effective Java》 - Joshua Bloch