Imagine we want to program a card game. We will need the ability to simulate a deck of cards and select a hand of cards for the player. If we store the deck as a list: ["Ace", "2", "3", …] we can think of the start of the list as the “top” of the deck and the end of the list as the “bottom”. Dealing a player cards could be as simple as slicing the deck - make one slice that has the first 5 cards, that is the player’s hand, and a second slice with everything else that is the leftover cards.
However, we don’t always want to give the player the cards Ace-4. We need to shuffle the deck before trying to deal. We will explore two different algorithms for doing a shuffle before dealing cards.
To reduce the complexity, we will only deal with a deck with 13 cards. However, we will write the code so that it could work for any size deck. A good practice when problem solving is to whenever possible, solve a smaller version of the problem before scaling up to tackle the full version.
Our first algorithm will be to try shuffling by doing a series of “cuts”, where we split the deck in half and put the “bottom” (second) half “on top of” (in front of) the “top” (first) half.
The exercises below will guide you through writing the algorithm. In the first part, we will just make one cut and reassemble the deck so the “top” and “bottom” halves are reversed.
cutPoint is set to a random location in the list of cards deck. Use it to make a slice which contains list items 0 up to (but not including) the cutPoint. Store it in a new variable top and then print out top. Run the program a few times to make sure that you are printing out a random amount of the list each time. Tests 1-2 should now pass.
Now make a slice that starts at cutPoint and goes until the end. Store that slice as bottom. Print it out and make sure it has the part of the list that top does not. Tests 3-4 should now pass.
Set deck to be bottom plus top and print what deck becomes. That should reverse the order of the two halves. (Doing + will merge two lists into one big list.) Print deck to see that you did in fact cut the cards and swap the two halves.
The checks for this program can’t verify it works because it is doing something random. They will just make sure you have some of the basic elements that are needed. Make sure to test your program until you are sure it is working. The checks do depend on you using the specified variable names in your code.
At this point, your program should print out a deck where part of the back has been moved to the front. So hopefully, if we repeat that process a bunch of times, the deck will keep getting chopped up differently and become more and more jumbled.
The second algorithm we will try will be to pick one card at random from the deck (other than the last card) and move it to the end of the deck. On its own, that won’t do much, but maybe if we repeat it a bunch of times, it will work.
The starter code makes selectIndex and sets it to a random value between 0 and 2 less than the length of the deck. (Since the last card is length - 1 and we do not want to select it).
Copy the card at that location of selectIndex to a variable removed. Then use the .pop(XXX) function to remove that item from the deck. Here is the section on Adding and Removing Items if you need to review.
Append the removed card to the end of the deck. Print the deck and verify that one random card was moved to the end. At this point the last test should pass.
The checks for this program can’t verify it works because it is doing something random. They will just make sure you have some of the basic elements that are needed. Make sure to test your program until you are sure it is working. The checks do depend on you using the specified variable names in your code.
Now we will repeat the process. Since we are only moving one card at a time, doing 10 repetitions probably won’t be enough. But let’s start with that and see if the method looks like it is working before we scale it up to more repetitions.
If we really wanted to prove which method was the better way to shuffle we would need to create a measurement of randomness and then test how “random” the results of the different algorithms are. We might also need to do this to figure out the optimum number of repetitions for any particular algorithm. But the “eye test” is good enough to identify that our second algorithm is superior.