I'm trying to create a game of Go Fish in Python. But I've stumbled onto a little problem that I can't seem to figure out how to deal with.

There is a human player (player 0) and three computer players (from 1-3). The human player goes first and chooses a target player. And then a card rank (for example, the player could target player two and choose jacks, then the computer would have to give the player all its jacks).

What I have so far is below but the problem I'm having is right at the bottom of the code. So far, the code generates a deck, creates hands for every player, and then shows the player his/her cards. Then the player is asked which computer player he/she wants to target as well as the rank of cards.

The problem I'm having is with the last set of lines (the def player_0_hitman) at the bottom of the code. Any help would be much appreciated. There are basically three issues I'm having problems with.

Basically, my code is ignoring the if's and else's. I don't get why. Everything appears to be positioned correctly, but for some odd reason, even after an if, the program also runs the else as well.

the "hit" is not being returned. Even though in the definition, I have the hit set to hit = hit - 1 for the last else, it still reruns the whole definition again as if it the hit was 1

I'm trying to use the count line to count how many cards are being transferred so the program will tell the player how many cards he gains when he gets a successful guess but I only get a statement saying I got 1 card each time no matter what (whether I get no cards or I get more than one).

I understand the basics of what I need to do but I can't seem to get a working code for this. I've tried changing the "for" to "if" but I get all sorts of errors so I don't think that will work. Then I tried converting "hit" into another code before entering the definition, changing it while inside, then converting it back before returning it but that also seems to do nothing, and I still get the same issues.

CODE:

import random

def SetDeck():
    suitList = ["s", "c", "d", "h"]
    rankList = ["a", "2", "3", "4", "5", "6", "7", "8", "9", "t", "j", "q", "k"]
    deck = []
    for suite in range(4):
        for rank in range(13):
            deck.append(rankList[rank]+suitList[suite])
    return deck

def Shuffle(deck):
    nCards = len(deck)
    for i in range(nCards):
        j = random.randint(i,nCards-1)
        deck[i], deck[j] = deck[j], deck[i]
    return deck

def GetTopCard(shuffledDeck):
    return shuffledDeck.pop(0)

def DealInitialCards(nPlayers,nCards,shuffledDeck):
    playersCards = [["" for j in range(nCards)] for i in range(nPlayers)]
    for j in range(nCards):
        for i in range(nPlayers):
            playersCards[i][j] = GetTopCard(shuffledDeck)
    return playersCards

def Sort(cards):
    rankString = "a23456789tjqk"
    swapped=True
    while swapped:
        swapped = False
        for i in range(len(cards)-1):
            if rankString.find(cards[i][0])>rankString.find(cards[i+1][0]):
                cards[i],cards[i+1]=cards[i+1],cards[i]
                swapped = True
    return


def ShowCards(player,cards):
    print("\n****************************************************")
    print("************Player "+str(player)+" has**************")
    print("****************************************************\n")
    for i in range(len(cards)):
        print(cards[i]),
    print("\n")
    return

def ShowMessage(msg):
    print("****************************************************")
    print(str(msg))
    print("****************************************************\n")
    return

def remove_suits(player):
    new_hand = []
    for card in pHands[player]:
        new_card = card[0]
        new_hand.append(new_card)
    return new_hand

def choosing_target():
    target_player = raw_input ("Who do you want to ask? (1-3)")
    while target_player.isdigit() == False or 1 > int(target_player) or 3 < int(target_player):
        print "Error: Must type a valid player id (from 1 to 3)"
        target_player = raw_input ("Who do you want to ask? (1-3)")
    target_player = int(target_player)
    return target_player

def target_rank():
    target_card = raw_input ("What rank are you seeking? (" + str(",".join(new_hand)) + ")")
    while target_card not in new_hand:
        print "Error: Must type one of the follow valid single character card ranks"
        print str(",".join(new_hand))
        target_card = raw_input ("What rank are you seeking? (" + str(",".join(new_hand)) + ")")
    return target_card

print("~"*70)
print("~"*25+"WELCOME TO GO FISH!"+"~"*26)
print("~"*70)

nPlayers = 4
nCards = 10
deck = SetDeck()
sDeck = Shuffle(deck[:])
pHands = DealInitialCards(nPlayers,nCards,sDeck)
Sort(pHands[0])
ShowCards(0,pHands[0])

hit = 1

while hit == 1 :
    ShowMessage("TURN: Player 0, its your turn.")
    target_player = choosing_target()
    new_hand = remove_suits(0)
    target_card = target_rank()
    ShowMessage("Target: Player " + str(target_player) + " is being targeted for the rank <" + str(target_card) + ">")
    temp_hit = player_0_hitman(hit)
    print "hit = " + str(hit)

def player_0_hitman(hit):
    for card in pHands[target_player]:
        if target_card[0] == card[0]:
            count = pHands[target_player].count(card)
            pHands[0].append(card)
            pHands[target_player].remove(card)
            ShowMessage("HIT: " + str(count) + " card(s) transferred")
    else:
        if target_card[0] != card[0]:
            top_card = GetTopCard(sDeck)
            pHands[0].append(top_card)
            if top_card[0] == target_card[0]:
                ShowMessage("HIT: LUCKILY Player 0 has fished up a rank <" + str(top_card[0]) + ">!!!")
            else:
                ShowMessage("MISS: You fished up the rank <" + str(top_card[0]) + ">")
                hit = hit - 1
            return hit 

Dani AI

Generated

Three separate problems explain the behavior in the original post: an indentation/for-else mixup, mutating a list while iterating, and not assigning the updated hit back to the outer loop. As pointed out, indentation is important; as correctly notes, for … else is a Python feature where the else runs after the loop completes normally (i.e. no break), so the draw/“miss” path was executing even after successful transfers.

Practical fixes (simple, reliable rules):

  • Don’t attach the draw logic to the for via a mis-indented else. Instead detect matches first, then either transfer them or draw one card.
  • Don’t remove items from a list while iterating it. Build a matches list, transfer or remove those items afterwards. This also makes the count correct: len(matches) is the number of cards moved.
  • Have the function accept the target player and target rank and return the updated hit (or a boolean continue_turn). Assign that return value back to the loop variable (for example, hit = player_0_hitman(...)). Also ensure the function is defined before it’s called.

A compact, implementation-ready pattern (keeps scope local, fixes counting and control-flow):

def player_0_hitman(target_player, target_rank, sDeck, pHands):
    matches = [c for c in pHands[target_player] if c[0] == target_rank[0]]
    if matches:
        pHands[0].extend(matches)
        pHands[target_player] = [c for c in pHands[target_player] if c[0] != target_rank[0]]
        ShowMessage("HIT: {} card(s) transferred".format(len(matches)))
        return 1    # keep turn
    top_card = GetTopCard(sDeck)
    pHands[0].append(top_card)
    if top_card[0] == target_rank[0]:
        ShowMessage("HIT: LUCKILY Player 0 has fished up a rank <{}>!!!".format(top_card[0]))
        return 1
    ShowMessage("MISS: You fished up the rank <{}>".format(top_card[0]))
    return 0

Checklist: define the function before the loop; call it with explicit arguments; assign its return to hit (or continue_turn); avoid removing while iterating. These changes will stop the erroneous double-path execution, make counts correct, and make hit update predictably.

Recommended Answers

All 3 Replies

Quick looky shows an indentation problem.

commented: no code shown +0
import random
def SetDeck():
    suitList = ["s", "c", "d", "h"]
    rankList = ["a", "2", "3", "4", "5", "6", "7", "8", "9", "t", "j", "q", "k"]
    deck = []
    for suite in range(4):
        for rank in range(13):
            deck.append(rankList[rank]+suitList[suite])
    return deck
def Shuffle(deck):
    nCards = len(deck)
    for i in range(nCards):
        j = random.randint(i,nCards-1)
        deck[i], deck[j] = deck[j], deck[i]
    return deck
def GetTopCard(shuffledDeck):
    return shuffledDeck.pop(0)
def DealInitialCards(nPlayers,nCards,shuffledDeck):
    playersCards = [["" for j in range(nCards)] for i in range(nPlayers)]
    for j in range(nCards):
        for i in range(nPlayers):
            playersCards[i][j] = GetTopCard(shuffledDeck)
    return playersCards
def Sort(cards):
    rankString = "a23456789tjqk"
    swapped=True
    while swapped:
        swapped = False
        for i in range(len(cards)-1):
            if rankString.find(cards[i][0])>rankString.find(cards[i+1][0]):
                cards[i],cards[i+1]=cards[i+1],cards[i]
                swapped = True
    return
def ShowCards(player,cards):
    print("\n****************************************************")
    print("************Player "+str(player)+" has**************")
    print("****************************************************\n")
    for i in range(len(cards)):
        print(cards[i]),
    print("\n")
    return
def ShowMessage(msg):
    print("****************************************************")
    print(str(msg))
    print("****************************************************\n")
    return
def remove_suits(player):
    new_hand = []
    for card in pHands[player]:
        new_card = card[0]
        new_hand.append(new_card)
    return new_hand
def choosing_target():
    target_player = raw_input ("Who do you want to ask? (1-3)")
    while target_player.isdigit() == False or 1 > int(target_player) or 3 < int(target_player):
        print "Error: Must type a valid player id (from 1 to 3)"
        target_player = raw_input ("Who do you want to ask? (1-3)")
    target_player = int(target_player)
    return target_player
def target_rank():
    target_card = raw_input ("What rank are you seeking? (" + str(",".join(new_hand)) + ")")
    while target_card not in new_hand:
        print "Error: Must type one of the follow valid single character card ranks"
        print str(",".join(new_hand))
        target_card = raw_input ("What rank are you seeking? (" + str(",".join(new_hand)) + ")")
    return target_card
print("~"*70)
print("~"*25+"WELCOME TO GO FISH!"+"~"*26)
print("~"*70)
nPlayers = 4
nCards = 10
deck = SetDeck()
sDeck = Shuffle(deck[:])
pHands = DealInitialCards(nPlayers,nCards,sDeck)
Sort(pHands[0])
ShowCards(0,pHands[0])
hit = 1
while hit == 1 :
    ShowMessage("TURN: Player 0, its your turn.")
    target_player = choosing_target()
    new_hand = remove_suits(0)
    target_card = target_rank()
    ShowMessage("Target: Player " + str(target_player) + " is being targeted for the rank <" + str(target_card) + ">")
    temp_hit = player_0_hitman(hit)
    print "hit = " + str(hit)
def player_0_hitman(hit):
    for card in pHands[target_player]:
        if target_card[0] == card[0]:
            count = pHands[target_player].count(card)
            pHands[0].append(card)
            pHands[target_player].remove(card)
            ShowMessage("HIT: " + str(count) + " card(s) transferred")
        else:
            if target_card[0] != card[0]:
                top_card = GetTopCard(sDeck)
                pHands[0].append(top_card)
                if top_card[0] == target_card[0]:
                    ShowMessage("HIT: LUCKILY Player 0 has fished up a rank <" + str(top_card[0]) + ">!!!")
                else:
                    ShowMessage("MISS: You fished up the rank <" + str(top_card[0]) + ">")
                hit = hit - 1
            return hit 

for-else is somethin' to. if the for uses break it won't execute the else block.

Inentation: a big misunderstanding.

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.