Refactoring: Machen Sie Blackjack in Java

Nachtrag: @ k73i55no5 kommentierte einen besseren Refactoring-Vorschlag. Vielen Dank. Siehe Kommentare für Details. Refactoring nur der Klassenmitgliedsstruktur (Struktur). Wir haben noch nicht begonnen, den Verarbeitungscode (Interieur, Implementierung) umzugestalten. (Bis hierher addiert)

Ich habe den Quellcode von "Blackjack mit Java machen" von @ yuta-yoshinaga gesehen. Ich schrieb einen etwas bitteren Kommentar, weil die Kapselung von allen Setzern und Gettern zerstört wurde und einige Klassen nicht funktionierten. Es ist nur ein Kommentar, also habe ich ihn auf meine eigene Weise überarbeitet. Es gibt noch einige Punkte zu überprüfen, aber ich hoffe, Sie finden es hilfreich.

Fügen Sie ein Sequenzdiagramm hinzu.

@startuml
participant "BlackJack" as blackjack
@enduml

BlackJack.java


public class BlackJack {
    private final Player player;
    private final Dealer dealer;

    public BlackJack() {
        this(new CUIPlayer(), new Dealer());
    }

    public BlackJack(Player player, Dealer dealer) {
        this.player = player;
        this.dealer = dealer;
    }

    public void play() {
        player.reset();
        dealer.reset();
        for (int i = 0; i < 2; i++) {
            dealer.dealCard(player);
            dealer.dealCard(dealer);
        }
        dealer.show();
        if (player.play(dealer)) {
            dealer.play(dealer);
            showJudge();
        }
    }

    public void showJudge() {
        dealer.show();
        player.show();
        Player winner = judgeWinner();
        System.out.println("----------");
        if (winner == player) {
            System.out.println("You are the winner.");
        } else if (winner == dealer) {
            System.out.println("It is your loss.");
        } else {
            System.out.println("It is a draw.");
        }
    }

    public Player judgeWinner() {
        if (player.isBust()) {
            return dealer;
        } else  if (dealer.isBust()) {
            return player;
        } else if (player.isBlackJack() && !dealer.isBlackJack()) {
            return player;
        } else if (dealer.isBlackJack() && !player.isBlackJack()) {
            return dealer;
        }
        int diff = player.calcScore() - dealer.calcScore();
        if (diff > 0) {
            return player;
        } else if (diff < 0) {
            return dealer;
        } else {
            return null;
        }
    }

    public static void main(String[] args) {
        BlackJack blackjack = new BlackJack();
        while (true) {
            blackjack.play();
            blackjack.player.play(null);
        }
    }
}

Player.java


import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

abstract public class Player {
    public final String name;
    protected final List<Card> cards = new ArrayList<Card>();
    protected boolean stand = false;

    public Player() {
        this("Player");
    }

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

    public void reset() {
        cards.clear();
        stand = false;
    }

    public void holdCard(Card card) {
        cards.add(card);
    }

    abstract boolean play(CardDealer dealer);

    public int calcScore() {
        int score = 0;
        boolean hasAce = false;
        for (Card card: cards) {
            score += card.rank < 10 ? card.rank : 10;
            if (card.rank == 1) {
                hasAce = true;
            }
        }
        if (score <= 11 && hasAce) {
            score += 10;
        }
        return score;
    }

    public boolean isBlackJack() {
        return cards.size() == 2 && calcScore() == 21;
    }

    public boolean isBust() {
        return calcScore() > 21;
    }

    public void show() {
        System.out.println("----------");
        showCards();
        System.out.println(name + "'s score: " + calcScore());
    }

    public void showCards() {
        System.out.println(name + "'s card: " + cards.stream().map(Object::toString).collect(Collectors.joining(", ")));
    }
}

CUIPlayer.java


import java.util.Scanner;

public class CUIPlayer extends Player {
    private Scanner sc = new Scanner(System.in);

    public boolean play(CardDealer dealer) {
        while (!isBust() || dealer == null) {
            if (!stand) {
                show();
            }
            System.out.println("----------");
            System.out.println("Please enter a command.");
            System.out.println("  q: quit");
            System.out.println("  r: restart");
            if (!stand && dealer != null) {
                System.out.println("  h: hit");
                System.out.println("  s: stand");
            }
            System.out.print("? ");
            String inputStr = sc.nextLine();
            switch (inputStr) {
                case "q":
                case "quit":
                    System.out.println("bye.");
                    sc.close();
                    System.exit(0);
                    break;
                case "r":
                case "reset":
                    return false;
                case "h":
                case "hit":
                    if (!stand && dealer != null) {
                        dealer.dealCard(this);
                    }
                    break;
                case "s":
                case "stand":
                    stand = true;
                    return true;
                default:
                    System.out.println("Unsupported command.");
                    break;
            }
        }
        stand = true;
        return true;
    }
}

Dealer.java


public class Dealer extends Player implements CardDealer {
    private final Deck deck;

    public Dealer() {
        this(new Deck());
    }

    public Dealer(Deck deck) {
        super("Dealer");
        this.deck = deck;
    }

    public void dealCard(Player player) {
        player.holdCard(deck.drowCard());
    }

    public boolean play(CardDealer dealer) {
        while (calcScore() < 17) {
            dealer.dealCard(this);
        }
        stand = true;
        return true;
    }

    @Override
    public void show() {
        if (stand || cards.size() != 2) {
            super.show();
        } else {
            System.out.println("----------");
            cards.get(1).faceDown();
            showCards();
            cards.get(1).faceUp();
        }
    }
}

CardDealer.java


public interface CardDealer {
    public void dealCard(Player player);
}

Deck.java


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

public class Deck {
    private final ArrayList<Card> cards = new ArrayList<Card>();

    public Deck() {
        reset();
    }

    void reset() {
        cards.clear();
        for (Suit suit: Suit.values()) {
            for (int rank = 1; rank <= 13; rank++) {
                cards.add(new Card(suit, rank));
            }
        }
        shuffle();
    }

    public void shuffle() {
        Collections.shuffle(cards);
    }

    public Card drowCard() {
        if (cards.size() == 0) {
            reset();
        }
        return cards.remove(0);
    }
}

Card.java


enum Suit {
    SPADE, CLOBBER, HEART, DIAMOND;
}

public class Card {
    public static String[] RANK = {
        "", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"
    };

    public final Suit suit;
    public final int rank;
    private boolean visible;

    public Card(Suit suit, int rank) {
        this.suit = suit;
        this.rank = rank;
        faceUp();
    }

    public void faceUp() {
        this.visible = true;
    }

    public void faceDown() {
        this.visible = false;
    }

    @Override
    public String toString() {
        if (visible) {
            return suit.name() + ' ' + RANK[rank];
        } else {
            return "???";
        }
    }
}

Recommended Posts

Refactoring: Machen Sie Blackjack in Java
Machen Sie einen Blackjack mit Java
Einfach, Slack Bot mit Java zu machen
Partisierung in Java
Änderungen in Java 11
Janken in Java
Refactoring in JUnit
Umfangsrate in Java
FizzBuzz in Java
Ich wollte (a == 1 && a == 2 && a == 3) in Java wahr machen
Interpreter-Implementierung durch Java
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
NVL-artiger Typ in Java
"Hallo Welt" in Java
Aufrufbare Schnittstelle in Java
Kommentare in der Java-Quelle
Azure funktioniert in Java
Formatieren Sie XML in Java
Einfache HTML-Spezialchars in Java
Boyer-Moore-Implementierung in Java
Hallo Welt in Java
Verwenden Sie OpenCV mit Java
WebApi-Memorandum mit Java
Typbestimmung in Java
Befehle in Java ausführen (Ping)
Verschiedene Threads in Java
Implementierung der Heap-Sortierung (in Java)
Zabbix API in Java
ASCII-Kunst in Java
Listen in Java vergleichen
POST JSON in Java
Fehler in Java ausdrücken
Erstellen Sie JSON in Java
Datumsmanipulation in Java 8
Was ist neu in Java 8?
Verwenden Sie PreparedStatement in Java
Was ist neu in Java 9,10,11
Parallele Ausführung in Java
Java-Anfänger machen Pokerspiele in 4 Tagen (3. Tag)
[Persönliches Memo] Erstellen Sie eine einfache, tiefe Kopie mit Java
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Java-Anfänger machen Pokerspiele in 4 Tagen (2. Tag)
Versuchen Sie es mit RocksDB mit Java
[Java] Machen Sie die Variablen der erweiterten for-Anweisung und für jede Anweisung unveränderlich
Lesen Sie Binärdateien in Java 1
Vermeiden Sie den Fehler, den Yuma in Java gemacht hat
Erstellen wir eine Taschenrechner-App mit Java ~ Zeigen Sie das Anwendungsfenster an
Holen Sie sich EXIF-Informationen in Java
Java - So erstellen Sie JTable
[Neta] Sleep Sort in Java
Bearbeiten von ini in Java: ini4j
Java-Geschichte in dieser Welt
Segfo Java in 6 Zeilen
Lassen Sie uns Spresense mit Java entwickeln (1)
Probieren Sie den Funktionstyp in Java aus! ①
Ich habe ein Roulette in Java gemacht.