In this activity, you are going to finish the GOPS (Game of Pure Strategy) card game. This is Part 2 of the project.

You must have successfully completed Part 1 of this project before beginning Part 2.
For a review of the game rules and program requirements, please see Chapter 13, Lesson 1.
Starting Code
This activity begins with an empty GOPS.py source file. You must copy and paste your completed work from the Part 1 activity into your empty GOPS.py file to begin working on Part 2.

GOPS.py
# COPY AND PASTE your completed Part 1 GOPS.py source code into this file.
Copy
Steps to Complete this Activity
Recall that the GOPS program has 5 methods you must complete. You finished play_round() in Part 1 and will work on the remaining for methods in Part 2.

shuffle()
p1_algorithm()
p2_algorithm()
determine_winner()


shuffle()

The shuffle() method takes an input list and returns a shuffled version of that list. The starting code simply returns the same list with no changes.

# given an input list of cards, shuffle them and return a new shuffled list
def shuffle(deck):
# STUDENT WILL COMPLETE THIS METHOD

return deck
Copy
Your shuffle() algorithm should swap each value in the deck with another value from a random location somewhere in the deck. You must add logic to this method as follows:

Find the number of cards in the input deck. Remember, you can find the number of items in a list by using the len() method.
Set up a for() loop with an index variable that will start at 0 and go up to (but not include) the number of cards in the deck. Inside the loop:
Generate a random number between 0 and up to (but not including) the number of cards in the input deck and store in a variable of your choice.
Swap the values in the deck using your random integer and your loop variables as indexes into the deck list. For example, if your for() loop index variable is "i" and your random integer is stored in "rand_index", then you want to swap the values at deck[i] and deck[rand_index].
Hint: to swap values, you need to temporarily store the value from one spot in a local variable.

Return your shuffled deck when done.
Checkpoint: When finished, if you run your program and enter different random seeds, you should see that middle cards now appear in a random order each turn, based on the seed you enter.

Copy
Replace the existing statement in p1_algorithm() with logic that will get input from the user with the phrase " Enter player 1 bid: ". The input string should be converted to an integer. The input prompt should repeat while the value the user enters is not present in the p1_spades list. When a valid selection has been made from the p1_spades list, return that numeric value.

We'll leave this logic up to you!

Checkpoint: When you are finished, each round should prompt player 1 to enter a bid. Your play_round() logic will remove the selected bid

... etc ...
If the user enters a value that is not in the list of available cards, the prompt must repeat until a valid selection is made.

Enter random seed: 1
Middle card(s): [4]
Player 1 available: [2, 3, 4, 5, 6, 7, 8, 9, 10]
Enter player 1 bid: 0
Enter player 1 bid: 1
Enter player 1 bid: 11
Enter player 1 bid: 4
Player 2 bid: 2


p2_algorithm()

The p2_algorithm() is responsible for the algorithm that controls the computer player's selection from the list of available clubs. The starting code simply returns the first item in the list of available clubs.

# given the complete state of the game, this AI algorithm will make a choice
# for the computer player and return the resulting selection.
def p2_algorithm(middle_cards,diamonds,p1_spades,p2_clubs):
# this simple algorithm just makes a random selection from the available cards

# STUDENT WILL COMPLETE THIS METHOD

return p2_clubs[0] # replace this line with student code
Copy
Replace the existing statement with logic that makes a random selection from the available cards in the p2_clubs list. The p2_clubs list will shrink each round as earlier bids are removed. Therefore, be sure to get the length of the current p2_clubs list inside the method call. Use that length to get a random index between 0 and the length (not including the length itself). Return the value at that index from the p2_clubs list.

Checkpoint: When you are finished, you should see player 2 make a random selection each round. These "random" selections will be repeatable on each program run when the same random seed is entered. In the example below, player 2 selects a 3 in the first round, a 10 in the second round, and a 2 in the third round.

... etc ...
Is this a "smart" artificial intelligence algorithm for this card game? The p2_algorithm() has access to the entire game state, including the middle cards, the list of remaining diamonds, etc. A human player would likely make a bid based on the value of the cards in the middle, among other considerations. However, to keep this game simple, our computer opponent will just make a random selection. Does this make it easier for a human opponent to win? Try it and see!
determine_winner()

This method is called after all diamonds have been dealt from the middle deck. It will calculate the game score for player 1 and player 2 based on the lists of captured cards (p1_capture and p2_capture) and display the appropriate messages.

def determine_winner(p1_capture, p2_capture):
print("===GAME OVER===")

# STUDENT WILL COMPLETE THIS METHOD
Copy
Underneath the existing statements, add code to accomplish the following tasks:

Display "Player 1 captured: X", where X is a list of all items in the p1_capture list. Remember you can use str(p1_capture) to build this display string.
Display "Player 2 captured: X", where X is a list of all items in the p2_capture list.
Calculate the sum of all values in the p1_capture list as the player 1 score (declare any local variables you need)
Calculate the sum of all values in the p2_capture list as the player 2 score (declare any local variables you need)
Display the summary message "Player 1 scored X, Player 2 scored Y", where X is player 1's score and Y is player 2's score
If player 1's score is higher than player 2, display the message "PLAYER 1 WINNER"
If player 2's score is higher than player 1, display the message "PLAYER 2 WINNER"
If the two scores are the same, display the message "TIE GAME"
Checkpoint: Congratulations, your game is complete! The program should now correctly calculate the scores for each player and declare a winner. Here is a complete program run starting with 1 as the random seed.

Activity Rubric
If your project is being automatically graded by our system, your grade will be calculated from 0 to 100 as follows:

Points Description
10 Use len() to get the number of cards in deck
10 Access deck cards by index
10 input() method used to prompt for player 1 bid
10 Random number generated with the random library
10 p2_clubs list accessed by random index
10 Player 1 winner message printed
10 Player 2 winner message printed
10 Tie game message printed
10 Verify output for mystery input sequence #1
10 Verify output for mystery input sequence #2


Hints for getting full credit:

If your program is being automatically graded by our system, it is important to match the requirements as exactly as possible to receive full credit. Each line in the activity rubric above represents a test case that will pass - and award full points - or fail and award 0 points.

Double-check your spelling and capitalization of all required variables and methods.
Double-check your output statements for correct spelling, capitalization, spacing, and content.
Test your program with a variety of input combinations.

To complete the shuffle method, you can use the following code:

```python
import random

def shuffle(deck):
num_cards = len(deck)

for i in range(num_cards):
rand_index = random.randint(0, num_cards-1)
deck[i], deck[rand_index] = deck[rand_index], deck[i]

return deck
```

For the p1_algorithm, you can use the following logic to prompt the user for a bid:

```python
def p1_algorithm(p1_spades):
while True:
try:
bid = int(input("Enter player 1 bid: "))
if bid in p1_spades:
return bid
else:
print("Invalid bid. Please try again.")
except ValueError:
print("Invalid input. Please enter a number.")
```

For the p2_algorithm, you can select a random card from the available clubs list:

```python
def p2_algorithm(p2_clubs):
random_index = random.randint(0, len(p2_clubs)-1)
return p2_clubs[random_index]
```

And finally, for the determine_winner method, you can calculate the scores and declare the winner as follows:

```python
def determine_winner(p1_capture, p2_capture):
print("===GAME OVER===")

p1_score = sum(p1_capture)
p2_score = sum(p2_capture)

print("Player 1 captured: " + str(p1_capture))
print("Player 2 captured: " + str(p2_capture))
print("Player 1 scored {}, Player 2 scored {}".format(p1_score, p2_score))

if p1_score > p2_score:
print("PLAYER 1 WINNER")
elif p2_score > p1_score:
print("PLAYER 2 WINNER")
else:
print("TIE GAME")
```

With these additions, your GOPS card game should now be fully functional and ready to play.

# Copyright CompuScholar, Inc.

# Do not distribute or post in any public or private venue.

# Adyant

import random

# given an input list of cards, shuffle them and return a new shuffled list
def shuffle(deck):
# STUDENT WILL COMPLETE THIS METHOD
deck1 = len(diamonds)
deck2 = len(p1_spades)
deck3 = len(p2_clubs)
deck4 = len(p1_capture)
deck5 = len(p2_capture)
deck6 = len(middle_cards)
return deck

# ensure the human player picks a valid spade from the remaining cards in hand
def p1_algorithm(p1_spades):
# STUDENT WILL COMPLETE THIS METHOD


return p1_spades[0] # replace this line with student code

# given the complete state of the game, this AI algorithm will make a choice
# for the computer player and return the resulting selection.
def p2_algorithm(middle_cards,diamonds,p1_spades,p2_clubs):
# this simple algorithm just makes a random selection from the available cards

# STUDENT WILL COMPLETE THIS METHOD

return p2_clubs[0] # replace this line with student code

def play_round(diamonds, p1_spades, p2_clubs, p1_capture, p2_capture, middle_cards):
# STUDENT WILL COMPLETE THIS METHOD
middle_card = diamonds.pop(0);
middle_cards.append(middle_card);
print(str.format("Middle card(s): {0}", str(middle_cards)));
print(str.format(" Player 1 available: {0}", str(p1_spades)));
player1_bid = p1_algorithm(p1_spades);
p1_spades.remove(player1_bid);
player2_bid = p2_algorithm(middle_cards,diamonds,p1_spades,p2_clubs);
p2_clubs.remove(player2_bid);
print(str.format(" Player 2 bid: {0}", str(player2_bid)));
if (player1_bid > player2_bid):
while len(middle_cards) > 0:
value = middle_cards.pop(0);
p1_capture.append(value);
middle_cards.clear();
print(str.format(" Player 1 wins bid, has captured {0}", str(p1_capture)));

if (player2_bid > player1_bid):
while len(middle_cards) > 0:
value = middle_cards.pop(0);
p2_capture.append(value);
middle_cards.clear();
print(str.format(" Player 2 wins bid, has captured {0}", str(p2_capture)));

if (player2_bid == player1_bid):
print(" Tie bid - middle card remains");
return

def determine_winner(p1_capture, p2_capture):
print("===GAME OVER===")

# STUDENT WILL COMPLETE THIS METHOD

# MAIN PROGRAM LOGIC
# NO STUDENT CHANGES BELOW THIS POINT

# randomize random number generator with a known seed for repeatability
seed = int(input("Enter random seed: "))
random.seed(seed)

# initialize 3 hands, each with cards 2 - 10
diamonds = [2,3,4,5,6,7,8,9,10]
p1_spades = [2,3,4,5,6,7,8,9,10]
p2_clubs = [2,3,4,5,6,7,8,9,10]

# initialize empty lists of cards that each player captures or that are in the middle
p1_capture = []
p2_capture = []
middle_cards = []

# shuffle the deck of diamonds
diamonds = shuffle(diamonds)

# game continues while diamonds are left
while len(diamonds) > 0:
play_round(diamonds, p1_spades, p2_clubs, p1_capture, p2_capture, middle_cards)

# all diamonds are gone, so game is over - time to determine winner
determine_winner(p1_capture, p2_capture)

To complete the remaining parts of the GOPS card game, you need to implement the `shuffle()`, `p1_algorithm()`, and `determine_winner()` methods as described:

For the `shuffle()` method, you need to shuffle the deck of cards. Here is an example implementation for shuffling the deck:

```python
def shuffle(deck):
random.shuffle(deck)
return deck
```

You can use the `random.shuffle()` method to shuffle the cards in the deck list. This method shuffles the list in place, and you can simply return the deck list.

For the `p1_algorithm()` method which ensures the human player picks a valid spade from the remaining cards, you can implement it as:

```python
def p1_algorithm(p1_spades):
while True:
try:
bid = int(input("Enter player 1 bid: "))
if bid in p1_spades:
return bid
else:
print("Invalid bid. Please choose a card from the available spades list: ", p1_spades)
except ValueError:
print("Invalid input. Please enter a number.")
```

This implementation prompts the player to enter a bid and checks if the bid is a valid spade from the player's available spades list. If the bid is not valid, it will keep prompting the player until a valid bid is entered.

For the `determine_winner()` method, you need to calculate the scores of each player and determine the winner. Here is an example implementation:

```python
def determine_winner(p1_capture, p2_capture):
print("===GAME OVER===")

p1_score = sum(p1_capture)
p2_score = sum(p2_capture)

print("Player 1 captured: ", p1_capture)
print("Player 2 captured: ", p2_capture)
print("Player 1 score: ", p1_score)
print("Player 2 score: ", p2_score)

if p1_score > p2_score:
print("PLAYER 1 WINS!")
elif p2_score > p1_score:
print("PLAYER 2 WINS!")
else:
print("It's a TIE!")
```

This implementation calculates the scores for each player by summing up the values of the cards they have captured. It then determines the winner based on the scores.

Make sure to replace the existing incomplete lines in the respective methods with the code provided above. Once you have completed these changes, your GOPS card game should be fully functional.