I have no idea what went wrong with my most recent code, but I suspect it has something to do with the following so I'll start there. Did I do something wrong in this?

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','A','A','A','A','K','K','K','K','J','J','J','J','Q','Q','Q','Q']

import random
random.shuffle(cards)
h1=[]
for card in cards[1:7]:
    h1.append(card)
    cards.remove(card)

I changed my mind, I believe I may have found the real culprit

It seems the error is actually in here:

class Hand(object):
    def __init__(self,cards):
        self.cards=[cards]
        self.score=0
        self.len=len(self.cards)

    def check_match(self,card0):
        if card0 in self.cards:
            for card in self.cards:
                if card==card0:
                    self.cards.remove(card)
                    self.score+=1
        else:
            self.cards.append(card0)
            


    def decide(self,other_hand):
        print('\nYour Hand:',self.cards,'\n')
        choice=input('Which card would you like to ask your opponent for?: ')
        if choice not in self.cards:
            print('Oh shit')
            while choice not in self.cards:
                print('\nNot a valid choice\n')
                choice=input('Which card would you like to ask your opponent for?: ')
        elif choice in self.cards:
            other_hand.give(self, choice)



    def give(self,other_hand,card1):
        if card1 in self.cards:
            for card in self.cards:
                if card==card1:
                    other_hand.check_match(card)
                    try:
                        self.cards.remove(card)
                    except:
                        pass
        else:
            print('Go Fish')
        self.decide(self)

    def draw(self, other_hand):
        deck.draw_From(self)
        other_hand.decide(self)###
        


class AI(Hand):

    def __str__(self):
        print('AI HAND')
        
    def decide(self,other_hand):
        import random
        random.shuffle(self.cards)
        choice=self.cards[0]
        other_hand.give(self,choice)



class Deck(object):
    def __init__(self, cards):
        self.cards=[cards]
        self.len=len(self.cards)

    def draw_From(self, other_hand):
        draw_card=self.cards[0]
        other_hand.check_match(draw_card)
        self.cards.pop(0)



#main


        

cards=['2','2','2','2','3','3','3','3','4','4','4','4','5','5','5','5','6','6','6','6','7','7','7','7','7','8','8','8','8','9','9','9','9','J','J','J','J','Q','Q','Q','Q','K','K','K','K','A','A','A','A']


import random
random.shuffle(cards)
deck=Deck(cards[0])
cards.pop(0)
for card in cards:
    deck.cards.append(card)
    cards.remove(card)
print(deck.cards)

h1=deck.cards[1:7]
player=Hand(deck.cards[0])
deck.cards.pop(0)
print(player.score)
for card in h1:
    deck.cards.remove(card)
print(deck.cards)

for card in h1:
    player.check_match(card)
ai=AI(deck.cards[0])
deck.cards.pop(0)

h2=deck.cards[0:7]
for card in h2:
    ai.check_match(card)
    deck.cards.remove(card)

player.decide(ai)

I get an IndexError at line 58, meaning that the list self.cards is empty. This happens in a sequence of nested calls of give() and decide(). There should be a for loop somewhere. I don't like the self.decide(self) at line 42 in give(). Perhaps you should describe the intended progress of the game with pseudo code.

updated a bit, however there's still something wrong with ai.cards. On it's first round it claims ai.cards[0] index is out of range?

class Hand(object):
    def __init__(self,cards):
        self.cards=[cards]
        self.score=0
        self.len=len(self.cards)

    def check_match(self,card0):
        if card0 in self.cards:
            for card in self.cards:
                if card==card0:
                    self.cards.remove(card)
                    self.score+=1
        else:
            self.cards.append(card0)
            



    def decide(self,other_hand):
        print(self.len)
        if self.len<1:
            print('AI',ai.score,'Player',player.score)
        else:
            print('\nYour Hand:',self.cards,'\n')
            choice=input('Which card would you like to ask your opponent for?: ')
            if choice not in self.cards:
                while choice not in self.cards:
                    print('\nNot a valid choice\n')
                    choice=input('Which card would you like to ask your opponent for?: ')
            elif choice in self.cards:
                other_hand.give(self, choice)
                other_hand.decide(other_hand)



    def give(self,other_hand,card1):
        if card1 in self.cards:
            for card in self.cards:
                if card==card1:
                    other_hand.check_match(card)
                    #self.cards.remove(card)
        else:
            print('Go Fish')
            other_hand.draw(self)
            self.decide(ai)

    def draw(self, other_hand):
        deck.draw_From(self)
        other_hand.decide(ai)
        


class AI(Hand):

    def __str__(self):
        print('AI HAND')
        
    def decide(self,other_hand):
        import random
        random.shuffle(self.cards)
        choice=self.cards[0]
        other_hand.give(self,choice)

    def give(self,other_hand,card1):
        if card1 in self.cards:
            for card in self.cards:
                if card==card1:
                    other_hand.check_match(card)
##                    self.cards.remove(card)
        else:
            print('Go Fish')
            other_hand.draw(self)
            self.decide(player)





class Deck(object):
    def __init__(self, cards):
        self.cards=[cards]
        self.len=len(self.cards)

    def draw_From(self, other_hand):
        draw_card=self.cards[0]
        other_hand.check_match(draw_card)
        self.cards.pop(0)






#main


        

cards=['2','2','2','2','3','3','3','3','4','4','4','4','5','5','5','5','6','6','6','6','7','7','7','7','7','8','8','8','8','9','9','9','9','J','J','J','J','Q','Q','Q','Q','K','K','K','K','A','A','A','A']


import random
random.shuffle(cards)
deck=Deck(cards[0])
cards.pop(0)
for card in cards:
    deck.cards.append(card)
    cards.remove(card)
print(deck.cards)

h1=deck.cards[1:7]
player=Hand(deck.cards[0])
deck.cards.pop(0)
print(player.score)
for card in h1:
    deck.cards.remove(card)
print(deck.cards)

for card in h1:
    player.check_match(card)
ai=AI(deck.cards[0])
deck.cards.pop(0)

h2=deck.cards[0:7]
for card in h2:
    ai.check_match(card)
    deck.cards.remove(card)
while len(player.cards)>0 and len(ai.cards)>0:
    player.decide(ai)

You mean infinite recursion from line 42 until deck become empty in line 58?

Do loop in main program, do not put looping inside the class. Would be easier to advice if I would know which rules you are trying to apply.

fixed infinite loop @ line 42. Rules are simple: ask ai for card in your hand, if they have it the cards are tossed and your score goes up by 1 if not then you draw a card, if that's the card you need the cards are tossed and score goes up by 1, then the ai does the same and it goes back and forth until player or ai is out of cards at which point the scores are tallied.

a few of the print()'s are just me making sure everything is running okay. Also the hands should start out as a list of 5 cards

And the cards have no tens?

.. and also 5 sevens.

Better go back few steps, you must test each new function before putting more, you could start from here and add logic (even maybe time for bed there in US)

(Please put your imports in beginning of the file, if you have not very good reason not to do so)

import random
from itertools import islice

class Hand(object):
    def __init__(self, deck, count=5):
        self.cards = deck.deal(count)
        self.score=0

    def add(self, card):
        self.cards.append(card)

    def take(self, card):
        """ Use exception handling to deal with cards run out """
        self.cards.remove(card)
        return card

    def __iter__(self):
        return iter(self.cards)
    
    def __str__(self):
        return "Score {score}, cards: {cards}".format(score=self.score, cards=', '.join(self))

class Deck(object):
    def __init__(self):
        deck = ['2','2','2','2',
                '3','3','3','3',
                '4','4','4','4',
                '5','5','5','5',
                '6','6','6','6',
                '7','7','7','7', '7',
                '8','8','8','8',
                '9','9','9','9',
                'J','J','J','J',
                'Q','Q','Q','Q',
                'K','K','K','K',
                'A','A','A','A']
        
        random.shuffle(deck)
        self.deck = iter(deck)
        self.len=len(deck)

    def deal(self, count=5):
        cards = [next(self.deck) for _ in range(count)]
        self.len -= count
        return cards

    def __iter__(self):
        return self.deck
    
    def __str__(self):
        return 'Deck with {len} cards.'.format(len=self.len)
#main      
deck=Deck()
print(deck)

h1=Hand(deck)
player=Hand(deck)

print(h1)
print(player)
print(deck)

print('Deck:', ', '.join(deck))

print
print(deck)

try:
    print('Take one card', h1.take('4'))
except ValueError:
    print('Card not in hand')
print('Hand is now', h1)
print('First cards in my hand are:', list(islice(h1, 2)))

With your rules, I would suggest a game logic such as

class OutOfCards(Exception):
    # raised by choice() or by deck.draw()
    pass

# initialize ai, player, deck
# the toss() method is supposed to return True or False

try:
    x, y = ai, player
    while True:
        x, y = y, x
        card = x.choice()
        if y.toss(card) or deck.draw() == card:
            x.toss(card)
            x.score += 1
except OutOfCards:
    tally_scores(player, ai)

Iterator of deck did not keep count upto date, fixed by loop and update:

from __future__ import print_function

import random
from itertools import islice

class Hand(object):
    def __init__(self, deck, count=5):
        self.cards = deck.deal(count)
        self.score=0

    def add(self, card):
        self.cards.append(card)

    def take(self, card):
        """ Use exception handling to deal with cards run out """
        self.cards.remove(card)
        return card

    def __iter__(self):
        return iter(self.cards)
    
    def __str__(self):
        return "Score {score}, cards: {cards}".format(score=self.score, cards=', '.join(self))

    #lazy little incorrect solution
    __repr__ = __str__

class Deck(object):
    def __init__(self):
        deck = ['2','2','2','2',
                '3','3','3','3',
                '4','4','4','4',
                '5','5','5','5',
                '6','6','6','6',
                '7','7','7','7', '7',
                '8','8','8','8',
                '9','9','9','9',
                'J','J','J','J',
                'Q','Q','Q','Q',
                'K','K','K','K',
                'A','A','A','A']
        
        random.shuffle(deck)
        self.deck = iter(deck)
        self.len=len(deck)

    def deal(self, count=5):
        cards = [next(self.deck) for _ in range(count)]
        self.len -= count
        return cards

    def __iter__(self):
        for card in self.deck:
            self.len -= 1
            yield card
    
    def __str__(self):
        return 'Deck with {len} cards.'.format(len=self.len)

    #lazy little incorrect solution
    def __repr__(self):
        return ', '.join(card for card in self.deck)


#main      
deck=Deck()
print(deck)

h1=Hand(deck)
player=Hand(deck)

print(h1)
print(player)
print(deck)

print('Deck:', ', '.join(deck))

print
print(deck)

try:
    print('Take one card', h1.take('4'))
except ValueError:
    print('Card not in hand')
print('Hand is now', h1)
print('First cards in my hand are:', list(islice(h1, 2)))

why is self.deck=iter(self.deck) necessary?

do you think this could work for deal?

def deal(self, count=5):
        hands= player, ai
        for unit in count:
            for hand in hands:
                for card in self.cards:
                    if card not in hand:
                        hand.cards.append[card]
                        self.deck.remove(card)
                        self.len-=1
                        hand.len+=1
                    else:
                        for crd in hand.cards:
                            if crd==card:
                                hand.cards.remove(crd)
                                hand.score+=1
                                self.deck.remove(card)

:-/ I can't believe I'm still having issues like this.

Four nested fors should normally not be needed. Which class this belongs to (Game class?) and why you are refering global instance names from class? I think you should start using classes as help tool and leave main routine as normal function. Inside class you are generally refering things through instance variables. To disallow global references you could separate the class definitions to separate modules. More than one class in module is ok in Python.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.