jeudi 3 décembre 2015

ValueError in Python simulation for card game War

I am trying to write a Python script for the card game "War" using OOP. http://ift.tt/1nX1qoy

I get an error below, and I don't know how to deal with it. There's obviously some problem between how I define the card suit and the card rank.

Code testing the main() function piece by piece, I can instantiate 'player objects' jack and jill. The error is at

jack.hand, jill.hand = Deck().deal_hands()

The ValueError I get in my IPython notebook is this:

   ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-54-99e9b8708bad> in <module>()
----> 1 jack.hand, jill.hand = Deck().deal_hands()

<ipython-input-50-9f961e6c68b0> in __init__(self)
      6         for suit in SUITS:
      7             for rank in RANKS:
----> 8                 card = Card(rank, suit)
      9                 self.cards.append(card)
     10 

<ipython-input-40-92debc7ca8b0> in __init__(self, suit, rank)
      8             self.suit = suit
      9 
---> 10         self.rank = int(rank)
     11 

ValueError: invalid literal for int() with base 10: 'Diamond'

Any help is appreciated. Here is my entire script:

#!/usr/bin/env python

from __future__ import (division, print_function, absolute_import)

import sys                 # used to exit program if infinite loop occurs
from random import shuffle # import shuffle function from random to shuffle deck

# define global variables
SUITS = ('Diamond', 'Heart', 'Club', 'Spade')
RANKS = tuple(range(2, 15))    # An ace is considered highest, with rank/order of 14


class Card:
    """Each card has a suit and rank/order. Only the rank/order directly determines game play."""

    def __init__(self, suit, rank):

        suits = ['Diamond', 'Heart', 'Club', 'Spade']

        if suit in suits:
            self.suit = suit

        self.rank = int(rank)

​class Deck:

    def __init__(self):
        self.cards = [] # cards list holds cards

        for suit in SUITS:
            for rank in RANKS:
                card = Card(rank, suit)
                self.cards.append(card)

        shuffle(self.cards) # use shuffle from 'random' module

    def deal_card(self):         # deal card from top of deck
        return self.cards.pop(0) # pop off top card

    def deal_hands(self):        # deal hands to two players
        player_A = []
        player_B = []
        players = [player_A, player_B]

        while self.cards:
            for hand in players:
                hand.append(self.deal_card())

        return player_A, player_B  # returns two values

class Player():

    def __init__(self, name):
        self.name = name
        self.hand = []

    def draw(self):   # pop off card from top of hand
        card = self.hand.pop(0)
        return card

    def pickup(self, card):  # pick up card, place on bottom of deck
        self.hand.append(card)


class War:

    def __init__(self, players, shuffle_winnings):
        self.round = 1 # begin with first round
        self.players = players
        self.winnings = []
        self.winner = None
        self.loser = None

        while self.players[0].hand and self.players[1].hand:
            self.winner = self.battle()

            if self.winner:
                self.loser = 0
            else:
                self.loser = 1

            self.winnings = [card for card_pairs in self.winnings for card in card_pairs]

            shuffle(self.winnings)  # shuffle the winnings; otherwise there's a probability that infinite loops arise 

            [self.players[self.winner].collect(card) for card in self.winnings] # winner collects 'winnings'

            self.winnings = []      # reset winnings list to empty for the next round of play

            if self.round == 10000: # exit program if play continues past 10,000 (which would be *highly* unlikely)
                sys.exit(0)

            self.round += 1         

    def battle(self, tie=False):

        """If tie, we use recursion to call function on itself"""

        def draw():
            # create list for the two cards in play
            cards = [self.players[0].draw(), self.players[1].draw()]
            return cards

        cards = draw() # draw cards; cards now in play

        if cards[0].rank != cards[1].rank:        # ranks unequal, therefore someone wins/loses
            if cards[0].rank >= cards[1].rank:
                winner = 0
            else:
                winner = 1

            # collect winnings
            self.winnings.append(cards)
            return winner

        else:                                    # ranks equal, therefore there's a tie
            self.winnings.append(cards)          # evenly ranked cards added to 'winnings' pile

            """Here, if there's a tie, three cards added to 'winnings' pile. 
               Players battle again. The winner receives 10 cards."""

            [self.winnings.append(draw()) for i in range(3)]

            winner = self.battle(tie=True)       # here another battle is played, until winner declared
            return winner




def main():

    # instantiate "player objects"
    jack = Player('Jack')
    jill = Player('Jill')

    # first deal out hands, 26 cards each
    jack.hand, jill.hand = Deck().deal_hands()

    players = [jack, jill] # list of "player objects" above

    # players battle war
    war = War(players)




Aucun commentaire:

Enregistrer un commentaire