CS 115 Project 3, Fall 2016: Racko


Summary: In this project, you will implement the game of 'Racko,' which is a game that involves rearranging your hand of cards in order to have an increasing sequence. Each card just has a number. While Racko is typically played with 2 to 4 players, we will keep this simple and just play the user versus the computer. The user’s moves are decided by the user by asking for input, the computer’s moves are decided by you the programmers!

For checkpoint A, you will be playing a single-player version of the game to build the basic building blocks of the game. For checkpoint B, you will add some functionality to play the user versus computer game. Here the logic used by computer will be very basic and provided to you. For the final code, you will be asked to become creative and program a strategy for the computer!

Due dates:

Note: Idea/concept application of this project was obtained from Dr. Bhusnurmath at the University of Pennsylvania.


Rules of the game

A Racko deck is composed of 60 cards, each numbered 1 to 60. The objective is to be the first player to arrange all of the cards in your rack from lowest to highest.
To start the game, shuffle the deck and both the user and the computer gets dealt 10 cards. As a player receives each card, he places it in the next available slot in his rack, without rearranging any of them. The goal of each hand is to create a sequence of numbers in ascending order, starting at slot 1.

The top card of the deck is turned over to start the discard pile. A player takes a turn by taking the top card from either the deck or the discard pile, then discarding one from his rack and inserting the new card in its place. If the player draws a card from the deck, he may immediately discard it; if he takes the top discard, though, he must put it into his rack.

The first player to get his 10 cards in ascending order calls ”Rack-O!” and wins the hand.

While I could not find a link to an online Racko game, there is a very similar game (with little Vikings!) over here tower blaster

Actual Program

This project will make heavy use of lists in the assignment. We will represent player's rack, deck and discard pile as lists. Note that in both the deck and the discard pile, you only have access to the top. If you take a card from the pile, you need to call the pop function. If you add a card to a pile you call the append function. For example, player's rack can be represeted as the following list

lst = [3, 17, 11, 30, 33, 38, 49, 46, 25, 53] 

Note that there are still some elements that are not in correct order so this list is not racko yet.


Checkpoint A (10 points)

For Checkpoint A, you will be provided with a specific deck of cards and player hand of a single user. Goal is to choose cards from the deck or discard pile and replace it with cards in the hand, while following the rules of the game. For this purpose, you need to write a program that implements the following functions:

def main():
# create a list of integers that represents a deck
deck = [8, 3, 2, 4]
#Assign hand to the user
human_hand = [5, 1, 7, 6]
# create an empty discard pile


# Take out top card from the deck to begin the discard pile


while True:
#print lists corresponding to deck, discard pile and user hand


#Retrieve the top card in the discard pile and ask user if they want it


if user chooses this card:
#Ask the user for the card (number) they want to kick out
#Modify the user's hand and the discard pile
#Print the user's hand
elif user did not choose this card:

#Get the top card from deck and print it to show the user what they got

#Ask the user if they want this card
second_choice = input("Do you want to keep this card? Enter yes or no: ")
if second_choice is yes:
#Ask the user for the card (number) they want to kick out
#Modify the user's hand and the discard pile
#Print the user's hand
else:
#Add card to discard pile
#Print the user's hand
else:
print("Choice can be only yes or no.")
sys.exit()


if len(deck) == 0:
print(" \nWOAH! Deck is empty. Exiting")
sys.exit()

The only way to get credit for Checkpoint A is to demo it for the course staff during workshop, lab, or tutoring hours (or by appointment) before Monday, Nov. 21 at 8PM.

Your output should be exactly as shown below:


Checkpoint B (10 points)

For Checkpoint B, you will be shuffling the deck and dealing the cards to both the "human user" and the "computer user". Then, the human user and computer user will take turns and try to win the game by getting a Racko. The logic used by computer to play its turn is provided. For the purpose of this checkpoint, you need to define two global variables:

#Define a global variable to denote the total number of cards. 
#In the actual game, this will be equal to 60 but for testing we use smaller numbers
numCards = 9 #9, 12, 60

#Define a global variable to denote the size of rack (number of cards in user's hand). #In the actual game, this will be equal to 10 but for testing we use smaller numbers rackSize = 3 #3, 4, 10

For the purpose of this checkpoint, implement the following functions:

def computer_play(computer_hand, deck, discard):

#Define a variable to specify the numbers that can be "allotted" to a single card in the rack
div = numCards // rackSize

#print lists corresponding to deck, discard pile and computer's current hand
...
...
...

#randomly decide whether to choose from the discard pile or deck
coin = random.random() #import random for this to work
if coin > 0.5:
# Show the discard card
discard_card = ... #Top card from the discard pile
print("Computer: Chooses top discard card " + str(discard_card))

#Choose a card to kick out
#First determine index where discard_Card should be inserted.
#Estimate it by dividing the discard Card with numbers per rack (div)
loc = (discard_card - 1) // div

#Replace by whatever card is in computer's hand at this index
number_of_card = computer_hand[loc]
print("Computer: Replacing it with " + str(number_of_card))
#Modify the discard pile and the computer's hand
...
...
print("Computer's new hand: ")
...
else:
# Pick the top card from deck and print it out
deck_card = ...
print("Computer: Chooses top card from the deck " + str(deck_card))

coin = random.random()
#Randomly decide whether to keep the deck card or not
if coin > 0.5:
# Choose a card to kick out
# First determine index where deck card should be inserted.
print("Computer: Chooses top deck card " + str(deck_card))

loc = (deck_card - 1) // div
# Replace by whatever card is in computer's hand at this index
number_of_card = computer_hand[loc]
print("Computer: Replacing it with " + str(number_of_card))

#Modify the discard pile and the computer's hand
... print("Computer's new hand is:")
...
else:
print("Computer: Rejects top deck card " + str(deck_card))

#Add card to discard pile ...
print("Computer's new hand is:")
... def main():
# Create a list of integers that represents the deck. # This should be numbers from 1 to numCards (see definition of numCards above)
... # shuffle the deck ...
# deal initial hands
human_hand, computer_hand = deal_initial_hands(deck)
# create an empty discard pile
...

# Take out top card from the deck to begin the discard pile
...

while neither the computer nor the user has racko:
#print lists corresponding to deck, discard pile and user hand


#Retrieve the top card in the discard pile and ask user if they want it


if user chooses this card:
#Ask the user for the card (number) they want to kick out
#Modify the user's hand and the discard pile
#Print the user's hand
elif user did not choose this card:

#Get the top card from deck and print it to show the user what they got

#Ask the user if they want this card
second_choice = input("Do you want to keep this card? Enter yes or no: ")
if second_choice is yes:
#Ask the user for the card (number) they want to kick out
#Modify the user's hand and the discard pile
#Print the user's hand
else:
#Add card to discard pile
#Print the user's hand
else:
print("Choice can be only yes or no.")
sys.exit()


if len(deck) == 0:
print(" \nUser: WOAH! Deck is empty.Shuffling discard pile and using that as the new deck.")
#Call replaceDeck to get the lists corresponding to the new deck and discard pile #Check if human user did not already win then computer gets to play its turn ...
...
if len(deck) == 0:
print(" \nComputer: WOAH! Deck is empty. Shuffling discard pile and using that as the new deck.\n") #Call replaceDeck to get the lists corresponding to the new deck and discard pile #Outside the while loop. We have a winner. Declare the winner along with the winner's hand. ...

The only way to get credit for Checkpoint B is to demo it for the course staff during workshop, lab, or tutoring hours (or by appointment) before Thursday Dec. 01 at 7PM.

See sample output below. Note, you can get the same output if you insert the statement random.seed(26) at the beginning of your main() function.

Sample Output 1 (using numCards = 9, rackSize = 3) in which human wins

Sample Output 2 (using numCards = 12, rackSize = 4) in which computer wins

 

Sample Output 3 (using numCards = 9, rackSize = 3) in which computer wins.

Sample Output 4 (using numCards = 12, rackSize = 4). Note this example is not reproducible. Only partial output is shown to indicate computer's sub-optimal second move in which a stronger algorithm would have made a better choice!


Final Code

In your final code, you will extend your Checkpoint B code in the following ways:

Note that in Example 2 of Idea 2 above, the computer plays a bad move by rejecting card 9. In other words, there is still scope of further improving computer's logic!

Download some examples here that shows the game progression using i) computer's logic from checkpoint B and ii) upgraded logic that removes random components. Note, these examples are using the random seed = 26, numCards = 30 and rackSize = 5.

There is no demo for your final code. See the end of this specification for submission instructions.


Grading

Correctness [55%]

The most important part of your grade is the correctness of your final program and creativity in upgrading the logic for computer's play. Your program will be tested numerous times, using different inputs, to be sure that it meets the specification. A detailed grading sheet for this project is here.

Programming Design and Style [25%]

In addition to being correct, your program should be easy to understand and well documented. For details, see the grading sheet above.

Checkpoints [20%]

Your checkpoints are each worth 10 points, as described above. The checkpoints cannot be submitted late.


Submitting your final code

You should submit your final code on Moodle by the deadline. As a backup, I strongly encourage you to upload a copy to your blue directory in case something goes wrong with your submission to Moodle.

Please name your file yourlastnameP3.py, substituting your actual last name (in lowercase) as indicated.


Collaboration policy

Programming projects must be your own work, and academic misconduct is taken very seriously. You may discuss ideas and approaches with other students and the course staff, but you should work out all details and write up all solutions on your own. The following actions will be penalized as academic dishonesty:

Late policy

There is a 48-hour grace period associated with the final project deadline. This grace period is designed to only cover small personal emergencies and other unexpected events. No other consideration will be given for these small emergencies.