Python бросок кости - PullRequest
       3

Python бросок кости

0 голосов
/ 13 июля 2020

Итак, для частного проекта я хочу оцифровать бросок нескольких разных игральных костей. Пока мой код запрашивает ввод, сколько и какие кости брошено, и выводит результат. Пока у меня есть следующее:

import dice

die = input("Roll the dice: ")

if die == "d4":
    dice.d4()
elif die == "d6":
    dice.d6()

, тогда как модуль кости содержит

import random

def d4():
    n = int(input())
    x = 0
    d4=[1, 2, 3, 4]
    while x < n: 
        print(random.choice(d4))
        x = x + 1

def d6():
    n = int(input())
    x = 0
    d6=[1, 2, 3, 4, 5, 6]
    while x < n: 
        print(random.choice(d6))
        x = x + 1

и так далее. Проверка if-elif для определения типа игральных костей кажется работоспособной, но несколько неуклюжей. Теперь к моему вопросу: есть ли более элегантный способ проверить количество и тип игральных костей? Например, я могу ввести 3d6, и скрипт вычислит 3 раза d6-throw?

Ответы [ 2 ]

2 голосов
/ 13 июля 2020

Есть ли более элегантный способ проверить количество и тип игральных костей?

Вы можете использовать регулярное выражение для синтаксического анализа (\d+)d(\d+), чтобы извлечь X и Y из XdY . Или даже просто разделите на "d", поскольку формат ввода строго <numbers>d<numbers>, что означает, что разделение не является неоднозначным.

Отсюда вы можете использовать getattr, чтобы получить соответствующий метод из модуля игральных костей, хотя в действительности модуль игральных костей бесполезен: dX это просто random.randint(1, X). Таким образом, вы можете просто иметь что-то вроде:

def roll(spec):
    rolls, dice = map(int, spec.split('d'))
    return [
        random.randint(1, dice)
        for _ in range(rolls)
    ]

И не иметь каких-либо ограничений в отношении «формы» игральных костей, которые вы хотите поддерживать, это нормально для любых граней, считающихся от 1 до практически бесконечность.

Между прочим, это можно изменить с помощью random.choices и явного range. Считаете ли вы его более простым или нет - дело вкуса:

def roll(spec):
    rolls, dice = map(int, spec.split('d'))
    return random.choices(range(1, dice+1), k=rolls)

У него менее широкая совместимость (варианты были добавлены в python 3.6), но его довольно легко расширить для поддержки, например, взвешенных игральных костей или специальные кубики, на которых дублируются некоторые грани (хотя, очевидно, последнее может поддерживаться путем простого переназначения значений из обычных кубиков).

0 голосов
/ 13 июля 2020

Самый «профессиональный» способ сделать это с помощью Regex ( читайте о регулярных выражениях здесь ).

Для вашего ввода шаблон ([0-9]*)(d[46]) соответствует двум группам.

Для ввода 3d6 он будет соответствовать ('3', 'd6').

Кроме того, вы используете random.choice в списке для случайных чисел от 1 до 6, вы можете использовать для d6, например, random.randint(1, 6) вместо random.choice, он вернет случайное число от 1 до 6.

...