# Go Fish Game Assignment Solution using Python

## Go Fish Game Assignment

To complete the python assignment, we will finish our shell game of Go Fish. There are many versions of Go Fish. Ours works like this: There are two players: the user and the computer. The goal of the game is to make the most “books” (four of a kind). Aces are the highest points, 2s are the lowest. A book of 2s is worth 2 points, a book of 3s is worth three points… a book of kings (K) is worth 13 points, and a book of aces (A) is worth 14 points. The computer and user both begin with 7 cards. In each turn, one player requests a card from the other player. Players can only request cards they also own a copy of. If the other player has that kind of card, they must transfer all copies to the requesting player. If the other player does not have that kind, the requesting player must “Go fish” by drawing a card from the deck. Players alternate turn and the user goes first. For example, suppose the user has one jack (“J”) and requests jacks from the computer. If the computer has at least one jack, then the computer must transfer all their copies of jacks to the user. Then it is the computer’s turn to request a card. The game ends once every “book” is owned by a player. Points are then tabulated based on the books owned and a winner is declared. For example, here might be the final hands of a game: user = [‘2’, '2', '2', '2', '7', '7', '7', '7', '8', '8', '8', '8', '9', '9', '9', '9', 'A', 'A', 'A', 'A', 'J', 'J', 'J', 'J', 'K', 'K', 'K', 'K'] comp = ['10', '10', '10', '10', '3', '3', '3', '3', '4', '4', '4', '4', '5', '5', '5', '5', '6', '6', '6', '6', 'Q', 'Q', 'Q', 'Q'] The user’s score will be 2 + 7 + 8 + 9 + 11 (J) + 13 (K) + 14 (A) = 64. The computer’s score will be 3 + 4 + 5 + 6 + 10 + 12 (Q) = 40. The user would be the winner.

draw_card() -- Adjust this function to consider the case when the deck is empty. If the deck is empty, print “Deck is out of cards” and return None.

display() -- Adjust this function so the user can easily determine what books they have and can strategize better. (I suggest doing this last)

play_again() -- Adjust the case when the user opts to play again. Before returning True, clear user and comp of contents and add cards back into the deck. Use only list methods to do this; do not user assignment statement for the user, comp, or deck. Remember that you can use the dir() function to see the available methods.

welcome_message() -- This function has no parameters. It prints a welcome message for the user announcing they will play Go Fish and giving a basic explanation of the rules.

Is_game_over() -- This function takes in no parameters. It returns a boolean value based on whether the conditions for the game to be over are met. It first checks if the deck is nonempty. If it has at least one card, the function returns False. The function then loops through all the unique cards held in the comp (use a set for this loop!). If the count of any card in comp is less than 4, it returns a False. The same approach is repeated with the user. At the end of the function, return True (meaning that return False was never called in the previous cases).

ask_comp() -- This function has no parameters. Create an empty list called potential_cards. Loop through all the unique cards in comp. If less than four copies are in the comp, add the card to potential_cards. If potential cards are not empty, pick a card from it at random. Otherwise, the computer has only books (4-of-a-kind) so the computer should just pick a random card from comp. Print a statement letting the user know what card the computer is requesting. If the request is in user, print a statement letting the user know that they have this card and call

give_cards() with the correct parameters. Otherwise, print a statement letting the user know they do NOT have this card and call go_fish with the correct parameter.

score() -- This function takes in no parameters. Make two variables representing the computer’s total score and the user’s total score and assign them the value 0.

Make this shell game as user-friendly as possible. Slow down the print-ups so as not to overwhelm the user by using the following command: input("Press enter to continue") This will require the user to hit enter in order to read more prints.

Solution:

``` from random import randint card_scores = {"A": 14, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "10": 10, "J": 11, "Q": 12, "K": 13} cards = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"] deck = [] # Take all elements from cards and add them to the deck 4 times for i in range(4): deck += cards user = [] comp = [] def draw_card() -> str: """ This function takes a card from the list 'deck' and returns it :return: card -> str """ # randomly select index of card index = randint(0, len(deck) - 1) # Get card and delete from deck card = deck.pop(index) # Return card return card def deal_cards() -> None: """ This function deals 7 cards for both user and computer. The cards are dealt alternatively to the user, computer, user, computer, etc... :return: None """ # Deal cards to user and computer for i in range(7): # Alternatively, deal one to user, then one to comp, etc user.append(draw_card()) comp.append(draw_card()) def go_fish(hand: list) -> None: """ This function adds a new card to the user or computer, depending on the hand passed as a parameter :param hand: List of cards (str) :return: None """ # print statement print("Go fish!") # Check if the given hand is equal to user or comp isUser = None if hand == user: isUser = True else: isUser = False # Draw card card = draw_card() # Add to hand hand.append(card) # Sort hand hand.sort() # Display info to the player if user: print("You drew a " + card) else: print("Computer drew a card") def give_cards(giver: list, taker: list, card: str) -> tuple: """ This function checks if the card is in the giver's hand. If it is in the giver's hand, all instances of that card are then removed from giver's hand and added to taker's hand :param giver: list of giver's cards :param taker: list of taker's cards :param card: card :return: Return the updated hands (lists) of giver and taker inside a tuple (giver, taker) """ print("The card " + card + " is being transferred.") # Iterate through the cards in giver for i, cardi in enumerate(giver): if cardi == card: # The card in giver at index i is equal to card # Remove from giver del giver[i] # Add to taker taker.append(card) # Sort taker taker.sort() # Now return as a tuple return (giver, taker) def display() -> None: """ This function shows to use the cards that he/she has in his/her hand and displays the number of cards in computer's hand :return:None """ print("The user hand is: ", end="") for i, card in enumerate(user): print(card, end="") if i < len(user) - 1: print(", ", end="") print("") print(f"Computer has {len(comp)} cards in its hand.") def play_again() -> bool: """ This function asks to user if he/she wants to play again The function uses an infinite loop that is broken only when the user enters a valid option :return: None """ # Start infinite loop while True: option = input("Do you want to play? (Y/N): ") if option.lower() == "y": return True elif option.lower() == "n": return False else: print("Invalid input.") def ask_user() -> None: """ This function asks to user for a card to be drawn from the computer's hand If the card is in the computer's hand, then all instances of that card are added to the user's hand and removed from computer's hand :return: None """ display() # ask user which card he/she wants to take from comp card = input("Enter the card to be requested to the computer: ").upper() # Check if the card is in the computer's hand if card in comp: # The comp has that card giver, taker = give_cards(comp, user, card) print("Computer has the card!") else: print("Computer does not have that card!") if len(deck) > 0: go_fish(user) def welcome_message() -> None: """ This function prints a welcome to message for the user announcing they will play go Fish and give a basic explanation of the rules :return: None """ print("Welcome! We'll be playing Go Fish!") print() print(" 1. Each player (you and computer) will start with 7 random cards each") print(" 2. Your objective is to have as many collection sets of 4-of-a-kind cards") print(" 3. Your score is the sum of these kinds that you have collected") print(" 4. You will make the first move by requesting a kind of card to a computer") print(" 5. If the computer has those cards, you'll get those transferred to you") print(" 6. If you completed a set of four-of-a-kind then you scored") print(" 7. Completed four-of-a-kind cards are non-tradable and is removed in your hand") print(" 8. If the computer does not have the card, you will get a random card from the deck") print(" 9. After your turn, the computer will do the same rules as you did") print("10. You and computer will trade alternately until all sets of four-of-a-kind are completed") input("Press enter to continue...") print() def is_game_over() -> bool: """ This function checks whether the conditions of the game to be over are met such that deck is empty and that there are incomplete books on both players :return: Boolean """ if len(deck) > 0: return False for card in set(comp): if comp.count(card) < 4: return False for card in set(user): if user.count(card) < 4: return False return True def ask_comp() -> None: """ Pick a potential card that the computer will request to make a book :return: None """ potential_cards = [] for card in set(comp): if comp.count(card) < 4: potential_cards.append(card) if len(potential_cards) > 4: index = randint(0, len(potential_cards) - 1) requested_card = potential_cards[index] else: index = randint(0, len(comp) - 1) requested_card = comp[index] print("Computer is requested card number " + requested_card + " from you") if requested_card in user: print("You have the requested card, moving all copies of those cards to computer") give_cards(user, comp, requested_card) else: print("You do not have the requested card") if len(deck) > 0: go_fish(comp) input("Press enter to continue...") def score() -> None: """ Calculate the score of players and evaluate the winner :return: None """ comp_score = 0 user_score = 0 for card in set(comp): comp_score += card_scores[card] for card in set(user): user_score += card_scores[card] print() print("User score: " + str(user_score)) print("Computer score: " + str(comp_score)) if user_score > comp_score: print("User wins the game") elif user_score < comp_score: print("Computer wins the game") else: print("The game is a tie") def game() -> None: """ Starts the game :return: None """ welcome_message() deal_cards() while not is_game_over(): ask_user() if is_game_over(): break ask_comp() print("Game is over") score() if play_again(): game() if __name__ == '__main__': game() ```