2017-06-19 102 views
0

我目前正试图编程一个数学卡技巧,它会询问用户他们的随机卡是什么桩。但是,第二次运行('技巧阶段'必须发生3次工作的诀窍)列表索引超出范围。我不确定问题出在哪里,并且会附上当前版本,以便您可以尝试运行以查看更清楚的内容。谢谢!列表失败,第二次运行

import random 

def makedeck(): 
    listy = [] 
    cardsindeck = 0 
    while cardsindeck != 21: 
    suit = random.randint(1,4) 
    if suit == 1: 
     suit = "D" 
    elif suit == 2: 
     suit = "H" 
    elif suit == 3: 
     suit = "S" 
    else: 
     suit = "C" 
    cardtype = random.randint(1,13) 
    if cardtype == 1: 
     card = "A" 
    elif cardtype == 2: 
     card = "2" 
    elif cardtype == 3: 
     card = "3" 
    elif cardtype == 4: 
     card = "4" 
    elif cardtype == 5: 
     card = "5" 
    elif cardtype == 6: 
     card = "6" 
    elif cardtype == 7: 
     card = "7" 
    elif cardtype == 8: 
     card = "8" 
    elif cardtype == 9: 
     card = "9" 
    elif cardtype == 10: 
     card = "10" 
    elif cardtype == 11: 
     card = "J" 
    elif cardtype == 12: 
     card = "Q" 
    else: 
     card = "K" 
    cardandsuit = (card + suit) 
    if cardandsuit not in listy: 
     listy.append(cardandsuit) 
     cardsindeck = cardsindeck + 1 
    return listy 

def dealdeck(listy): 
    list1 = [] 
    list2 = [] 
    list3 = [] 
    for i in range(len(listy)): 
    if i % 3 == 0: 
     list1.append(listy[i]) 
    elif i % 3 == 1: 
     list2.append(listy[i]) 
    else: 
     list3.append(listy[i]) 
    return[list1, list2, list3] 

def makepiles(pile1,pile2,pile3): 
    print("Pile 1\t\tPile 2\t\t Pile 3\t\t") 
    for i in range(7): 
    print(pile1[i],"\t\t",pile2[i],"\t\t",pile3[i],"\t\t") 

def usercardpile(): 
    userinput = input("What pile is your card in?") 
    if userinput == "1" or userinput.title() == "One": 
    return 1 
    elif userinput == "2" or userinput.title() == "Two": 
    return 2 
    elif userinput == "3" or userinput.title() == "Three": 
    return 3 
    else: 
    print("Please only write 1, 2 or 3") 
    return usercardpile() 


listy = makedeck() 
pile1, pile2, pile3 = dealdeck(listy) 
for i in range(1,4): 
    newlisty = makepiles(pile1,pile2,pile3) 
    userspile = usercardpile() 
    if userspile == 1: 
    newlisty = (pile2,pile1,pile3) 
    elif userspile == 2: 
    newlisty = (pile1,pile2,pile3) 
    else: 
    newlisty = (pile1,pile3,pile2) 
    pile1, pile2, pile3 = dealdeck(newlisty) 

print("Your card is",newlisty[10]) 
+2

考虑保持cardtype到卡的映射,所以你不需要在你的代码中写入'if's墙。 –

+0

我很新,所以我不太明白。你能解释一下吗? –

回答

1

的一个问题是这行代码:

newlisty = makepiles(pile1, pile2, pile3) 

你希望makepiles回到3所列出,而返回None(没有明确的项目返回)。

我想如果你从这个函数返回堆,它会工作。

的另一件事是,你正在做这件事:

newlisty = (pileX, pileY, pileZ) 

这将创建列表的一个元组,你会遍历整个列表,而不是单独的卡。我相信你想

newlisty = pile1 + pile3 + pile2` 

这将通过线性组合较小的桩创建一个21个元素的复合列表。


其他评论:

考虑存储dict。你decktype和卡类型。这样,您可以快速查找并生成桩,而无需编写一长串if语句。例如:

可以减少

cardtype = random.randint(1,13) 
if cardtype == 1: 
    card = "A" 
elif cardtype == 2: 
    card = "2" 
elif cardtype == 3: 
    card = "3" 
elif cardtype == 4: 
    card = "4" 
elif cardtype == 5: 
    card = "5" 
elif cardtype == 6: 
    card = "6" 
elif cardtype == 7: 
    card = "7" 
elif cardtype == 8: 
    card = "8" 
elif cardtype == 9: 
    card = "9" 
elif cardtype == 10: 
    card = "10" 
elif cardtype == 11: 
    card = "J" 
elif cardtype == 12: 
    card = "Q" 
else: 
    card = "K" 

要...

cardtype_lookup = { 1 : 'A', 2 : '2', 3 : '3', .... 12 : 'K' } 

card = cardtype_lookup[random.randint(1, 13)] 

...等等。

+0

非常感谢你!真的帮助我解决了这个问题:D我一定会在将来使用有关查找的建议:) –

+0

还有一个改进:不是选择一张随机卡片,而是检查它是否已经在卡组中,生成一个包含所有牌的牌组,然后使用'random.shuffle'将其洗牌。 –

+1

@Błotosmętek哦,好主意。 '从itertools导入产品;从随机进口洗牌; cards([''.join(x)for x in list(product(list('DHSC'),list('A123456789JQK')+ ['10']))];洗牌(卡);卡片[:21]' –

0

我认为除了最终的迭代之外,您的代码还是会遇到一些问题。以下是一些建议以及我认为能够达到您的目的的评论。

from random import shuffle 

# Function for generating 21 random cards 
def makedeck(): 

    # Create 52 cards by suit and cardtype 
    listy = [card + suit for card in ['A','2','3','4','5','6','7','8','9','10','J','Q','K'] for suit in ['D','H','S','C']] 

    # Shuffle the list 
    shuffle(listy) 

    # Choose only the first 21 items of that list 
    listy = listy[:21] 

    return listy 

# Function for dividing 21-card deck into 3 equally-sized piles 
def dealdeck(listy): 

    # Iterate over listy, stepping by 3, starting with the first, second, and third item 
    list1 = listy[::3] 
    list2 = listy[1::3] 
    list3 = listy[2::3] 

    # Return the three lists as three items to correspond to the three piles of the call 
    return list1, list2, list3 

# This works 
def makepiles(pile1,pile2,pile3): 
    print("Pile 1\t\tPile 2\t\t Pile 3\t\t") 
    for i in range(7): 
     print(pile1[i],"\t\t",pile2[i],"\t\t",pile3[i],"\t\t") 

# This works 
def usercardpile(): 
    userinput = input("What pile is your card in?") 
    if userinput == "1" or userinput.title() == "One": 
     return 1 
    elif userinput == "2" or userinput.title() == "Two": 
     return 2 
    elif userinput == "3" or userinput.title() == "Three": 
     return 3 
    else: 
     print("Please only write 1, 2 or 3") 
     return usercardpile() 

listy = makedeck() 
pile1, pile2, pile3 = dealdeck(listy) 
for i in range(1,4): 
    # Because this function does not return anything, it should be run on its own, and not assigned to a variable 
    makepiles(pile1,pile2,pile3) 

    userspile = usercardpile() 

    # Now you want to re-order the piles based on user input. Because these are lists, you can simply add them together in a new order to create a newly arranged list 
    if userspile == 1: 
     newlisty = pile2 + pile1 + pile3 
    elif userspile == 2: 
     newlisty = pile1 + pile2 + pile3 
    else: 
     newlisty = pile1 + pile3 + pile2 

    # Now you create new piles based on the re-sorted list and re-iterate 
    pile1, pile2, pile3 = dealdeck(newlisty) 

# Uses .format method instead 
print("Your card is {}".format(newlisty[10]))