【python3】不明所以的out of range

是这样的,我刚学 python3,在写一个 21 点小游戏,其中涉及到了发牌这个流程,于是我把所有牌都放进了 list
里,然后写一个函数用于发牌。函数的流程是首先随机从 list 里选中一张牌,然后把这个被选中的牌从 list 内del 掉,然后把选中的牌 return 出去,在外面放进玩家的牌组里。

下面是我的代码。系统会报错说 index 是 out of range 的,没想明白为啥。我感觉我写的 randint 没有超出范围呀。

求大大解答,谢谢!

#牌组
cards = [1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13]

#发牌
def randcard():
    index = random.randint(0, len(cards))
    del cards[index]
    if len(cards) == 0:
        print('Game over! No more cards now!')
        return game()
    else:
        return cards[index]
阅读 3.9k
4 个回答

详细解释请看注解。

#牌组
cards = [1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13]

#发牌
def randcard():
   if len(cards) !=0:
        index = random.randint(0, len(cards)-1) # 列表的索引应该是长度减 1
        randcard = cards[index] # 拷贝一下发出的牌,防止删除元素后,出现索引超出范围。
        del cards[index] # 此处删除了列表中的元素。
        return randcard
   else: 
        print('Game over! No more cards now!')
        return game()   
    

我觉得虽然其他答案也说明了索引或循环list的一些注意事项,
但是他们都没说到另一个关键点,程序逻辑是有问题的:

你们的代码是先发牌,然后判断是否没有牌了。
这种情况必然导致了没牌时,却要发第一张票(索引为随机值0)引发的错误。

正确的逻辑:
开始
判断牌堆是否为空:
是:结束,返回
否:随机选牌,移出牌堆,返回移出的牌。

def randcard():
    length = len(cards)
    if length == 0:
        print('Game over! No more cards now!')
        return
    idx = random.randint(0, length-1)
    card = cards.pop(idx)
    return card

你可以看看card.pop(index)这个方法,比你的简单粗暴。而且你这种写法,我不用试就知道有问题。

原因是在删除list中的元素后,list的实际长度变小了,但是循环次数没有减少,依然按照原来list的长度进行遍历,所以会造成索引溢出

关于list的删除操作推荐这篇文章https://www.cnblogs.com/banan...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题