python中的while循环中randrange()的空范围

时间:2018-11-04 08:21:58

标签: python python-3.x

在经历while循环后,从函数获取随机整数一直存在问题。该功能的目的是洗牌:

def shuffling(maindeck, shuffle_steps):
random.seed()
# sets a number of steps and creates a new array to be returned
steps = 0
shuffler = maindeck

while steps < shuffle_steps:
    firstR = random.randrange(len(maindeck) - 1)
    secondR = random.randrange(len(maindeck) - 1)

    shuffler[firstR], shuffler[secondR] = shuffler[secondR], shuffler[firstR]

    steps +=1

return shuffler

这是使用该功能的代码:

from deck import *
from shuffle import shuffling
gameState = True


while gameState:
    input("Welcome to War! Press any key to continue... \n")

    game_deck = shuffling(total_deck, 500)

    while gameState and len(game_deck) > 1:
        print("Both players draw a card...")

        playerCard = game_deck.pop(0)
        opponentCard = game_deck.pop(0)

        # some code

        keep_playing = input("Play again? (y/n) \n")
        if keep_playing is not ('y' or 'Y'):
           gameState = False

gameState = False

if len(game_deck) < 2:
    print("No cards left!")
    keepPlaying = input("Play again? (y/n) \n")
    if keepPlaying is ('y' or 'Y'):
        gameState = True

其中total_deck是来自文件deck.py的数组

这段代码在while循环的第一次迭代中运行良好,但是当循环迭代时,我得到了错误:

 ValueError: empty range for randrange()

并且在

时发生错误
random.randrange(len(Maindeck) - 1) 

开始被称为

len(Maindeck) - 1 

现在得出等于或小于0的数字吗?为什么是这样?

2 个答案:

答案 0 :(得分:1)

选项:

  • 如果列表中有一组卡,并且想要重新整理整个序列,只需使用random.shuffle(sequence)进行就地改组。

  • 如果要获取随机组合的副本,请使用random.sample()并将长度设置为序列的长度。


此行:

shuffler = maindeck

假设maindeck属于某种可变列表数据结构,shuffler引用的数据与maindeck相同-您正在伪装maindeck并将其返回-再往下,您正在操纵它。您可以使用random.sample()来返回主甲板的改组副本。

random.seed()设置生成您的随机性的Mersenne_Twister的开始内部状态-如果需要,可以设置一次,但不必每次遍历甲板时都设置一次。 Seeding具有固定值的随机数将导致相同的随机数,因为您要使用相同的随机运算,因为每个随机运算都会更改内部状态-不需要任何种子就可以使用它,默认情况下会在源中完成:请参见Python's random: What happens if I don't use seed(someValue)?

您的代码应使用random.sample(maindeck,k=len(maindeck))


代码:

import random
random.seed(42) # generate same states if same operations are used 

# https://en.wikipedia.org/wiki/Standard_52-card_deck
ranks = ["ace"] + [str(c) for c in range(2,11)] + ["jack", "queen", "king"]
colors = ["clubs","diamonds","hearts","spades"]

def generate_52_card_deck():
    """Returns a new deck of cards. Each card is a tuple of (rank,color)."""
    return [ (r,c) for c in colors for r in ranks  ]

deck = generate_52_card_deck()    
print(deck)

# inplace
random.shuffle(deck)
print(deck)

new_deck = random.sample(deck,k=52)
print("sampled deck:  ", new_deck[:10])
print("original deck: ", deck[::5])

输出:

# after generation (shortened)
[('ace', 'clubs'), ('2', 'clubs'), ('3', 'clubs'), ('4', 'clubs'), 
 ('5', 'clubs'), ('6', 'clubs'), ('7', 'clubs'), ('8', 'clubs'), 
 ('9', 'clubs'), ('10', 'clubs'), ('jack', 'clubs'), ('queen', 'clubs'),
 ('king', 'clubs'), 
 ('ace', 'diamonds'), ('2', 'diamonds'), ('3', 'diamonds'), ('4', 'diamonds'), 
 ('5', 'diamonds'), ('6', 'diamonds'), ('7', 'diamonds'),  ... , 
 ('jack', 'spades'), ('queen', 'spades'), ('king', 'spades')]


# after shuffling once (shortened)
[('10', 'clubs'), ('jack', 'diamonds'), ('king', 'diamonds'), ('4', 'clubs'),
 ('9', 'diamonds'), ('king', 'hearts'), ('4', 'diamonds'), ('ace', 'spades'), 
 ('7', 'diamonds'), ('queen', 'clubs'), ('8', 'spades'), 
 ('queen', 'diamonds'), ('8', 'hearts'), ('4', 'hearts'), ..., 
 ('9', 'spades'), ('2', 'clubs'), ('8', 'clubs'), ('2', 'spades')]

# first 10 cards ...
sampled deck:   [('4', 'spades'), ('king', 'hearts'), ('ace', 'diamonds'), 
                 ('jack', 'clubs'), ('queen', 'hearts'), ('2', 'hearts'),
                 ('6', 'diamonds'), ('3', 'spades'), ('8', 'hearts'), 
                 ('9', 'diamonds')]

# first 10 cards
original deck:  [('10', 'clubs'), ('jack', 'diamonds'), ('king', 'diamonds'), 
                 ('4', 'clubs'), ('9', 'diamonds'), ('king', 'hearts'), 
                 ('4', 'diamonds'), ('ace', 'spades'), ('7', 'diamonds'), 
                 ('queen', 'clubs')]

如果您需要纸牌价值,请使用:

def get_base_card_value(c):
    # ace == 11 not done here
    v = {"ace":1 ,"jack":10, "queen":10, "king":10}
    return v.get(c[0]) or int(c[0])

答案 1 :(得分:1)

啊!我看到了问题!您的游戏“用完了”主牌组,因为shuffling()函数置换并返回了 the 原始牌组:

shuffler = maindeck

不会创建主卡座的副本。因此

game_deck.pop(0)

也从主甲板上拿卡。

修复:复制主卡座的深层副本并使用它(在shuffling()中):

import copy
...
shuffler = copy.deepcopy(maindeck)

瞧!每个游戏都有一个全新的游戏甲板。