CS 106 Winter 2017

Lab 07: Randomness and Noise


Question 1 Poker

A standard deck of cards contains 52 cards. Each card has a suit (Spades, Hearts, Diamonds, Clubs) and a rank (Ace, 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King). All distinct combinations are represented in the deck, whence we get 4×13=52 cards. Of course, these cards are used for countless solitaire and multiplayer games. A popular one is Texas Hold 'em Poker. Don't worry, the rules of poker in general, or of Texas Hold 'em in particular, won't matter for this question. The only thing you will have to do is shuffle the deck and deal the cards. The challenge is to use randomness correctly to ensure that the sketch accurately simluates drawing cards from a single 52-card deck, with no duplicates.

  1. In the starter code, open the sketch titled HoldEm. You'll see a fairly complete interface for visualizing a round of Texas Hold 'em. Your two "hole cards" are shown face-up on the bottom of the screen; your opponent's two hole cards, and the five "community cards", are initially face-down. You can press the space bar to advance through the phases of the game, first revealing the three-card "flop", then the "turn", then the "river", and finally your opponent's hole cards. (In real poker, these reveals would be interspersed with rounds of betting, which of course we won't include here.)

  2. The source code is divided into two files. The main sketch is in HoldEm, and relies on a Card class to hold information about a single playing card. Read the source code and poke around until you have some intuition for what it does and how it works.

  3. Locate the TODO comment in the deal() function. This is the only place where you will have to write new code. As written, the function constructs nine legal cards completely at random. This process doesn't accurately model a real-world deck, because you might randomly generate the same card multiple times in a single round of poker. Your goal is to change the deal() function so that it deals its cards from a single deck. This requires some careful control of randomness, and is more challenging than, say, generating a random roll of a die.

  4. In deal(), declare a local array of Cards called deck. Initialize it to be a new array of size 52. Now write code that fills the array with exactly one copy of every legal card in a deck of cards. The easiest approach is to use two nested loops: one over suits, and one over ranks. You could try to figure out a mathematical formula that tells you the offset in a one-dimensional array based on your two loop counters. Another approach is to use a third variable to keep track of where in the array to write the new card, and just increment that variable every time you store a card.

  5. Now shuffle the deck. The easiest way to do that is to perform a large number of "random swaps": pick two cards in the deck, and swap their positions. To do so, generate two random integers in the range 0...51, and use them as indices into the deck array. Swapping in an array follows a pattern that's standard in computer programming. For example, if arr is an array of integers, this code would swap elements at positions 17 and 31:

    int tmp_val = arr[17];
    arr[17] = arr[31];
    arr[31] = tmp_val;
    

    In a loop, you should perform many random swaps, say 100,000.

  6. Now, instead of repeatedly using randCard() to make up random cards, use the first nine cards in deck to populate the arrays my_hole, your_hole and community.

That's all you have to do. The work consists about about 10–15 lines of code, and changes to the final three lines of the existing function, which initialize the arrays. Submit your work in a sketch titled HoldEm.

The obvious next step in this sketch would be to add code that determines who won the hand. That would require implementing the rules for ranking poker hands, which is highly complex and would require at least 2-3 times as much code as the entire current sketch. We would of course award bonus marks for a successful implementation of this feature!

Question 2 Lava Lamp

The NoiseDirectManip sample sketch offers a direct visualization of the noise() function, together with the ability to explore the function's behaviour across the entire plane via direct manipulation. In this exercise, you will add a few simple features to this sketch to turn it into an animated visualization sort of like a lava lamp.

  1. In the starter code, open the LavaLamp sketch.

    As provided, the sketch is nothing more than a clone of NoiseDirectManip. We'll use it as a starting point for adding new features.

  2. Choose a colour scheme. Your colour scheme must consist of at least three, and not more than six, distinct colours. Store your colours in an array declared as a global variable.

  3. Instead of turning the value of noise function directly into a greyscale level (by multiplying by 256), let's divide the range of noise values into narrow "bands" and assign each band a colour from your array.

    There's a nice mathematical trick to doing this. Choose the number of bands you want, an integer between 20 and 150. Multiply the value of the noise() function by the number of bands, and round the result to an integer. Now compute the remainder when that integer is divided by the number of colours in your array (using the % operation). That remainder can be used as an index into the array of colours; set each pixel to the colour taken from the array for the pixel's corresponding noise value. You should now have something that looks like a frame in the video above, though it won't warp over time.

  4. Experiment with the global variable sc and the number of bands you chose in the previous step until you have a density of bands and visual complexity that you're happy with.

  5. To add the slow animated warping, simply add a third parameter to the call to noise(). This third parameter should be something that changes slowly from frame to frame; the effect is to move gradually through 2D "slices" out of the 3D noise function, allowing us to visualize the change in noise over time. A simple choice is something like frameCount * temp_scale, where temp_scale is a variable that controls how fast the pattern changes. Choose a small number (say, 0.001) to start and then experiment from there.

That's all you need to do for this sketch. The total sketch will be 30–35 lines, and you need to write only about 5 of them. You are welcome to experiment with other visual effects or changes, and we may award bonus marks to especially attractive results.

Save your sketch under the name LavaLamp.

Submission

When you are ready to submit, please follow these steps.

  1. If necessary, review the Code Style Guide and use Processing's built-in auto format tool. You do not need to use the precise coding style outlined in the guide, but whatever style you use, your code must be clear, concise, consistent, and commented.

  2. If necessary, review the How To Submit document for a reminder on how to submit to LEARN.

  3. Make sure to include a comment at the top of all source files containing your name and student ID number.

  4. Create a zip file called L07.zip containing the entire L07 folder and all its subfolders.

  5. Upload L07.zip to LEARN. Remember that you can (and should!) submit as many times as you like. That way, if there's a catastrophe, you and the course staff will still have access to a recent version of your code.

  6. If LEARN isn't working, and only if LEARN isn't working, please email your ZIP file to the course account (see the course home page for the address). In this case, you must mail your ZIP file before the deadline. Please use this only for emergencies, not "just in case". Submissions received after the deadline may receive feedback, but their marks will not count.