2015-04-23 2 views
1

У меня в настоящее время есть код для создания колоды карт, для перетасовки колоды и создания руки из этой колоды.«Pop index out the range» для колоды карт

from random import randint 

def make_deck(): 
    deck = [] 
    for suit in suits: 
     for rank in ranks: 
      deck.append((suit,rank)) 
    return deck 

suits = ['spades','hearts','diamonds','clubs'] 
ranks = ['ace','two','three','four','five','six','seven','eight','nine','ten','jack','queen','king'] 

deck = make_deck() #list of cards 

def shuffle(deck): 
    for k in range(100): # do it 100 times 
     card = deck.pop(randint(0,51)) 
     deck.append(card) 

def make_hand(): 
    hand = [] 
    for k in range(2): 
     card = deck.pop(randint(0,51)) 
     hand.append(card) 
    return hand 

hand = make_hand() 

Когда я запускаю программу, печать deck даст мне список карт, как мне нравится, и тогда, когда я пытаюсь тасует колоду, я получаю ошибку о том, что индекс популярности находится вне диапазона. Не совсем уверен, почему он окажется вне индекса, так как диапазон (0,51) представляет все 52 карты колоды.

Такая же ошибка возникает при попытке использовать функцию make_hand(), хотя и не всегда. Я неправильно использую метод pop? Что мне нужно изменить, чтобы работала функция shuffle, и hand всегда будет возвращать две разные карты из колоды?

+0

Как еще один ответ указывает, что вы не добавляете карты после того, как делаете руку, я предполагаю, что это преднамеренное поведение, но вы забываете перестроить колоду, прежде чем перетасовывать карты? Это поможет показать поток того, как их называют. – SuperBiasedMan

+0

Вы уверены, что у вашей колоды действительно есть 52 карты? (Попробуйте: напечатайте len (колода) после вызова make_deck().) Проблема с форматированием в вашем коде - две циклы «for» не работают, как показано из-за отступа. Интересно, возвращаетесь ли вы с неправильного места. (Когда я исправляю отступы второго «за» и запускаю его сам, я не получаю ошибок.) –

+0

О, ничего себе. У колоды только 50 карт. Теперь я еще более смущен! (Кроме того, отступы верны сами по себе, я просто не форматировал их правильно, когда я копировал их на SO.) –

ответ

2

Это безопаснее, чтобы написать это как

card = deck.pop(randint(0,len(deck)-1)) 

Хотя это быстрее, если вы сохраните это значение где-то.

Но это также указывает на проблему, с которой сталкивается ваша колода. Правильно ли вы настроили петли в создании колоды? Возможно, вы создаете менее 52 карт, поэтому, когда вы генерируете целое число на верхнем конце, вы получаете эту ошибку. Это также кажется вероятным, если это случается иногда в make_hand (где вы повторяете дважды) и постоянно в случайном порядке (где вы повторяете 100 раз).

Если вы намерены перетасовать карты после того, как раздались руки, вам определенно нужно использовать len() или отслеживать размер колоды каким-либо другим способом. И даже в функции make_hand вы выталкиваете одну карту, а затем все еще пытаетесь сделать из списка размером 52, даже если вы вытащили карту.

+0

Хм, я думаю, что я исправил проблему с make_hand, теперь я вижу, почему может быть случай, когда индекс слишком высок, если карта вынимается из колоды с первой итерации (т.е. осталось всего 51 карта после первого поп). Из того, что я вижу, петли for в 'make_deck()' правы - просто создавая список комбинаций костюмов и рангов, 4 костюма и 13 рангов, поэтому 52 комбинации. –

+0

В каком порядке вызывается функция? Возможно, вы не полностью учитываете изменение колоды. – SuperBiasedMan

+0

Порядок функций - 'make_deck()', а затем 'shuffle (deck)'. Это возвращает ошибку индекса pop. 'Shuffle (deck)' должен находиться в зоне действия, потому что при создании колода имеет 52 карты. –

3

pop мутирует список, удаляя объект из списка. Таким образом, длина списка станет меньше, чем 52, и в итоге будет выведена ошибка. Вместо 51 используйте длину списка каждый раз len(deck).

Для перетасовки, вы могли бы также использовал функцию shuffle из библиотеки random:

from random import shuffle 
## later in the code 
shuffle(deck) 
+0

, но OP добавляет карту обратно в колоду прямо на самой следующей строке 'shuffle' – Alik

+0

Нет, он не работает в' make_hand'. – nikaltipar

+0

Зачем это произошло? – nikaltipar

1

В make_hand вы берете 2 карты из колоды. Первый из них всегда будет успешным, но второй должен работать с колодой, содержащей только 51 карточку, в то время как все еще есть шанс на 1 из 52, чтобы попытаться сделать pop(52), что не удастся.

Я не могу воспроизвести ту же ошибку с помощью функции shuffle, если только я не передам ей колоду, которая была использована в make_hand, поэтому я предполагаю, что это то, что вы сделали.

Просто убедитесь, что в обеих функциях вы можете использовать randint(0, len(deck)-1).

Смежные вопросы