我正在尝试使用python创建字符选择CLI。
我想显示用户的“当前角色选择方”,以便他们可以看到他们已经选择的人。用户不能两次选择相同的字符。用户必须有4个字符才能继续
我创建了以下代码(我确实称呼它不用担心!):
def ChooseCharacters():
CharList=[]
CurrentParty=[]
print("Select up to 4 explorers!")
while len(CharList)!=4:
if len(CharList)!=4:
if len(CharList)==0:
pass
else:
for CharID in list(set(CharList)):
print(CharList)
SQL=("SELECT firstname,secondname FROM characters WHERE CharID=%s")
mycursor.execute(SQL,(CharID,))
myresult=mycursor.fetchone()
Name=(myresult[0]+" "+myresult[1])
CurrentParty= list(set(CurrentParty))
CurrentParty.append(Name)
print("Current Party: ",CurrentParty)
PrintChoice(CharList)
def PrintChoice(CharList):
mycursor.execute("SELECT * FROM characters")
myresults=mycursor.fetchall()
Num=0
for char in myresults:
Num = Num + 1
print(str(Num)+("."),char[1],char[2])
Choice=input("Select Character: ")
if Choice in CharList:
print("Character already selected!")
return
CharList.append(Choice)
print(CharList)
似乎第一个选择的字符在列表中重复,其余代码正常工作。
预期结果
Current Party: ['Sam Jordan']
Current Party: ['Sam Jordan','Olivia Cope']
Current Party: ['Sam Jordan','Olivia Cope','Dylan Nesbitt']
实际结果
Current Party: ['Sam Jordan']
Current Party: ['Olive Cope', 'Sam Jordan', 'Sam Jordan']
Current Party: ['Sam Jordan', 'Olive Cope', 'Dylan Nesbitt', 'Sam Jordan']
我无法确定第一个输入的第二次复制发生在哪里,因为第一个输入正确无误。
如果您需要查看数据库表,请询问。
答案 0 :(得分:1)
您当前的代码有点困难,因为它包含了非常不同类型的活动:从数据库读取,让用户以交互方式进行选择以及常规算法逻辑。此外,代码还依赖于通常最好避免的模式-即,将数据结构传递给其他函数,以便其他函数可以对其进行修改。编写获取数据并返回新数据的函数通常更为简单和明智。
我建议您将其重构以进行更清晰的分离,而不是困惑于如何解决当前代码。这是一个简单的例子:
import string
# A top-level function to orchestrate things.
def choose_characters():
chars = get_characters_from_db(12) # Read 12 from DB.
selected = select_items(chars, 4) # Select 4 of them.
print(selected)
# One or more functions to interact with the database.
# In this example we just return some mock data.
def get_characters_from_db(n):
return string.ascii_uppercase[0:n]
# A general function to have a user select N items.
def select_items(xs, n):
selected = []
print('Choices:')
for i, x in enumerate(xs):
print(i + 1, x)
print()
while len(selected) < n:
s = input('=> ')
try:
i = int(s) - 1
x = xs[i]
except Exception:
print('Invalid entry')
continue
if x in selected:
print('Already selected')
else:
selected.append(x)
print()
return selected
choose_characters()
答案 1 :(得分:0)
问题出在CurrentParty
和CharList
列表的处理上。在获取名称的for
循环的开头,CurrentParty
包含上次选择字符时添加的名称。由于调用CharList
,set
中元素的顺序可能在每次循环执行中发生变化,因此添加到CurrentParty
的姓氏可能已经存在。
一个简单的解决方案可能是在每次执行循环时重新初始化CurrentParty
,并删除CharList
不必要的设置。该功能的简化版本可能是:
def ChooseCharacters():
CharList = []
print("Select up to 4 explorers!")
while len(CharList) < 4:
PrintChoice(CharList)
CurrentParty = []
for CharID in CharList:
SQL = "SELECT firstname,secondname FROM characters WHERE CharID=%s"
mycursor.execute(SQL, (CharID,))
myresult = mycursor.fetchone()
Name = myresult[0] + " " + myresult[1]
CurrentParty.append(Name)
print("Current Party: ", CurrentParty)
print("Final Party: ", CurrentParty)
print()
正如用户FMc在其答案中观察到的那样,问题中的代码难以理解。这是代码的一个版本,该版本试图减少重复,对每个函数保持明确的职责并最大程度地减少对数据库的调用。为简单起见,假设mycursor
作为全局变量存在。
此代码是使用Python 3.7编写的;如果您使用的是Python的早期版本,请将all_chars
设为OrderedDict,以确保行为正确。
def main():
# Call this function to run the code.
all_chars = fetch_characters()
selected = select_characters(all_chars)
party_ids = map_selection_to_ids(selected, all_chars)
print_party(party_ids, all_chars)
# Do rest of the program.
return
def fetch_characters():
# Make a dictionary that maps database id to character name.
all_chars = {}
stmt = """SELECT CharID, firstname, secondname FROM characters;"""
mycursor.execute(stmt)
for id_, firstname, secondname in mycursor.fetchall():
all_chars[id_] = '{} {}'.format(firstname, secondname)
return all_chars
def select_characters(all_chars):
# Display the selection menu.
# Note the values that the user selects will not necessarily
# correspond to the database id.
selected = set()
while len(selected) < 4:
for idx, name in enumerate(all_chars.values(), start=1):
print('{}. {}'.format(idx, name))
print()
choice = input('Select Character: ')
if choice in selected:
print("Character already selected!")
continue
selected.add(choice)
return selected
def map_selection_to_ids(selected, all_chars):
# Given the values selected by the user, get the corresponding
# database id.
party_ids = []
char_ids = list(all_chars.keys())
for selection in selected:
adjusted = int(selection) - 1
party_ids.append(char_ids[adjusted])
return party_ids
def print_party(party_ids, all_chars):
names = []
for id_ in party_ids:
names.append(all_chars[id_])
print(', '.join(names))
return