Я только что закончил изучение основ Python в CS50 и сейчас пытаюсь создать небольшую игровую программу для практики. На полпути я столкнулся с потенциальной проблемой.
Подводя итог игры, она выглядит так:
Пример:
User's input - 1,2,3,4,5
Possible patterns - a,a+1,a+2,a+3,a+4 1 point
- a,a+2,a+4,a+6,a+8 2 points
- a,a+1,a+3,a+5,a+7 3 points
Таким образом, в этом случае пользователь получает 1 балл.
Моя текущая проблема заключается в том, что я пытаюсь создать много разных шаблонов (например, 20), но на данный момент я знаю только один способ - использовать оператор if для каждого шаблона, например:
if .....
if .....
if .....
Делать это для каждого шаблона кажется неправильным. Я пытался найти способы уменьшить количество операторов if, но такие методы, как использование таблицы переходов (словарей), похоже, здесь не работают. Заранее спасибо.
а — наименьшее число из пяти чисел, которые вводит пользователь.
Для такого сценария на большинстве языков можно использовать «Переключить (совпадение)» или «Карта (данные формы объекта)».
пример:
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case _:
return "Something's wrong with the internet"
Как это можно использовать для задаваемого вопроса?
@user19077881 user19077881 Если вы этого не понимаете, не используйте его.
Вы можете поместить свои шаблоны и оценки в списки. Например, сохраните шаблоны в виде лямбда-выражений, которые можно вычислить на основе входных данных a
.
Затем вы можете перебирать шаблоны, оценивать их и сравнивать результат с пользовательским вводом.
user_input = [12, 14, 16, 18, 20]
a = user_input[0]
# define your patterns and their scores
patterns = [
lambda x: [x, x + 1, x + 2, x + 3, x + 4],
lambda x: [x, x + 2, x + 4, x + 6, x + 8],
lambda x: [x, x + 3, x + 6, x + 9, x + 12],
]
scores = [1, 2, 3]
def compare_list(list1, list2):
return list1 == list2
score = 0
for idx, pattern in enumerate(patterns):
if compare_list(user_input, pattern(a)):
print("Pattern found")
score = scores[idx]
break
print(f"Score: {score}")
Возможно, вам придется отсортировать списки перед проверкой равенства, в зависимости от шаблонов, которые вы хотите сопоставить.
Функциональность match
/case
была добавлена в Python 3.10, поэтому, если ваша версия ограничена и, следовательно, ограничена операторами if
, возможно, программа проверки вызовет другую функцию, чтобы вы могли вернуться, если оператор if
совпадает (поэтому вы ограничиваете количество операторов if
). Затем добавьте математику в свои утверждения if
, чтобы они охватывали несколько сценариев.
Пример:
<-SNIP->
def check_value(a, value):
checkvalue = value - a
# sort the if statements from highest to lowest return
if checkvalue%2 == 1:
return 3
if checkvalue%2 == 0:
return 2
if checkvalue <= 4:
return 1
# etc
return 0
# Call the checker in your other method:
# a is target value
# value is under input value
win_result = check_value(a, value)
<-SNIP->
Обновлено: теперь я вижу, что для каждой разницы может быть несколько результатов выигрыша, что делает if
или match
с return
бесполезным решением. В этом случае вы можете использовать dict
для хранения пар разница/выигрыш. Примечание. Вы можете использовать целочисленные ключи для словаря, если вы определяете dict
с помощью {}
, но не с помощью dict()
.
Пример:
<-SNIP->
result_dict = {
1 : 4, # 1+3
2 : 3, # 1+2
3 : 4, # 1+3
4 : 3, # 1+3
5 : 3, # 3
# and so on
}
win_result = result_dict[user_value-target_value]
<-SNIP->
Вы можете использовать список или словарь для хранения кортежа (distance_between_element, точки) Рассчитайте расстояние между элементами списка.
input = [1,2,3,4,5]
result = []
for i in range(input)-1:
result.append(list[i+1] -list[i])
Теперь вам нужен дикт. с ключом [1,1,1,1] и значением 1 это будет a, a+1, a+2, a+3, a+4 и получит 1 балл.
Если пользователи введут 1 2 3 4 5
, то это будет строка, поэтому для этого ответа потребуется преобразование в список целых чисел. Также лучше не дублировать имя input
, которое используется в Python для определенной цели.
def pattern1(numbers):
# Check if numbers match the pattern a, a+1, a+2, a+3, a+4
return all(numbers[i] == numbers[0] + i for i in range(len(numbers)))
def pattern2(numbers):
# Check if numbers match the pattern a, a+2, a+4, a+6, a+8
return all(numbers[i] == numbers[0] + 2*i for i in range(len(numbers)))
def pattern3(numbers):
# Check if numbers match the pattern a, a+1, a+3, a+5, a+7
return all(numbers[i] == numbers[0] + sum(range(i+1)) for i in range(len(numbers)))
# Dictionary to store patterns and their scores
patterns = {
pattern1: 1,
pattern2: 2,
pattern3: 3
}
def evaluate_input(user_input):
# Convert the user input string to a list of integers
numbers = list(map(int, user_input.split(',')))
# Initialize score
score = 0
# Check each pattern
for pattern, points in patterns.items():
if pattern(numbers):
score += points
return score
# Main program
user_input = input("Enter 5 numbers separated by commas (e.g., 1,2,3,4,5): ")
score = evaluate_input(user_input)
print(f"Your score: {score}")
Объяснение:
Такой подход делает ваш код более организованным и масштабируемым, упрощая добавление новых шаблонов или изменений в оценку. Это снижает сложность и повышает удобство сопровождения за счет инкапсуляции логики шаблонов в отдельные функции.
Предполагая, что ваша версия Python допускает сопоставление регистров (и что каждая запись соответствует вашим примерам последовательного увеличения/уменьшения первого числа), вы можете преобразовать входные данные в шаблон и сопоставить их для получения оценки, используя приведенный ниже код. Если механизмы входа могут иметь более сложный вариант, тогда преобразование необходимо будет соответствующим образом изменить.
user_str = input('enter five numbers ')
def func(entry):
comp = []
vals = entry.split()
for num in vals:
comp.append(int(num) - int(vals[0]))
match comp[1:]: # compare all but first element
case [1, 2, 3, 4]: points = 1
case [2, 4, 6, 8]: points = 2
case [1, 3, 4, 7]: points = 3
case _: points = 0 # catch all non-matching patterns
return points
print(func(user_str))
поэтому, если пользователь вводит 1 2 3 4 5
, код выдает 1
Приятно видеть, как пользователь вводит все числа одновременно! Я думаю, что некоторая комбинация вашего и моего ответа была бы идеальной. Таким образом, метод будет возвращаться для каждого совпадения вместо установки возвращаемого значения и возврата в конце метода.
Это будет проще и понятнее. Идея здесь состоит в том, чтобы узнать hcf. hcf — это не что иное, как самое большое число, на которое можно разделить все элементы входных данных. Если после нахождения hcf все элементы входных данных разделить на hcf, вы напрямую получите шаблон.
# Get comma separated input
usr_entry = input()
# convert input into list
usr_entry = usr_entry.split(',')
#convert each element into int
usr_entry = [int(float(x)) for x in usr_entry]
# create a dict keys being pattern with a = 1
dct = {(1, 2, 3, 4, 5) : 1,
(1, 3, 5, 7, 9) : 2,
(1, 2, 4, 6, 8) : 3}
# find the smallest number of the user input
small = min(usr_entry)
if tuple(usr_entry) not in dct.keys():
# Iterate from small to 1 in reverse step being -1
for i in range(small, 0, -1):
if i != 1:
#find out hcf and break
if all(x % i == 0 for x in usr_entry):
hcf = i; break
else: hcf = 1
# Divide all the user input by hcf
usr_entry = [x/hcf for x in usr_entry]
# convert the usr_entry to tuple
usr_entry = tuple(usr_entry)
print(dct[usr_entry])
В вашем примере что такое
a
?