Как лучше организовать подсчёт счёта

В целях изучения программирования делаю игру 21, уже довольно долго думаю как организовать подсчёт карт. На данный момент думаю насчёт туплей в тупле, но возвращать то приходится всё равно стринг..

def make_deck(self):
        numbers = (("6", 6), ("7", 7),  ("8", 8), ("9", 9), ("10", 10), ("Jack", 2), ("Queen", 3), ("King", 4), ("Ace", 11))
        suits = ("Diamonds", "Spades", "Hearts", "Clubs")
        deck = []
        for i in range(len(numbers)):
            count = 0
            while count < 4:
                deck.append((numbers[i][0] + " " + numbers[i][1]) + " of " + suits[count])
                count += 1    
        return deck

Вопрос к более опытным людям - в какую сторону смотреть, что бы проще организовать подсчёт карт? Я думал потом разбивать итоговый стринг по пробелам, выводить для юзера определённые знаки, а функции подсчёта давать только цифры веса карт. Но что-то мне подсказывает, что это не очень хорошая идея в плане оптимизации и в целом.


Ответы (2 шт):

Автор решения: Sergei Kirjanov

Mожно туплы, можно класс сделать под карту.

возвращать то приходится всё равно стринг

Возвращать из функции можно что угодно. Вот показывать пользователю в текстовой игре -- стринг.

Склеивать проще, чем парсить. Храните в структурированном виде.


K ООП я отношусь спокойно. Его плюсы заметны на сложном проекте, и со статической типизацией.

Что за "сложность"? На вашем примере (предположим):

  • вы начнaаете путаться, что на какой позиции в тупле лежит
  • вы начнaаете путаться между разными по смыслу туплами.

Вот, нашел такую возможность:

from collections import namedtuple 
Card = namedtuple('Card', 'title,value')
card = Card("Ace",11)
print(card.title)
print(card)
print(type(card))

У namedtuple можно брать элементы по имени и смотреть тип.

→ Ссылка
Автор решения: MarianD
def make_deck(self):
    numbers = (("6", 6), ("7", 7),  ("8", 8), ("9", 9), ("10", 10), ("Jack", 2), ("Queen", 3), ("King", 4), ("Ace", 11))
    suits = ("Diamonds", "Spades", "Hearts", "Clubs")
    deck = []
    for name, number in numbers:
        for suit in suits:
            # deck.append(f"({name} {number}) of {suit}")   # не как строки,
            deck.append((name, number, suit))               # a как кортежи
    return deck

Результат — значение возвращённой переменной deck:

[('6', 6, 'Diamonds'),
 ('6', 6, 'Spades'),
 ('6', 6, 'Hearts'),
 ('6', 6, 'Clubs'),
 ('7', 7, 'Diamonds'),
 ('7', 7, 'Spades'),
 ('7', 7, 'Hearts'),
 ('7', 7, 'Clubs'),
 ('8', 8, 'Diamonds'),
 ('8', 8, 'Spades'),
 ('8', 8, 'Hearts'),
 ('8', 8, 'Clubs'),
 ('9', 9, 'Diamonds'),
 ('9', 9, 'Spades'),
 ('9', 9, 'Hearts'),
 ('9', 9, 'Clubs'),
 ('10', 10, 'Diamonds'),
 ('10', 10, 'Spades'),
 ('10', 10, 'Hearts'),
 ('10', 10, 'Clubs'),
 ('Jack', 2, 'Diamonds'),
 ('Jack', 2, 'Spades'),
 ('Jack', 2, 'Hearts'),
 ('Jack', 2, 'Clubs'),
 ('Queen', 3, 'Diamonds'),
 ('Queen', 3, 'Spades'),
 ('Queen', 3, 'Hearts'),
 ('Queen', 3, 'Clubs'),
 ('King', 4, 'Diamonds'),
 ('King', 4, 'Spades'),
 ('King', 4, 'Hearts'),
 ('King', 4, 'Clubs'),
 ('Ace', 11, 'Diamonds'),
 ('Ace', 11, 'Spades'),
 ('Ace', 11, 'Hearts'),
 ('Ace', 11, 'Clubs')]

Объяснение:

  1. В Питоне не нужно итерировать по индексам, а прямо по элементам списка / кортежа:

    for suit in suits:
    
  2. Из кортежа можно получить отдельные элементы через запятую:

    for name, number in numbers:
    
  3. Вместо конструкции сложной строки с применением оператора + возможно применить f-строки:

    f"({name} {number}) of {suit}"
    
  4. Вместо списка строк сделайте список кортежей, см. пункт 2 как из них получить отдельные элементы:

    (name, number, suit)
    
  5. Вместо циклов возможно использовать генератор списка, т.е

    deck = [(name, number, suit) for name, number in numbers for suit in suits]
    

    вместо

    deck = []
    for name, number in numbers:
        for suit in suits:
            deck.append((name, number, suit))
    

    и даже возвратит его прямо в команде return, вез предварительного присвоения, чем ваша функция может оказаться слишком короткой:

    def make_deck(self):
        numbers = (("6", 6), ("7", 7),  ("8", 8), ("9", 9), ("10", 10), ("Jack", 2), ("Queen", 3), ("King", 4), ("Ace", 11))
        suits = ("Diamonds", "Spades", "Hearts", "Clubs")
        return [(name, number, suit) for name, number in numbers for suit in suits]
    
  6. Вместо кортежа парей numbers вы можете более наглядно создать 2 самостоятельные списки

    names = "6 7 8 9 10 Jack Queen King Ace".split()     # список ["6", "7", ..., "Ace"]
    nums = (6, 7, 8, 9, 10, 2, 3, 4, 11)
    

    В случае необходимости вы всегда можете склеить их обратно в соответствующие пары применением стандартной функции zip():

    numbers = zip(names, nums)
    

    и даже создать из них словарь:

    dict(zip(names, nums))
    
    {'6': 6,
     '7': 7,
     '8': 8,
     '9': 9,
     '10': 10,
     'Jack': 2,
     'Queen': 3,
     'King': 4,
     'Ace': 11}
    
→ Ссылка