Tuesday, March 26, 2013

AP Comp Sci Sorting Algorithms

Sorting

Sorting

Introduction

The AP Computer Science test expects you to know 3 sorting methods.

  • Selection sort
  • Insertion sort
  • Merge sort

The blackjack program I have put together needs sorting too. When a hand is scored in Blackjack Aces can be either 1 or 11 in favor of the highest hand you can make without going over 21. By sorting the hands with Aces last the hand can be scored quite easily. So this seemed to be good time to go over sorting.

The Selection sort and Insertion sort are quite easy to implement. Why not start with the easiest part first? To keep it simpler still only int arrays will be used for sorting.

Selection Sort

In selection sort you visit each element of the array up to the second to last element. At each step you look through the array from i to the end, find the smallest value and swap it for the ith element. The pseudo-code should clarify:

int sortArray[] = {4,5,9,6,1,0,3,8,7,2};
int tmp, tmp_idx;

for (int i=0; i < sortArray.length - 1; i++)
{
  tmp = sortArray[i];
  tmp_idx = i;
  for (int j = i + 1; j < sortArray.length; j++) 
  {
    if (sortArray[j] < tmp) {
      tmp = sortArray[j];
      tmp_idx = j;
    }
  }
  // swap the values if the i-th was the smallest this swap doesn't do anything
  // you could test for that if you wanted (which is the way it's done in 
  // the final code)
  sortArray[tmp_idx] = sortArray[i];
  sortArray[i] = tmp;
}

Insertion Sort

Start at the second element and visit the rest of the list. Check the elements before the ith position and see if it is less than any previous elements. If not it stays where it is and move on. This has the appearance of removing the number shifting the elements before it to create a space and placing the number where it belongs.

In the actual implementation you visit each previous element starting at the element immediately to the left and do compare-swaps until one of 2 conditions apply either the number is now at the begining of the list or the element to the immediate left is less. This method accomplishes the shifting of the elements and the comparisons in a way more neatly suited for looping. Again, pseudo-code should help your understanding.

int sortArray[] = {4,5,9,6,1,0,3,8,7,2};
int tmp, tmp_idx;
int j;

for (int i = 1; i < sortArray.length; i++)
{
  for (j = i; j > 0 && sortArray[j] < sortArray[j - 1]; j--)
  {
     // swap
     tmp = sortArray[j];
     sortArray[j] = sortArray[j - 1];
     sortArray[j - 1] = tmp;
  }
}

Create a Sort Lab

To experiment with these I have created a SortLab class. I have borrowed the shuffle method (from the blackjack program) and reworked it for use in the SortLab class. I did this the old fashioned way by cutting and pasting and then changing the names to fit the names of the SortLab fields. The constructors allow you to default to an int array of size 10 or to experiment with other sizes. The arrays are intialized with positive whole numbers. Then they are shuffled to use for sorting. A display method is implemented to print out the values in the array. There is also a swap method to switch values. The selection sort is implemented in 2 different ways. One with an inline swap and a check if a swap is necessary (the first element could have been the lowest of all remaining elements). The other using the swap method with no check.

public class SortLab {

    int[] labArray = null;
    int len = 10;

    public SortLab(int n) {
        this.len = n;
        labArray = new int[this.len];
        for (int i = 0; i < this.len; i++) {
            labArray[i] = i;
        }
        this.shuffle();
    }

    public SortLab() {
        this(10);
    }

    // This shuffle routine adapted from the work done previously
    private void shuffle() {
        int rindex;
        int swap;

        for (int i = 0; i < this.len; i++) {
            rindex = (int) ((Math.random() * ((double) (this.len - i))) + i);
            swap = this.labArray[i];
            this.labArray[i] = this.labArray[rindex];
            this.labArray[rindex] = swap;
        }
    }

    void swap(int k, int l) {
        int tmp;

        tmp = this.labArray[k];
        this.labArray[k] = this.labArray[l];
        this.labArray[l] = tmp;
    }

    public void display() {
        for (int i = 0; i < this.len; i++) {
            System.out.print(this.labArray[i] + "  ");
        }
        System.out.println();
    }

    public void selection() {
        int tmp, tmp_idx;

        for (int i = 0; i < this.len - 1; i++) {
            //select the ith element save value and index
            tmp = this.labArray[i];
            tmp_idx = i;
            // Check if selected is the lowest of the remaining array
            // if not switch them
            for (int j = i + 1; j < this.len; j++) {
                if (this.labArray[j] < tmp) {
                    // found something less save it and it's index
                    tmp = this.labArray[j];
                    tmp_idx = j;
                }
            }
            // if tmp_idx != i then swap the values (move the lowest val in)
            if (tmp_idx != i) {
                this.labArray[tmp_idx] = this.labArray[i];
                this.labArray[i] = tmp;
            }
        }
    }

    // Alternate implementation of selection sort using swap function 
    public void selectionA() {
        int tmp, tmp_idx;
        for (int i = 0; i < this.len - 1; i++) {
            tmp = this.labArray[i];
            tmp_idx = i;
            for (int j = i + 1; j < this.len; j++) {
                if (this.labArray[j] < tmp) {
                    tmp = this.labArray[j];
                    tmp_idx = j;
                }
            }
            swap(i, tmp_idx);
        }
    }

    public void insertion() {
        int j;

        for (int i = 1; i < this.len; i++) {
            for (j = i; j > 0 && this.labArray[j] < this.labArray[j - 1]; j--) {
                this.swap(j, j - 1);
            }
        }
    }

    public static void main(String[] args) {
        SortLab select = new SortLab();
        SortLab selectA = new SortLab();
        SortLab insert = new SortLab();

        System.out.println("Selection Sort");
        System.out.print("unsorted: ");
        select.display();
        select.selection();
        System.out.print("sorted:   ");
        select.display();
        System.out.println("SelectionA Sort");
        System.out.print("unsorted: ");
        selectA.display();
        selectA.selectionA();
        System.out.print("sorted:   ");
        selectA.display();
        System.out.println();
        System.out.println();
        System.out.println("Insertion Sort");
        System.out.print("unsorted: ");
        insert.display();
        insert.insertion();
        System.out.print("sorted:   ");
        insert.display();
    }
}

Output 1

run:
Selection Sort
unsorted: 4  7  2  6  1  5  3  9  8  0  
sorted:   0  1  2  3  4  5  6  7  8  9  
SelectionA Sort
unsorted: 1  3  9  6  8  7  5  4  2  0  
sorted:   0  1  2  3  4  5  6  7  8  9  


Insertion Sort
unsorted: 4  5  9  6  1  0  3  8  7  2  
sorted:   0  1  2  3  4  5  6  7  8  9  
BUILD SUCCESSFUL (total time: 0 seconds)

AP Exam

One way they may ask you about these sorts is to show you interim passes on the list and ask you what type of sort is being done. With a few simple additions our SortLab class can print out interim results to show you how this would look. By placing print statement at the end of the outer loop you can get a print out that shows you the developing sorted lists.

Look at the bottom of the outer loop in each of the 3 sort implementations. I have also added a fourth routine that implements insertion sort with an explicit shift of elements. Some practice exams implement insertion sort in this fashion. Take a look at the output trail it's operation is no different than the first insertion sort. But it uses an extra inner loop.

 public void selection() {
     int tmp, tmp_idx;

     for (int i = 0; i < this.len - 1; i++) {
         //select the ith element save value and index
         tmp = this.labArray[i];
         tmp_idx = i;
         // Check if selected is the lowest of the remaining array
         // if not switch them
         for (int j = i + 1; j < this.len; j++) {
             if (this.labArray[j] < tmp) {
                 // found something less save it and it's index
                 tmp = this.labArray[j];
                 tmp_idx = j;
             }
         }
         // if tmp_idx != i then swap the values (move the lowest val in)
         if (tmp_idx != i) {
             this.labArray[tmp_idx] = this.labArray[i];
             this.labArray[i] = tmp;
         }
         System.out.print("interim:  ");
         this.display();
     }
 }

 // Alternate implementation of selection sort using swap function 
 public void selectionA() {
     int tmp, tmp_idx;
     for (int i = 0; i < this.len - 1; i++) {
         tmp = this.labArray[i];
         tmp_idx = i;
         for (int j = i + 1; j < this.len; j++) {
             if (this.labArray[j] < tmp) {
                 tmp = this.labArray[j];
                 tmp_idx = j;
             }
         }
         swap(i, tmp_idx);
         System.out.print("interim:  ");
         this.display();
     }
 }

 public void insertion() {
     int j;

     for (int i = 1; i < this.len; i++) {
         for (j = i; j > 0 && this.labArray[j] < this.labArray[j - 1]; j--) {
             this.swap(j, j - 1);
         }
         System.out.print("interim:  ");
         this.display();
     }
 }

 public void insertionShift()
 {
     int j;
     int tmp;

     for (int i = 1; i < this.len; i++) {
         // take ith element find where it should be inserted
         tmp = this.labArray[i];
         for (j = i; j > 0 && this.labArray[j] < this.labArray[j - 1]; j--) {
             // no need to do anything
             // when the loop ends j will be the insertion position
         }
         // Shift elements from j to i-1 over 1
         for (int k = i - 1; k >= j; k--)
         {
             this.labArray[k + 1] = this.labArray[k];
         }
         this.labArray[j] = tmp;
         System.out.print("interim:  ");
         this.display();
     }
 }

 public static void main(String[] args) {
     SortLab select = new SortLab();
     SortLab selectA = new SortLab();
     SortLab insert = new SortLab();
     SortLab insertA = new SortLab();

     System.out.println("Selection Sort");
     System.out.print("unsorted: ");
     select.display();
     select.selection();
     System.out.print("sorted:   ");
     select.display();
     System.out.println("SelectionA Sort");
     System.out.print("unsorted: ");
     selectA.display();
     selectA.selectionA();
     System.out.print("sorted:   ");
     selectA.display();
     System.out.println();
     System.out.println();
     System.out.println("Insertion Sort");
     System.out.print("unsorted: ");
     insert.display();
     insert.insertion();
     System.out.print("sorted:   ");
     insert.display();
     System.out.println("Insertion Sort with Explicit Shift");
     System.out.print("unsorted: ");
     insertA.display();
     insertA.insertion();
     System.out.print("sorted:   ");
     insertA.display();
}

Output 2

run:
Selection Sort
unsorted: 9  6  2  1  3  7  8  4  0  5  
interim:  0  6  2  1  3  7  8  4  9  5  
interim:  0  1  2  6  3  7  8  4  9  5  
interim:  0  1  2  6  3  7  8  4  9  5  
interim:  0  1  2  3  6  7  8  4  9  5  
interim:  0  1  2  3  4  7  8  6  9  5  
interim:  0  1  2  3  4  5  8  6  9  7  
interim:  0  1  2  3  4  5  6  8  9  7  
interim:  0  1  2  3  4  5  6  7  9  8  
interim:  0  1  2  3  4  5  6  7  8  9  
sorted:   0  1  2  3  4  5  6  7  8  9  
SelectionA Sort
unsorted: 9  0  5  7  2  8  4  3  1  6  
interim:  0  9  5  7  2  8  4  3  1  6  
interim:  0  1  5  7  2  8  4  3  9  6  
interim:  0  1  2  7  5  8  4  3  9  6  
interim:  0  1  2  3  5  8  4  7  9  6  
interim:  0  1  2  3  4  8  5  7  9  6  
interim:  0  1  2  3  4  5  8  7  9  6  
interim:  0  1  2  3  4  5  6  7  9  8  
interim:  0  1  2  3  4  5  6  7  9  8  
interim:  0  1  2  3  4  5  6  7  8  9  
sorted:   0  1  2  3  4  5  6  7  8  9  


Insertion Sort
unsorted: 3  0  5  2  6  4  7  9  1  8  
interim:  0  3  5  2  6  4  7  9  1  8  
interim:  0  3  5  2  6  4  7  9  1  8  
interim:  0  2  3  5  6  4  7  9  1  8  
interim:  0  2  3  5  6  4  7  9  1  8  
interim:  0  2  3  4  5  6  7  9  1  8  
interim:  0  2  3  4  5  6  7  9  1  8  
interim:  0  2  3  4  5  6  7  9  1  8  
interim:  0  1  2  3  4  5  6  7  9  8  
interim:  0  1  2  3  4  5  6  7  8  9  
sorted:   0  1  2  3  4  5  6  7  8  9  
Insertion Sort with Explicit Shift
unsorted: 1  9  3  8  5  7  6  4  0  2  
interim:  1  9  3  8  5  7  6  4  0  2  
interim:  1  3  9  8  5  7  6  4  0  2  
interim:  1  3  8  9  5  7  6  4  0  2  
interim:  1  3  5  8  9  7  6  4  0  2  
interim:  1  3  5  7  8  9  6  4  0  2  
interim:  1  3  5  6  7  8  9  4  0  2  
interim:  1  3  4  5  6  7  8  9  0  2  
interim:  0  1  3  4  5  6  7  8  9  2  
interim:  0  1  2  3  4  5  6  7  8  9  
sorted:   0  1  2  3  4  5  6  7  8  9    
BUILD SUCCESSFUL (total time: 1 second)

Conclusion

That's 2 of the 3 sorts you need to know about. Questions on the AP may show code and of course try to hide what is really going on. If there is an inner loop shifting multiple elements then placing the value in after the shift think insertion sort. The insertion sort above combines the compare and the shift together but the effect is the same. Selection sorts you should see a single swap of 2 values then back out to the main loop. I like to think of it as "select the lowest value and swap it to the current front of the line".

Merge Sort should be next but its implementation is simplified by recursion. So before we go into Merge Sort I want to revisit recursion in my next blog post. Then tackle merge sort. Then I will get back to finishing up blackjack.

You should also visit wikipedia they have some nice animations of how these sorts work.

References

  1. Aho, Alfred V., John E. Hopcroft, and Jeffrey D. Ullman. Data Structures and Algorithms. Reading, MA: Addison-Wesley, 1983.
  2. "Selection Sort." Wikipedia. Wikimedia Foundation, 25 Mar. 2013. Web. 26 Mar. 2013. http://en.wikipedia.org/wiki/Selectionsort
  3. "Insertion Sort." Wikipedia. Wikimedia Foundation, 22 Mar. 2013. Web. 26 Mar. 2013. http://en.wikipedia.org/wiki/Insertionsort
  4. Litvin, Maria, and Gary Litvin. Be Prepared for the AP Computer Science Exam in Java. Andover: Skylight, 2009.

Date: 2013-03-28T17:58-0400

Author: Nasty Old Dog

Monday, March 18, 2013

Blackjack Almost a Real Game

AP Computer Science Adding Some User Input/Output

AP Computer Science Adding Some User Input/Output

Introduction

When we last left our Blackjack program we had put in place a model for dealing with a deck of cards, Shuffling the deck and a way to distinguish 'hands' for dealer and player. Now let's scaffold in some user I/O (input/output). Sounds impressive but it's just a series of prints, printlns and getLines. To be able to repeat the process for multiple games (or hands) there will need to be a loop of some sort (keyword repeat at the beginning of the sentence is the give away for a loop).

I am trying to plow through this program for you so you have a fairly large project to look at. Since the target audience for these AP Computer Science Blogs are beginning programmers I am trying to get you to see the utility of what you have learned so far. I hope that your experience with computer science has been positive. It's really not that difficult a subject and for the thoughtful student provides a virtual world where almost anything is possible. The field is really limitless and is bound only by your imagination and time.

For those of you who have been turned off by the experience of taking AP Computer Science and feel you were crazy to think this was interesting, don't let this experience jade you. AP Computer Science is a one size fits all type of course with restrictions on what should do. It may be that your imagination finds the restrictions too limiting and burdensome. At the university level you will find Professors that love Computer Science so much they have chosen to specialize in the subject. I would give it another chance at the university level. You may find that the right instructor with a broad base of experience was all you needed to get your mind around the subject.

When you do take college courses remember you have at your disposal the Professor of the course and his or her teaching assistants. That means you have multiple people with exellent experience to help you master the subject. In High School AP there is the teacher alone, if you don't connect with their perspective you are out of luck. In college you will have professors, teaching assistants, and fellow students each with a different perspective. You should be able to find someone that can connect with you to help you master this subject.

The game loop pseudocode

The design process here is:

  • guess at the calls
  • get the structure of the code in place
  • then cut and paste into the IDE and see what the real calls are supposed to be

The Pseudo Code

Pay attention to the comments below they help in understanding what is going on

CardDeck card = new CardDeck();

String user_inp = new String("");
int bankroll = 1000;
int bet = 0;           // if the user bets 0 quit the game loop

// game loop just loop forever
while(true) {
  // Tell the user the amount of the bank roll 
  System.out.println("Bankroll = " + bankroll);
  // get bet
  System.out.print("Enter the amount you want to bet: ");
  user_inp = System.in.getLine();
  bet = Integer.toInt(user_inp);

  // bet == 0 is the signal to quit loop and end program
  if (bet == 0) { 
    break;
  }

  card.shuffle();

  card.dealPlayer();
  card.dealDealer();
  card.dealPlayer();
  card.dealDealer();

  card.displayHands();

  // Need a loop to handle HIT or STAND commands
  while(true) { 
    System.out.print("Player Hand hit or stand? ");
    user_inp = System.in.getLine();
    if (user_inp.equals("HIT")) {
      card.dealPlayer();
      card.displayHands();
    }
    else if (user_inp.equals("STAND")) {
      break;
    }
    else {
      // If we end up here it's because of a typo or wiseguy
      // print error response and go back to looping
      System.out.println("I don't understand: " + user_inp);
    }
  }

  // Manually control dealer hand the same way
  // We will swap this out for code that will run the dealer rules 
  // automatically
  while(true) { 
    System.out.print("Dealer Hand hit or stand? ");
    user_inp = System.in.getLine();
    if (user_inp.equals("HIT")) {
      card.dealDealer();
      card.displayHands();
    }
    else if (user_inp.equals("STAND")) {
      break;
    }
    else {
      // If we end up here it's because of a typo or wiseguy
      // print error response and go back to looping
      System.out.println("I don't understand: " + user_inp);
    }
  }

  // Code to score the game and settle the bet will go here

}

Pseudo code to real code

  • I need to use the Scanner class to get user input there is no System.in.getLine
    • I defined uinp to be a scanner for System.in
    • I replaced the System.in.getLine's with uinp.nextLine()
  • The String userinp doesn't need a constructor just " "
  • There is no toInt in the Integer class use getInteger instead
import java.util.Scanner;

public class CardDeck {

    int deck[] = new int[52];
    String faceVal = "A23456789TJQK";
    String suit = "HDSC";

    public CardDeck() {
        for (int i = 0; i < 52; i++) {
            deck[i] = i;
        }
    }

    void shuffle() {
        int rindex;
        int swap;

        for (int i = 0; i < 52; i++) {
            // each time through the loop there are less numbers to randomize
            // 52 - i to be exact. But then everything from 0 to i-1 has already
            // been selected at random so add i to the random number to get the
            // appropriate index
            rindex = (int) ((Math.random() * ((double) (52 - i))) + i);
            swap = deck[i];
            deck[i] = deck[rindex];
            deck[rindex] = swap;
        }
    }

    public String getCardText(int crd) {
        int card_val = crd % 13;
        int card_suit = crd % 4;
        return this.faceVal.substring(card_val, card_val + 1)
                + this.suit.substring(card_suit, card_suit + 1);
        //return this.faceVal.substring(card_val, card_val+1).concat(
        //this.suit.substring(card_suit, card_suit+1));
    }

    void display() {
        int card_val;
        int card_suit;
        for (int i = 0; i < 52; i++) {
            //card_val = deck[i]%13;
            //card_suit = deck[i]%4;
            System.out.print(this.getCardText(deck[i]) + " ");
        }
        System.out.println();
    }
    int playerHand[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int dealerHand[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int dcards = 0; // the number of cards in the dealer hand so far
    int pcards = 0; // the number of cards in the player hand so far
    int deckidx = 0; // the location of the next card to be dealt

    public int deal() {
        if (this.deckidx < 52) {
            return this.deck[this.deckidx++]; // return the top card and increment to the next card
        } else {
            return this.deck[this.deckidx - 1];
        }
    }

    public void dealPlayer() {
        this.playerHand[pcards] = deal();
        this.pcards++;
    }

    public void dealDealer() {
        this.dealerHand[dcards] = deal();
        this.dcards++;
    }

    public void displayHands() {
        System.out.println("Player Hand  ");
        for (int i = 0; i < this.pcards; i++) {
            System.out.print(this.getCardText(this.playerHand[i]) + " ");
        }
        System.out.println();
        System.out.println("Dealer Hand:  ");
        for (int j = 0; j < this.dcards; j++) {
            System.out.print(this.getCardText(this.dealerHand[j]) + " ");
        }
        System.out.println();
        System.out.println();
    }

    public static void main(String[] args) {
        CardDeck card = new CardDeck();

        card.display();
        card.shuffle();
        card.display();

        card.dealPlayer();
        card.dealDealer();
        card.dealPlayer();
        card.dealDealer();

        card.displayHands();
        // Start game intialize bankroll to 500
        // Start game loop <CR> on bet means quit
        // CardDeck card = new CardDeck();

        String user_inp = " ";
        int bankroll = 1000;
        int bet = 0;           // if the user bets 0 quit the game loop

        // Need a Scanner for user input
        Scanner uinp = new Scanner(System.in);

        // game loop just loop forever
        while (true) {
            // Tell the user the amount of the bank roll 
            System.out.println("Bankroll = " + bankroll);
            // get bet
            System.out.print("Enter the amount you want to bet: ");
            user_inp = uinp.nextLine();
            bet = Integer.getInteger(user_inp);

            // bet == 0 is the signal to quit loop and end program
            if (bet == 0) {
                break;
            }

            card.shuffle();

            card.dealPlayer();
            card.dealDealer();
            card.dealPlayer();
            card.dealDealer();

            card.displayHands();

            // Need a loop to handle HIT or STAND commands
            while (true) {
                System.out.print("Player Hand hit or stand? ");
                user_inp = uinp.nextLine();
                if (user_inp.equals("HIT")) {
                    card.dealPlayer();
                    card.displayHands();
                } else if (user_inp.equals("STAND")) {
                    break;
                } else {
                    // If we end up here it's because of a typo or wiseguy
                    // print error response and go back to looping
                    System.out.println("I don't understand: " + user_inp);
                }
            }

            // Manually control dealer hand the same way
            // We will swap this out for code that will run the dealer rules 
            // automatically
            while (true) {
                System.out.print("Dealer Hand hit or stand? ");
                user_inp = uinp.nextLine();
                if (user_inp.equals("HIT")) {
                    card.dealDealer();
                    card.displayHands();
                } else if (user_inp.equals("STAND")) {
                    break;
                } else {
                    // If we end up here it's because of a typo or wiseguy
                    // print error response and go back to looping
                    System.out.println("I don't understand: " + user_inp);
                }
            }

            // Code to score the game and settle the bet will go here

        }
    }
}

Output

run:
AH 2D 3S 4C 5H 6D 7S 8C 9H TD JS QC KH AD 2S 3C 4H 5D 6S 7C 8H 9D TS JC QH KD AS 2C 3H 4D 5S 6C 7H 8D 9S TC JH QD KS AC 2H 3D 4S 5C 6H 7D 8S 9C TH JD QS KC 
5S AS 9C 4H QS 8D 7H 7D AC JH 9D TS KD QD 2H 6S 4S KC 2C 7C QC 6D 3H 3S 5C QH 6H KS 8C 4C 2D 5D KH TD 9H JC 8H 4D 5H 2S JS 7S 6C 8S TH JD 3D TC AH 3C AD 9S 
Player Hand  
5S 9C 
Dealer Hand:  
AS 4H 

Bankroll = 1000
Enter the amount you want to bet: 10
Exception in thread "main" java.lang.NullPointerException
        at apcompsci.CardDeck.main(CardDeck.java:129)
Java Result: 1
BUILD SUCCESSFUL (total time: 19 seconds)

Debugging

If you use the program above 129 is not the right line number I have extra comments produced in the IDE that I don't cut and paste. So the problem is at the bet = Integer.getInteger line. It seems that our user input is not working so well. I'm not sure what is wrong here. Stepping through the code in the debugger shows the 'userinp' variable gets assigned "10", I am probably using the Integer class incorrectly. Let's take a different tact.

For AP purposes you can use the Scanner class routines (nextInt). That seems to work so I changed the following:

//            user_inp = uinp.nextLine();
//            bet = Integer.getInteger(user_inp).intValue();
            bet = uinp.nextInt();

Output 2

run:
AH 2D 3S 4C 5H 6D 7S 8C 9H TD JS QC KH AD 2S 3C 4H 5D 6S 7C 8H 9D TS JC QH KD AS 2C 3H 4D 5S 6C 7H 8D 9S TC JH QD KS AC 2H 3D 4S 5C 6H 7D 8S 9C TH JD QS KC 
7S 6H 2C 4S 2S 4D TH 5H QH AH 7H TD 3C JC 4C AC KH KD TC 9H 6C 5S 2H 3H 2D QC 3D KC JS 6S 8C 8S 9D TS QD 7D KS 8H 5C AD JD 7C 4H 9C 6D 3S QS 5D JH AS 9S 8D 
Player Hand  
7S 2C 
Dealer Hand:  
6H 4S 

Bankroll = 1000
Enter the amount you want to bet: 10
Player Hand  
7S 2C 6D AD 
Dealer Hand:  
6H 4S JD 9D 

Player Hand hit or stand? I don't understand: 
Player Hand hit or stand? HIT
Player Hand  
7S 2C 6D AD JH 
Dealer Hand:  
6H 4S JD 9D 

Player Hand hit or stand? STAND
Dealer Hand hit or stand? HIT
Player Hand  
7S 2C 6D AD JH 
Dealer Hand:  
6H 4S JD 9D 5S 

Dealer Hand hit or stand? STAND
Bankroll = 1000
Enter the amount you want to bet: 0
BUILD SUCCESSFUL (total time: 34 seconds)

There is one major problem I left the old code from the previous blog in as a debugging aid. That's why there are four (4) cards instead of two (2) when we play the game. I need to reset the hands to no cards before we start the game.

It also looks like the CR after I input the bet gets registered as input. I will leave this error alone since it is a minor annoyance and tests the input error portion of the code (I will try to fix it in a later post).

Let's create a resetHands method. It will set all the cards in the hands to 0 and reset the card indexes for each hand. Let's place it in the code so it fixes the above problem. Let's also assume we win every hand and modify the bankroll accordingly.

public void resetHands()
{
  for (int i = 0; i < playerHand.length; i++) {
    playerHand[i] = 0;
    dealerHand[i] = 0;
  }
  dcards = 0;
  pcards = 0;
}

// Now after the first displayHands add this method call before we start:
        // Reset hands
        card.resetHands();

        // CardDeck card = new CardDeck();

        String user_inp = " ";

// Then at the end of the main loop lets add the following code:
            // Code to score the game and settle the bet will go here
            // For now assume we win every time
            bankroll = bankroll + bet;

            // reset hands to play a new game
            card.resetHands();

Output 3

run:
AH 2D 3S 4C 5H 6D 7S 8C 9H TD JS QC KH AD 2S 3C 4H 5D 6S 7C 8H 9D TS JC QH KD AS 2C 3H 4D 5S 6C 7H 8D 9S TC JH QD KS AC 2H 3D 4S 5C 6H 7D 8S 9C TH JD QS KC 
3S 2S QD 8H QC 5D AH TC 7C TD 9D 5S QH 4H JH KD 6C 2D 6H QS 6S JC TH 9S 4S 3H 2H AD KH KS 3C AS KC 5H 9C 7H AC JD 6D 4C 8D 9H 8S JS 2C 7S TS 5C 8C 7D 4D 3D 
Player Hand  
3S QD 
Dealer Hand:  
2S 8H 

Bankroll = 1000
Enter the amount you want to bet: 10
Player Hand  
5C 8S 
Dealer Hand:  
8D 4C 

Player Hand hit or stand? I don't understand: 
Player Hand hit or stand? HIT
Player Hand  
5C 8S 6C 
Dealer Hand:  
8D 4C 

Player Hand hit or stand? STAND
Dealer Hand hit or stand? HIT
Player Hand  
5C 8S 6C 
Dealer Hand:  
8D 4C TC 

Dealer Hand hit or stand? STAND
Bankroll = 1010
Enter the amount you want to bet: 0
BUILD SUCCESSFUL (total time: 40 seconds)

Not bad we actually won the hand for real (your results may vary). Under the rules of Blackjack the dealer had to HIT the 8,4 (12 points) since it's 16 or less. But even if we had lost we increase the bankroll anyway for now.

Conclusion

So this isn't quite polished. The program needs to score each hand after a deal and it must step through the dealer rules. It should also hide one card of the dealer until the player 'STANDS'. But the user can now step through some games and do the calculations themselves to see if it would be a winning or losing game. Don't worry we will massage this into a useable program.

To be continued.

Final Code

import java.util.Scanner;

public class CardDeck {

    int deck[] = new int[52];
    String faceVal = "A23456789TJQK";
    String suit = "HDSC";

    public CardDeck() {
        for (int i = 0; i < 52; i++) {
            deck[i] = i;
        }
    }

    void shuffle() {
        int rindex;
        int swap;

        for (int i = 0; i < 52; i++) {
            // each time through the loop there are less numbers to randomize
            // 52 - i to be exact. But then everything from 0 to i-1 has already
            // been selected at random so add i to the random number to get the
            // appropriate index
            rindex = (int) ((Math.random() * ((double) (52 - i))) + i);
            swap = deck[i];
            deck[i] = deck[rindex];
            deck[rindex] = swap;
        }
    }

    public String getCardText(int crd) {
        int card_val = crd % 13;
        int card_suit = crd % 4;
        return this.faceVal.substring(card_val, card_val + 1)
                + this.suit.substring(card_suit, card_suit + 1);
        //return this.faceVal.substring(card_val, card_val+1).concat(
        //this.suit.substring(card_suit, card_suit+1));
    }

    void display() {
        int card_val;
        int card_suit;
        for (int i = 0; i < 52; i++) {
            //card_val = deck[i]%13;
            //card_suit = deck[i]%4;
            System.out.print(this.getCardText(deck[i]) + " ");
        }
        System.out.println();
    }
    int playerHand[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int dealerHand[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    int dcards = 0; // the number of cards in the dealer hand so far
    int pcards = 0; // the number of cards in the player hand so far
    int deckidx = 0; // the location of the next card to be dealt

    public int deal() {
        if (this.deckidx < 52) {
            return this.deck[this.deckidx++]; // return the top card and increment to the next card
        } else {
            return this.deck[this.deckidx - 1];
        }
    }

    public void dealPlayer() {
        this.playerHand[pcards] = deal();
        this.pcards++;
    }

    public void dealDealer() {
        this.dealerHand[dcards] = deal();
        this.dcards++;
    }

    public void resetHands() {
        for (int i = 0; i < playerHand.length; i++) {
            playerHand[i] = 0;
            dealerHand[i] = 0;
        }
        dcards = 0;
        pcards = 0;
    }

    public void displayHands() {
        System.out.println("Player Hand  ");
        for (int i = 0; i < this.pcards; i++) {
            System.out.print(this.getCardText(this.playerHand[i]) + " ");
        }
        System.out.println();
        System.out.println("Dealer Hand:  ");
        for (int j = 0; j < this.dcards; j++) {
            System.out.print(this.getCardText(this.dealerHand[j]) + " ");
        }
        System.out.println();
        System.out.println();
    }

    public static void main(String[] args) {
        CardDeck card = new CardDeck();

        card.display();
        card.shuffle();
        card.display();

        card.dealPlayer();
        card.dealDealer();
        card.dealPlayer();
        card.dealDealer();

        card.displayHands();
        // Reset hands
        card.resetHands();

        // CardDeck card = new CardDeck();

        String user_inp = " ";
        int bankroll = 1000;
        int bet = 0;           // if the user bets 0 quit the game loop

        // Need a Scanner for user input
        Scanner uinp = new Scanner(System.in);

        // game loop just loop forever
        while (true) {
            // Tell the user the amount of the bank roll 
            System.out.println("Bankroll = " + bankroll);
            // get bet
            System.out.print("Enter the amount you want to bet: ");
//            user_inp = uinp.nextLine();
//            bet = Integer.getInteger(user_inp).intValue();
            bet = uinp.nextInt();
            // bet == 0 is the signal to quit loop and end program
            if (bet == 0) {
                break;
            }

            card.shuffle();

            card.dealPlayer();
            card.dealDealer();
            card.dealPlayer();
            card.dealDealer();

            card.displayHands();

            // Need a loop to handle HIT or STAND commands
            while (true) {
                System.out.print("Player Hand hit or stand? ");
                user_inp = uinp.nextLine();
                if (user_inp.equals("HIT")) {
                    card.dealPlayer();
                    card.displayHands();
                } else if (user_inp.equals("STAND")) {
                    break;
                } else {
                    // If we end up here it's because of a typo or wiseguy
                    // print error response and go back to looping
                    System.out.println("I don't understand: " + user_inp);
                }
            }

            // Manually control dealer hand the same way
            // We will swap this out for code that will run the dealer rules 
            // automatically
            while (true) {
                System.out.print("Dealer Hand hit or stand? ");
                user_inp = uinp.nextLine();
                if (user_inp.equals("HIT")) {
                    card.dealDealer();
                    card.displayHands();
                } else if (user_inp.equals("STAND")) {
                    break;
                } else {
                    // If we end up here it's because of a typo or wiseguy
                    // print error response and go back to looping
                    System.out.println("I don't understand: " + user_inp);
                }
            }

            // Code to score the game and settle the bet will go here
            // For now assume we win every time
            bankroll = bankroll + bet;

            // reset hands to play a new game
            card.resetHands();
        }
    }
}

Author: Nasty Old Dog

Friday, March 8, 2013

Blackjack (adding more features)

AP Computer Science Blackjack Continued

AP Computer Science Blackjack Continued

Representing Dealer and Player Hands

Last time we created a CardDeck class to simulate a deck of cards. Now we need a way to deal those cards and store them in 'hands' for a player and a dealer.

  • Use arrays for the dealer and player hands
  • put the arrays in CardDeck class.
  • create 'dealPlayer' and 'dealDealer' methods to store cards in the arrays associated with each hand
  • Use int variables to track the indexs of the hands and the deck
    • increment the index after each deal so we get the next card from the deck
    • increment the index for the appropriate hand
  • create a method to display the hands with only one card turned over on the dealer
  • create a method to display all the hands so that a winner can be determined by the user for now
  • Hold off on creating a hand scoring mechanism
int playerHand[20];
int dealerHand[20];
int dcards = 0; // the number of cards in the dealer hand so far
int pcards = 0; // the number of cards in the player hand so far
int deckidx = 0; // the location of the next card to be dealt

public int deal()
{
  if (deckidx < 52) {
    return deck[deckidx++]; // return the top card and increment to the next card
  }
  else {
    return deck[deckidx-1];
  }
}

public void dealPlayer()
{
  playerHand[pcards] = deal();
  pcards++;
}

public void dealDealer()
{
  dealerHand[dcards] = deal();
  dcards++;
}

public void displayHands()
{
  System.out.println("Player Hand  ");
  for (int i = 0; i < pcards; i++) {
    System.out.print(playerHand[i]+" ");
  }
  System.out.println();
  System.out.println("Dealer Hand:  ");
  for (int j = 0; j < dcards; j++) {
    System.out.print(dealerHand[j],+" ");
  }
  System.out.println();
  System.out.println();
}

Bugs

I have a ',' in the print statement in the 'displayHands' routine. I have forgotten my style requirements that I use 'this' prepended to all field usage. I need to initialize the arrays for hand.

Fixed code with usage in 'main' method

int playerHand[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int dealerHand[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int dcards = 0; // the number of cards in the dealer hand so far
int pcards = 0; // the number of cards in the player hand so far
int deckidx = 0; // the location of the next card to be dealt

public int deal()
{
  if (this.deckidx < 52) {
    return this.deck[this.deckidx++]; // return the top card and increment to the next card
  }
  else {
    return this.deck[this.deckidx-1];
  }
}

public void dealPlayer()
{
  this.playerHand[pcards] = deal();
  this.pcards++;
}

public void dealDealer()
{
  this.dealerHand[dcards] = deal();
  this.dcards++;
}

public void displayHands()
{
  System.out.println("Player Hand  ");
  for (int i = 0; i < this.pcards; i++) {
    System.out.print(this.playerHand[i]+" ");
  }
  System.out.println();
  System.out.println("Dealer Hand:  ");
  for (int j = 0; j < this.dcards; j++) {
    System.out.print(this.dealerHand[j] +" ");
  }
  System.out.println();
  System.out.println();
}

    public static void main(String[] args) {
        CardDeck card = new CardDeck();

        card.display();
        card.shuffle();
        card.display();

        card.dealPlayer();
        card.dealDealer();
        card.dealPlayer();
        card.dealDealer();

        card.displayHands();
    }

Make a card convert routine

The above example does not display the text based card. It would be nice to have a method that converts the integer representation into the text based representation. This can then be used in both the hand display method and the deck display method. Good design too use the same underlying method in both places means less chance for error. If there is an error found localizing it to one method means it's fixed everywhere when the bug is fixed in the conversion method. Call the method 'getCardText' and the method can just return a String (right? makes sense, it's just going to be a couple of characters). Let's modify the deck display routine (i.e. the 'display' method) to make use of this conversion routine as well (don't forget I use method, routine, and function interchangeably I hope it's not too confusing).

public String getCardText (int crd) 
{
  int card_val = crd%13;
  int card_suit = crd%4;
  return this.faceVal.substring(card_val,card_val+1) + 
         this.suit.substring(card_suit,card_suit+1);    // Why does this work??
}

Digression on the String Class

I flagged the return statement with a comment. Do you the reader understand why that code actually works? There is really a great deal of Java compiler magic happening in that one statement. It's the same magic that happens implicitly in a System.out.print method call. 'faceVal' and 'suit' are 'String' fields in the CardDeck class. 'substring' is a method in the 'String' class that returns a 'String' class (or object if you prefer). The 2 calls to substring (one for 'faceVal' and the other for 'suit') will get done first. Then the compiler will be faced with what to do with 'String' + 'String'. It turns out that the '+' operator has built in meaning when dealing with Strings. It will concatenate the 2 strings together (which essential glues them together) to form a new String. It would be the same as if we used the 'concat' method of the 'String' class:

return this.faceVal.substring(card_val,card_val+1).concat(this.suit.substring(card_suit,card_suit+1));

Either return statement works. I prefer the '+' operator because it gives me a natural split to place the long method calls on separate lines.

Back to the final code

So now fixing up all the routines the code is now:

public class CardDeck {

    int deck[] = new int[52];
String faceVal = "A23456789TJQK";
String suit = "HDSC";

    public CardDeck() {
        for (int i = 0; i < 52; i++) {
            deck[i] = i;
        }
    }

    void shuffle() {
        int rindex;
        int swap;

        for (int i = 0; i < 52; i++) {
            // each time through the loop there are less numbers to randomize
            // 52 - i to be exact. But then everything from 0 to i-1 has already
            // been selected at random so add i to the random number to get the
            // appropriate index
            rindex = (int) ((Math.random() * ((double) (52 - i))) + i);
            swap = deck[i];
            deck[i] = deck[rindex];
            deck[rindex] = swap;
        }
    }

    public String getCardText (int crd) 
{
  int card_val = crd%13;
  int card_suit = crd%4;
  return this.faceVal.substring(card_val,card_val+1) + 
         this.suit.substring(card_suit,card_suit+1);
}

    void display() {
        int card_val;
        int card_suit;
        for (int i = 0; i < 52; i++) {
            //card_val = deck[i]%13;
            //card_suit = deck[i]%4;
            System.out.print(this.getCardText(deck[i]) + " ");
        }
        System.out.println();
    }

int playerHand[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int dealerHand[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int dcards = 0; // the number of cards in the dealer hand so far
int pcards = 0; // the number of cards in the player hand so far
int deckidx = 0; // the location of the next card to be dealt

public int deal()
{
  if (this.deckidx < 52) {
    return this.deck[this.deckidx++]; // return the top card and increment to the next card
  }
  else {
    return this.deck[this.deckidx-1];
  }
}

public void dealPlayer()
{
  this.playerHand[pcards] = deal();
  this.pcards++;
}

public void dealDealer()
{
  this.dealerHand[dcards] = deal();
  this.dcards++;
}

public void displayHands()
{
  System.out.println("Player Hand  ");
  for (int i = 0; i < this.pcards; i++) {
    System.out.print(this.getCardText(this.playerHand[i])+" ");
  }
  System.out.println();
  System.out.println("Dealer Hand:  ");
  for (int j = 0; j < this.dcards; j++) {
    System.out.print(this.getCardText(this.dealerHand[j]) +" ");
  }
  System.out.println();
  System.out.println();
}

    public static void main(String[] args) {
        CardDeck card = new CardDeck();

        card.display();
        card.shuffle();
        card.display();

        card.dealPlayer();
        card.dealDealer();
        card.dealPlayer();
        card.dealDealer();

        card.displayHands();
    }
}

Output

AH 2D 3S 4C 5H 6D 7S 8C 9H TD JS QC KH AD 2S 3C 4H 5D 6S 7C 8H 9D TS JC QH KD AS 2C 3H 4D 5S 6C 7H 8D 9S TC JH QD KS AC 2H 3D 4S 5C 6H 7D 8S 9C TH JD QS KC 
8C 6H 4D 4S 5S 5C 2C KD 2S 3D 6C 9D 7S 8S QS 5H QD 3S JS 3H 7D TD KH TC 7C 9H 8H 8D TS JH QH 4C AC 9S 5D 9C AS 4H JD QC TH 2H 2D JC KS KC 6S 6D 3C AH AD 7H 
Player Hand  
8C 4D 
Dealer Hand:  
6H 4S 

Conclusion

Not bad. The class can shuffle, deal hands, and display hands. In the next installment let's work on the 'main' method to accept a bankroll and bets. Have it accept input to HIT or STAND on the player hand. The dealer can just take 1 card for now as it's hand playing rule. Hopefully we can simulate a game

Author: Nasty Old Dog

Thursday, March 7, 2013

Modulo Part II

AP Computer Science Modulo Part II

AP Computer Science Modulo Part II

Fun with Modulo

Back to uses of modulo. Rather than expound on the virtues of modulo.

Let's make a simple blackjack game.

This will be a multi-part blog so first let's define what the game will be. Then start building the pieces.

Simple Blackjack Rules

  • Dealer and player try to make a hand as close to 21 without going over
  • Player goes first
    • may HIT (take a card) or STAND (done dealer's turn)
  • Dealer goes next must HIT or STAND according to rules
    • Hand <= 16 dealer must HIT
    • Hand > 16 dealer must STAND
  • Any hand that goes over 21 is BUST and loses immediately regardless if the dealer hasn't dealt his hand
  • Player starts with a Bankroll (total amount of money he has to bet with)
  • Player places a bet before the cards are dealt.
  • Player may bet any amount up to the value of his bankroll

Task

Design a text based input and output program to play the game of blackjack according to the rules above. Use single letter designations for the type of card (A,2,3,..,8,9,T,J,Q,K) and single letter for the suit (H,D,S,C).

You may only use a one dimensional array for the storage of a deck of cards

You must be able to shuffle the deck of cards randomly using the random number generator supplied by Java with no repeats.

Design Analysis

  • loop until player hits return rather than a value for a bet (ie. not betting ends the game)
  • print a prompt with the current bankroll when asking for a bet
  • deal hands displaying both cards of the player and XX for the hole card of dealer
  • accept user input H or S for HIT or STAND check for bust after each HIT
  • Display the hand with all the cards after each HIT
  • When S start the dealer's play hitting or standing according to the rules
  • At each HIT of the dealer redisplay the hands
  • when dealer stands determine the winner
  • update bankroll according to whether player won or lost
  • ** use only a one dimensional array to store the deck of cards **
  • Need a shuffle routine (it can't just be random()*52 I may get duplicates)

Where to Start: A Deck of Cards

  • The deck of cards there are 52 cards lets not worry about suits represent them by a number from 0 - 51
  • Let's create a CardDeck object to house them in.
  • The constructor will just initialize the one dimensional array in cardinal order
  • Let's put a shuffle method to shuffle the deck
class CardDeck {
int deck[] = new int[52];

public CardDeck() {
  for(int i=0; i < 52; i++) {
    deck[i] = i;
  }
}

void display()
{
  for(int i=0; i < 52; i++) {
    System.out.print(i + " ");
  }
  System.out.println();
}

public static void main(String[] args)
{
  CardDeck card = new CardDeck();

  card.display();
}

And the output from the above program:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 

SHUFFLE

Obviously I want to use the random number generator but how? I could randomly select a number from 0 to 51 and move it to a new array that would become the shuffled deck. I could then shift all the values down and then pick a random number from 0 to 50, and so on until I've randomly moved all the values.

But think for a second what if I just swap the random value for the one at the end. Then pick again from 0 - 50 (ie. n-1) and so on. But then I have to do descending loops which I don't like to do. But think for a minute. If I move throught the array one at a time starting at 0 (like a for loop would) I could pick a random index and then swap the ith index with the random index. This way I just need to pick a random number between i and 51 swap and repeat the loop.

void shuffle()
{
  int rindex;
  int swap;

  for (i = 0; i <= 52; i++) {
    // this will probably need some debugging 
    rindex = Math.rand()*(52-i)+i;
    swap = card[i];
    card[i] = card[rindex];
    card[rindex] = swap;
  }
}

The random number generator needed some debugging and some casting 1. I will just display the code after debug. I did it again on the 'display' routine too, I forgot the deck[] reference and just displayed i instead. So here is the class definition so far:

public class CardDeck {

    int deck[] = new int[52];

    public CardDeck() {
        for (int i = 0; i < 52; i++) {
            deck[i] = i;
        }
    }

    void shuffle() {
        int rindex;
        int swap;

        for (int i = 0; i < 52; i++) {
            // each time through the loop there are less numbers to randomize
            // 52 - i to be exact. But then everything from 0 to i-1 has already
            // been selected at random so add i to the random number to get the
            // appropriate index
            rindex = (int) ((Math.random() * ((double) (52 - i))) + i);
            swap = deck[i];
            deck[i] = deck[rindex];
            deck[rindex] = swap;
        }
    }

    void display() {
        for (int i = 0; i < 52; i++) {
            System.out.print(deck[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        CardDeck card = new CardDeck();

        card.display();
        card.shuffle();
        card.display();
    }
}

Output

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 
43 15 34 41 27 14 17 2 3 36 48 12 45 7 37 4 39 13 44 8 16 29 23 46 19 10 18 42 51 1 25 0 38 20 28 31 35 9 50 21 40 11 30 32 47 24 22 6 49 26 5 33 

So how are we going to get the suits and face values of the cards from a single number? If you guessed modulo because I'm writing about modulo you're correct. There are 13 different cards for each suit and 4 different suits. It will be as easy as taking the card number and modulo 13 for value and modulo 4 for suit. To represent them in text in a more card appropriate way let's create 2 strings to hold the text values:

String faceVal = "A23456789TJQK";
String suit = "HDSC";

Then change 'display' to print the 2 character representation of each card.

void display() {
    int card_val;
    int card_suit;
    for (int i = 0; i < 52; i++) {
        card_val = deck[i]%13;
        card_suit = deck[i]%4;
        System.out.print(this.faceVal.substring(card_val,card_val+1) + 
                          this.suit.substring(card_suit,card_suit+1) + " ");
    }
    System.out.println();
}

Output of cards in text

AH 2D 3S 4C 5H 6D 7S 8C 9H TD JS QC KH AD 2S 3C 4H 5D 6S 7C 8H 9D TS JC QH KD AS 2C 3H 4D 5S 6C 7H 8D 9S TC JH QD KS AC 2H 3D 4S 5C 6H 7D 8S 9C TH JD QS KC 
9S 9C TS 9D 7D KC 5H 4C AH JD 6S QC QS 5S AC AD JS 2C 3S 5C 3H 8S 6D KS TH 5D 7C 3D JH JC 3C TC 6C 8H 2S 2D QH AS 6H KH 4H QD 4S 7S 4D TD KD 2H 8C 7H 8D 9H 

The output of your program should be the same for the top line when you initialize the deck. But you should get a different second line the results after a shuffle has taken place. That's because different computers will have different random number sequences depending on what you random seed is and how many times you run the program.

The Program So Far

public class CardDeck {

    int deck[] = new int[52];
String faceVal = "A23456789TJQK";
String suit = "HDSC";

    public CardDeck() {
        for (int i = 0; i < 52; i++) {
            deck[i] = i;
        }
    }

    void shuffle() {
        int rindex;
        int swap;

        for (int i = 0; i < 52; i++) {
            // each time through the loop there are less numbers to randomize
            // 52 - i to be exact. But then everything from 0 to i-1 has already
            // been selected at random so add i to the random number to get the
            // appropriate index
            rindex = (int) ((Math.random() * ((double) (52 - i))) + i);
            swap = deck[i];
            deck[i] = deck[rindex];
            deck[rindex] = swap;
        }
    }

    void display() {
        int card_val;
        int card_suit;
        for (int i = 0; i < 52; i++) {
            card_val = deck[i]%13;
            card_suit = deck[i]%4;
            System.out.print(this.faceVal.substring(card_val,card_val+1) + 
                              this.suit.substring(card_suit,card_suit+1) + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        CardDeck card = new CardDeck();

        card.display();
        card.shuffle();
        card.display();
    }
}

Next Steps

We've only just begun. In the next part we will work on how we deal hands to the player and dealer. I'm going to try to do this in one class definition only. Yes, that's poor object oriented design but let's see what that would look like and then for the final part let's refactor the program into a more appropriate object oriented example.

(To Be Continued)

Footnotes:

1 Casting
The compiler is able to make some decisions of how to represent various base types as other base types. For instance double to int. A double is what we think of as a decimal number. The compiler with a 'casting' directive can return just the whole number portion of the decimal number. Placing the base type in parenthesis instructs the computer to make that modification.
For example: (int) 32.25 → 32
Likewise: (double) 32 → 32.0
This is a nice way of telling the compiler you are purposefully looking for it to make those modifications.

Author: Nasty Old Dog