I tried to implement Dragon Quest poker in Python

Introduction

This time, I would like to implement Dragon Quest poker using the deck in Previous article.

Normal poker is basically played between players,

For this reason, it ’s not poker between players, I would like to implement a one-person game like Dragon Quest poker.

Game flow

Make a role in poker → Double your score in a double-up game That is the basic flow.

Functional requirements

Basic

poker

  1. 5 cards are dealt
  2. Select to change or leave one by one
  3. Swap the card you chose to change
  4. Calculation of the role with 5 cards after replacement
  5. Judge the role and decide the score according to the role

Double up game

  1. Five cards are dealt (one face up, four face down)
  2. Select a card that you think is stronger than the face-up card from the four face-down cards
  3. If you are strong, your score will be doubled and you can try the double-up game again.
  4. If weak, score 0, restart from poker

About roles and scores

Role name Card status Example of hand Score
1 pair One pair of the same number [♣️-4, ♠︎-4, ♦︎-Q, ♠︎-K, ❤︎-5] 50
2 pairs Two pairs of the same number [♣️-4, ♠︎-4, ♦︎-Q, ♠︎-Q, ❤︎-5] 100
3 cards 3 same numbers [♣️-4, ♠︎-4, ♦︎-4, ♠︎-Q, ❤︎-5] 200
straight The numbers are continuous [♣️-3, ♠︎-4, ♦︎-5, ♠︎-6, ❤︎-7] 300
flash All marks are the same [♠︎-3, ♠︎-4, ♠︎-5, ♠︎-Q, ♠︎-9] 400
Full house 3 same numbers+1 pair [♠︎-3, ♠︎-4, ♠︎-5, ♠︎-Q, ♠︎-9] 500
Four Cards 4 same numbers [♠︎-4, ♦︎-4, ♠︎-4, ♣️-4, ❤︎-9] 1000
Straight flush Flash and straight [♠︎-4, ♠︎-5, ♠︎-6, ♠︎-7, ♠︎-8] 2000
Royal straight flush Flash and straight [♠︎-10, ♠︎-J, ♠︎-Q, ♠︎-K, ♠︎-A] 10000

Implementation

We have prepared the following classes. I think there are other good ways. ..

Card class / Deck class

I used the one created in this article as it is.

Player class

class Player:
    """
Player Score / Hand / Poker Victory Flag
    """

    def __init__(self):
        self.score = 0
        self.hands = []
        self.is_poker_win = True

    def draw_card(self, deck, num=1):
        """
Draw a card from the deck and add it to your hand
* Even if different numbers are drawn, it is ok

        Parameters
        ----------
        num : int, default 1
Number of times to draw a card

        Examples
        --------
        >>> player.draw_card(2) #2 draws[♠︎-J, ♠︎-10]
        >>> player.draw_card(3) # [♦︎-9, ♣️-10, ♠︎-2]
        >>> print(player.hands)
        [♠︎-J, ♠︎-10, ♦︎-9, ♣️-10, ♠︎-2]
        """
        self.hands_store = deck.pick_card(num)
        self.hands.extend(self.hands_store)

Game class

class Game:
    """
Main game

    Examples
    --------
    >>> game = Game()
    >>> game.main() #Game start (displays the initial phase below)

    """

    RANKS = (*"23456789", "10", *"JQKA")
    VALUES = (range(2, 14 + 1))
    #Associate the display mark with the score
    RANK_TO_VALUES = dict(zip(RANKS, VALUES))

    def main(self):
        """
The whole game (poker)+Double up chance)
        """
        can_play_game = True

        while can_play_game:

            #Reset player information for each game
            player = Player()

            #Deck set (determine the number of sets)=Rebuild the deck for each game
            deck = stock.Deck()
            poker = Poker(deck, player)
            poker.main_game()

            #Double up chance with a role
            print(player.is_poker_win)
            if player.is_poker_win:
                bonus_game = DoubleUp(player)
                bonus_game.main_game()

            #Game restart
            restart_msg = "End the game with Q, start the game otherwise:"
            start_res = input(restart_msg)
            if start_res == 'Q':
                can_play_game = False


if __name__ == '__main__':
    game = Game()
    game.main()

Poker class

About role judgment

The flow chart below shows the combination judgment.

poker.png

class Poker:

    RANKS = (*"23456789", "10", *"JQKA")
    VALUES = (range(2, 14 + 1))
    #Associate the display mark with the score
    RANK_TO_VALUES = dict(zip(RANKS, VALUES))

    def __init__(self, deck, player):
        self.deck = deck
        self.player = player

    def change_hands(self, player_hands):
        """
Let them exchange cards one by one and return the exchanged hand

        Parameters
        ----------
        player_hands : list
Player deck before card exchange

        Returns
        --------
        changed_hands : list
Player deck after card exchange
        """

        changed_hands = []

        #Select either "Rubbing" or "Frog" for each card
        print("Enter \"y\" to replace the card.")

        for card_idx, change_card in enumerate(player_hands):
            change_card_msg = f"{change_card}:"
            change_card_res = input(change_card_msg)

            #If you want to change it, draw from the deck and exchange the card
            if change_card_res == "y":
                #Draw from the deck and overwrite
                change_card = self.deck.pick_card(1)[0]
                self.player.hands[card_idx] = change_card

            #Added to associative array
            check_card_set = str(change_card).split("-")
            # ❤︎
            card_mark = check_card_set[0]
            # K
            card_rank = check_card_set[1]
            # 13
            card_number = self.RANK_TO_VALUES[card_rank]
            #Add to check dictionary
            changed_hands.append({
                "mark": card_mark,
                "rank": card_rank,
                "number": card_number
            })
        return changed_hands

    def calc_hand(self, check_hands):
        """
Calculation of roles from hand

        Parameters
        ----------
        check_hands : list
Player deck after card exchange

        Returns
        --------
        hand_results : dict
The state of each role in the player's deck
        """

        #Flash (same mark)
        is_flash = True
        #Straight (numbers are serial numbers)
        is_straight = True
        #Count of the same number
        same_number_count = 0
        same_number = 0
        #Number of pairs (1 pair or 2 pairs)
        match_pair_count = 0

        #Sort from hand to card number in ascending order
        check_hands_sorted = sorted(check_hands, key=lambda x: x["number"])

        #Check one by one from 5 cards
        for check_idx, check_card in enumerate(check_hands_sorted):

            #Skip the first card because there is no previous card
            if check_idx == 0:
                continue

            #Previous card{'mark': '♠︎', 'rank': '4', 'number': 4}
            prev_card = check_hands_sorted[check_idx - 1]

            #If the front and back marks are different, set the flash judgment to False.
            if is_flash and check_card["mark"] != prev_card["mark"]:
                is_flash = False

            #If the numbers are not consecutive before and after, set the straight judgment to False.
            if is_straight and check_card["number"] != prev_card["number"] + 1:
                is_straight = False

            #If the numbers match before and after, count the same number+1
            if check_card["number"] == prev_card["number"]:
                #Number of matches+ 1
                same_number_count += 1

                #Last card
                if check_idx == 4:
                    if same_number_count == 1:
                        #Number of pairs+ 1
                        match_pair_count += 1
                    else:
                        #3 cards and 4 cards
                        same_number = same_number_count + 1

            #For different numbers
            else:
                if same_number_count == 1:
                    #Number of pairs+ 1
                    match_pair_count += 1
                elif same_number_count > 1:
                    #3 cards and 4 cards
                    same_number = same_number_count + 1
                #Reset because it is a different number
                same_number_count = 0

        #State of each role in the hand
        hand_results = {
            "is_flash": is_flash,
            "is_straight": is_straight,
            "same_number_count": same_number_count,
            "same_number": same_number,
            "match_pair_count": match_pair_count
        }
        return hand_results

    def showdown_hand(self, hand_status, check_hands):
        """
Determining the role from the state of the role, score calculation

        Parameters
        ----------
        hand_status : dict
The state of the player's role after exchanging cards
        check_hands : list
player's hand

        Returns
        --------
        hand_result_msg : str
Judgment sentence of the role
        """

        #result
        hand_result_msg = ""

        #Flash and straight
        if hand_status["is_flash"] and hand_status["is_straight"]:
            #The smallest card is 10,The largest card is 14(A)
            if check_hands[0]["number"] == 10 and  \
                    check_hands[4]["number"] == 14:
                hand_result_msg = "Royal straight flush"
                self.player.score = 10000
            else:
                hand_result_msg = "Straight flush"
                self.player.score = 2000
        #4 cards
        elif hand_status["same_number"] == 4:
            hand_result_msg = "4 cards"
            self.player.score = 1000

        #3 cards,Full house judgment
        elif hand_status["same_number"] == 3:
            #3 cards and 1 pair
            if hand_status["match_pair_count"] == 1:
                hand_result_msg = "Full house"
                self.player.score = 500
            else:
                hand_result_msg = "3 cards"
                self.player.score = 250

        #flash
        elif hand_status["is_flash"]:
            hand_result_msg = "flash"
            self.player.score = 400

        #straight
        elif hand_status["is_straight"]:
            hand_result_msg = "straight"
            self.player.score = 300

        #2 pairs
        elif hand_status["match_pair_count"] == 2:
            hand_result_msg = "2 pairs"
            self.player.score = 200

        #1 pair
        elif hand_status["match_pair_count"] == 1:
            hand_result_msg = "1 pair"
            self.player.score = 150

        return hand_result_msg

    def main_game(self):
        """
Main game of poker
        """

        print("Poker Game start")

        #First draw 5 cards
        self.player.draw_card(self.deck, 5)

        #Initial card display
        print(f"player's hands:{self.player.hands}")

        #Card exchange phase
        check_hands = self.change_hands(self.player.hands)

        #Card display after exchange
        print(f"player's hands:{self.player.hands}")

        #Sort in ascending order based on the numbers in your hand
        check_hands_sorted = sorted(check_hands, key=lambda x: x["number"])

        #Calculation of roles from hand
        hand_results = self.calc_hand(check_hands_sorted)
        print(hand_results)
        #Role judgment
        hand_result_msg = self.showdown_hand(hand_results, check_hands_sorted)

        #Lose if there is nothing
        if hand_result_msg == "":
            hand_result_msg = "There was no role..."
            self.player.is_poker_win = False

        #Result output
        print(hand_result_msg)

DoubleUp class

import re
from deck import stock


class DoubleUp:

    RANKS = (*"23456789", "10", *"JQKA")
    VALUES = (range(2, 14 + 1))
    #Associate the display mark with the score
    RANK_TO_VALUES = dict(zip(RANKS, VALUES))

    def __init__(self, player):
        self.player = player
        self.is_game_win = True

    def add_check_hands(self, player_hands):
        """
Display cards one by one and assign numbers

        Parameters
        ----------
        player_hands : list
5 cards in hand

        Returns
        --------
        check_hands : list
player's hand
        """

        check_hands = []
        for card_idx, card_val in enumerate(player_hands):

            #Added to associative array
            check_card_set = str(card_val).split("-")
            # ❤︎
            card_mark = check_card_set[0]
            # K
            card_rank = check_card_set[1]
            # 13
            card_number = self.RANK_TO_VALUES[card_rank]
            #Add to check dictionary
            check_hands.append({
                "mark": card_mark,
                "rank": card_rank,
                "number": card_number
            })
            #The first cannot be selected
            if card_idx >= 1:
                #hide
                # print(f"{card_idx}:*-*")
                print(f"{card_idx}:{card_val}")

        return check_hands

    def win_judge_selected_card(self, input_res, check_hands):
        """
Game Victory Judgment (Compare selected card with face-up card)

        Parameters
        ----------
        input_res : str
The number entered in the command
        check_hands : list
player's hand
        """

        if re.compile(r'^[1-4]+$').match(input_res) is not None:
            #Comparison of the number size of the card with the selected number and the face-up card
            if check_hands[int(input_res)]["number"] >= check_hands[0]["number"]:
                #Double the score if it is large
                print("win!")
                self.player.score *= 2
            else:
                #If small,Score 0 and start again from poker
                print("lose..")
                self.player.score = 0
                self.is_game_win = False
        else:
            print("Is useless")

    def main_game(self):
        """
Double-up main game
        """

        while self.is_game_win:
            #Reconstruction of deck
            self.deck = stock.Deck()
            print("double-Up Chance Game start")
            print(f"Now, your score is {self.player.score} points.")
            self.player.hands = []

            #Deal 5 cards from the deck
            self.player.draw_card(self.deck, 5)

            #1 out of 5 is set face up, 4 is face down
            print(f"player's hands:{self.player.hands[0]}, *-*, *-*, *-*, *-*")

            #Display cards one by one and assign numbers
            check_hands = self.add_check_hands(self.player.hands)

            #Choose one of the four face-down cards that is stronger than the number on the face-up card
            card_select_msg = f"Enter a card number that is stronger than {self.player.hands[0]}:"
            card_select_res = input(card_select_msg)

            #Choose one from numbers 1 to 4
            self.win_judge_selected_card(card_select_res, check_hands)

            print(self.player.score)

motion

$ python main.py
Poker Game start

player's hands:[❤︎-4, ♠︎-9, ♣️-4, ♠︎-3, ♠︎-2]
Enter "y" to replace the card.
❤︎-4:
♠︎-9: y
♣️-4:
♠︎-3: y
♠︎-2: y
player's hands:[❤︎-4, ❤︎-K, ♣️-4, ♠︎-K, ♣️-6]
2 pairs

double-Up Chance Game start
Now, your score is 100 points.
player's hands:♠︎-6, *-*, *-*, *-*, *-*
1:*-*
2:*-*
3:*-*
4:*-*
Enter a card number that is stronger than ♠︎-6: 2
Selected card is ❤︎-12
win!
200

double-Up Chance Game start
Now, your score is 200 points.
player's hands:♠︎-K, *-*, *-*, *-*, *-*
1:*-*
2:*-*
3:*-*
4:*-*
Enter a card number that is stronger than ♠︎-K: 3
Selected card is ♦︎-2
lose..
0

End the game with Q, start the game otherwise: Q

Recommended Posts

I tried to implement Dragon Quest poker in Python
I tried to implement PLSA in Python
I tried to implement permutation in Python
I tried to implement PLSA in Python 2
I tried to implement ADALINE in Python
I tried to implement PPO in Python
I tried to implement TOPIC MODEL in Python
I tried to implement selection sort in python
I tried to implement a pseudo pachislot in Python
I tried to implement GA (genetic algorithm) in Python
I tried to implement a one-dimensional cellular automaton in Python
I tried to implement the mail sending function in Python
I tried to implement blackjack of card game in Python
I tried to implement a misunderstood prisoner's dilemma game in Python
I tried to implement Bayesian linear regression by Gibbs sampling in python
I tried to implement StarGAN (1)
I tried to implement a card game of playing cards in Python
I tried to graph the packages installed in Python
I want to easily implement a timeout in python
I tried to implement Minesweeper on terminal with python
I tried to implement an artificial perceptron with python
I tried to summarize how to use pandas in python
I tried to implement merge sort in Python with as few lines as possible
I tried to implement what seems to be a Windows snipping tool in Python
I tried to implement Deep VQE
I tried to touch Python (installation)
I tried to implement adversarial validation
I tried to implement hierarchical clustering
I tried to implement Realness GAN
I tried Line notification in Python
I tried to create API list.csv in Python from swagger.yaml
I tried "How to get a method decorated in Python"
I tried to make a stopwatch using tkinter in python
I tried to summarize Python exception handling
I tried to implement Autoencoder with TensorFlow
Python3 standard input I tried to summarize
I tried using Bayesian Optimization in Python
I wanted to solve ABC159 in Python
I tried to implement CVAE with PyTorch
[Python] I tried to calculate TF-IDF steadily
I tried to touch Python (basic syntax)
[Python] I tried to summarize the set type (set) in an easy-to-understand manner.
I tried to develop a Formatter that outputs Python logs in JSON
I tried to solve AtCoder's depth-first search (DFS) in Python (result: TLE ...)
I tried to implement reading Dataset with PyTorch
I want to do Dunnett's test in Python
Try to implement Oni Maitsuji Miserable in python
How to implement Discord Slash Command in Python
I want to create a window in Python
I tried playing a typing game in Python
How to implement shared memory in Python (mmap.mmap)
I tried to integrate with Keras in TFv1.1
I tried simulating the "birthday paradox" in Python
I tried the least squares method in Python
I wrote "Introduction to Effect Verification" in Python
[Memo] I tried a pivot table in Python
I tried to output LLVM IR with Python
I want to merge nested dicts in Python
I tried non-blocking I / O Eventlet behavior in Python
I tried to automate sushi making with python
I tried adding a Python3 module in C