Showing posts with label AP Java Subset. Show all posts
Showing posts with label AP Java Subset. Show all posts

Sunday, April 28, 2013

AP Computer Science Study Guide as Computer Program Take 2

AP Computer Science Study Guide Take 2 <![CDATA[/*>

AP Computer Science Study Guide Take 2

Introduction

This guide was started in a previous article with comments for language elements an AP Student should know and be able to give a code example. This incantation of the same topic fills in most of the blanks with coding examples. If you were a good student you should be able to compare yours to mine. If you are a lazy student (meaning you didn't try to add any of your own code to the study guide) you better look through the code examples carefully and make sure they look familiar to you.
How to use this guide:
  • Pull the code into your IDE in its own project and run the program.
  • Generate the javadoc for the project. There should be a menu command to do it. In netbeans in was found in the run menu. For eclipse users if you can't find a quick web search should give you an answer.
  • Read through the code. The comments tell the story of what is going on.
  • Print out
    • the JavaDoc
    • the code
    • the output
  • Place them side by side on a large table and look through line by line and find where things are happening and why.

Things to look for

Different Types of Java Comments

The AP overview indicates you should be aware of the various types of comments. The most complex is the Javadoc style block comment. It contains @param and @return metafunctions in them. These comments start with /** and have *'s beginning each line with a terminating */ (on the last line). If they occur just before a method or class declaration the text within the comment will appear in the generated Javadoc. There are 2 other forms of comments one the // is used extensively in the APSubset code. The regular block comment /* . . . */ is shown only once.
The reason to point this out to you is that large portions of the code have to be used to engage the Java comments in an insignificant way. Where most of the java code examples can be accomplished with a few lines of code and a few output statements.

Method overloading

This functionality is spread in 2 different sections of code. The reverse method is defined twice. Once for Strings and then for integers. It is then used in the main method showing how the call signatures are the same and only the parameters change.

Exceptions

This could almost be done within the main method alone except that you also need to know about throwing an Exception. For this I created a small method that looks at its 'int' input parameter and throws an Exception if the parameter is the 'int' 3. Otherwise it just prints some diagnostic text to let you know it was called. The AP document was not too specific about which 'Exception's you should know about. I picked 3 that I thought you may have come across already in your projects. The fourth 'Exception' used is the parent class for Exceptions. Using this class is a useful way to catch Exceptions when your not sure which ones are likely to be thrown.
The reason for try-catch-finally and 'Exceptions' are to allow a program to either die gracefully or recover from an error. They are used extensively in large programming projects and Java does a nice job of integrating them in a modular way.
The 'finally' clause is run after every exception 'catch' clause has completed. In the code set up in APSubset the try catch block is run in a loop. The loop is set up to simulate a different error during each iteration. In a more robust program the try-catch block may be around your entire code. Remember most of the time Exceptions are things to avoid in the design of your code. You put them in because you may not be aware of every error scenario that could occur. In a small example such as this I had to force things to happen in a very small space. The idea behind 'finally' is that it gives you a guarenteed exit point from any Exception. A place where you can reset things or decide that the error involved was too grave and you must terminate the program. It's a place where common error handling or recovery can be done.
In the exception code there is a line commented out. It does a divide by zero but it is outside the try-catch block. Uncomment it in the IDE and run the code. You should find that the program will terminate there and no other statements past that point will be executed. Now compare that with the way the zero divide works inside the try-catch block. That should give you an idea of the utility of the Exception handling facilities in Java.

APSubset.java

The code is 600+ lines of code so rather than place it in the text of the article I have made it into a downloadable file. Go ahead and download it and run it yourself in your own Java IDE.
APSubset.java

Output (Run from Netbeans IDE)

run:
APSubset: BASIC TYPES
APSubset: int a = 0
APSubset: double b = 0.0
APSubset: boolean c = false
APSubset: 

APSubset: BASIC OPERATORS
APSubset: int a = 1 + 2 = 3
APSubset: double b = 2.0 + 3.5 = 5.5
APSubset: int a = 2 - 3 = -1
APSubset: double b = 2.0 - 3.5 = -1.5
APSubset: int a = 2 * 3 = 6
APSubset: double b = 2.0 * 3.5 = 7.0
APSubset: int a = 3 / 2 = 1
APSubset: double b = 3.5 / 2.0 = 1.75
APSubset: int a = 17 % 5 = 2
APSubset: double b = 17.0 % 6.0 = 5.0
APSubset: 

APSubset: Pre/Post-increment and Pre/Post-decrement
APSubset: int a = 2
APSubset: a++ = 2
APSubset: int a = 3
APSubset: ++a = 4
APSubset: int a = 4
APSubset: a-- = 4
APSubset: int a = 3
APSubset: --a = 2
APSubset: int a = 2
APSubset: double b = 5.0
APSubset: b++ = 5.0
APSubset: double b = 6.0
APSubset: ++b = 7.0
APSubset: double b = 7.0
APSubset: b-- = 7.0
APSubset: double b = 6.0
APSubset: --b = 5.0
APSubset: double b = 5.0
APSubset: 

APSubset: Assignment operators +=, -=, *=, /=, %=
APSubset: int a = 13
APSubset: double b = 13.0
APSubset: int a += 7 = 20
APSubset: double b += 7.5 = 20.5
APSubset: int a -= 3 = 17
APSubset: double b -= 3.5 = 17.0
APSubset: int a *= 2 = 34
APSubset: double b *= 2.0 = 34.0
APSubset: int a /= 2 = 17
APSubset: double b /= 2.0 = 17.0
APSubset: int a %= 5 = 2
APSubset: double b %= 6.0 = 5.0
APSubset: boolean c = 1 == 1 = true
APSubset: boolean c = 2 != 3 = true
APSubset: boolean c = 2 < 1 = false
APSubset: boolean c = 2 < 3 = true
APSubset: boolean c = 2 <= 4 = true
APSubset: boolean c = 2 <= 2 = true
APSubset: boolean c = 4 > 1 = true
APSubset: boolean c = 4 >= 5 = false
APSubset: boolean c = 5 >= 5 = true
APSubset: 

APSubset: Logical Operators ||, &&, !
APSubset: boolean c = true || true = true
APSubset: boolean c = true || false = true
APSubset: boolean c = false || false = false
APSubset: boolean c = true && true = true
APSubset: boolean c = true && false = false
APSubset: boolean c = false && false = false
APSubset: int[] d = null: in else clause due to short circuit
APSubset: int[] d = 1  2  3  4  5  
APSubset: double b = 5.0/2 = 2.5
APSubset: double b = (int) b = 2.0
APSubset: int a = (int) 5.0/2 = 2
APSubset: double b = 5.0/(int) 2 = 2.5
APSubset: double b = (int) 5.0/(int) 2 = 2.0
APSubset: double b = ((int) 5.0)/(double) 2 = 2.5
APSubset: double b = ((int) 5.0)/ 2 = 2.0
APSubset: Take a string, concat a number13and another string
APSubset: to see a back slash must escape it with a backslash \\ = \
APSubset: to print a double quote use backslash double quote \" = "
APSubset: 
 to get
 extra 
 lines use backslash-n (\n) 

APSubset: Look at the code for this because there are some interesting \ (backslash) uses


APSubset: One Dimension Array: Size = 5  array = 0 1 2 3 4
APSubset: Notice in the code that the size is 5 and the indexes range from 0 - 4
APSubset: Output 2 x 2 array in matrix form
0  1   
1  0   
APSubset: twod[0].size = 2
APSubset: twod[1].size = 2
APSubset: twod.size = 2
APSubset: if statements: single statement follows
APSubset:   stmt1:
APSubset:   single statement if: 1 < 2
APSubset:   stmt2:
APSubset: if statements: compound statements
APSubset:   stmt1:
APSubset:   compound if:
APSubset:   1 < 2 is true
APSubset:   all statements are executed within braces
APSubset:   stmt2:
APSubset: only 1 of the if statement is executed in the compound ifs
APSubset: then clause: num + 5 < 20 is true
APSubset: else clause: num + 15 < 20 is false
APSubset: while loop: count numbers from 0 to 9
0 1 2 3 4 5 6 7 8 9 APSubset: end while loop
APSubset: for loop: version of above while loop
APSubset: for(i = 0; i < 10; i++): all loop controls are in first line (you don't have to search through the loop)
0 1 2 3 4 5 6 7 8 9 APSubset: end for loop
APSubset: for each: use on intarr defined above, check the difference
APSubset: this version uses the fact that if you are going to visit each element
APSubset: the computer knows the size and can automatically code the loop parameters
0 1 2 3 4 APSubset: end for each style loop
APSubset: new operator: using new to create an object instance of APSubset
APSubset: this will give us an object to use the 'reverse' methods defined above
APSubset: apsubset instantiated to an APSubset object
APSubset: method over loading: 2 reverses have been defined:
APSubset: one to reverse strings and one to give a string of reversed 'int'
APSubset: look at their definitions they have different call parameters
APSubset: the compiler figures out which one to use based on parameter type
APSubset: apsubset.reverse("abcdefg") = gfedcba
APSubset: apsubset.reverse(12345) = 54321
APSubset: The methods do similar things but to different types of parameters.
APSubset: Run your IDE JavaDoc on this class and you will see what different
APSubset: comment styles do for the JavaDoc Documentation.
APSubset: Single line comments starting with // are used copiously in this class
APSubset: these 'log' statements are defined as static they can be used anywhere
APSubset: inside this class definition. If one were to use it in another class
APSubset: would have to use: APSubset.log();
APSubset: APSubset.log() call check the code
APSubset: static field: APSubset.ANSWER = 42
APSubset: String nullstr = null;  can't print this because it's null it has no String value yet
APSubset: We can test if the variable is a null variable
APSubset: null: reserved variable name value is null
APSubset: if (e = true): Forgot the extra equal sign setting e to true rather than testing with ==
APSubset: e = true; f = false
APSubset: if (e = f): in else clause because of '=' assignment now e is false
APSubset: e = true; f = true
APSubset: if (e == f): Now this works as expected.
APSubset: Be careful with your use of = and == especially with booleans
APSubset: exceptionGeneratorMethod executed no exception thrown ctr = 0
APSubset: try-catch ArithmeticException: / by zero
APSubset: finally clause executed: j = 0
APSubset: exceptionGeneratorMethod executed no exception thrown ctr = 1
APSubset: try-catch NullPointerException: null
APSubset: finally clause executed: j = 1
APSubset: exceptionGeneratorMethod executed no exception thrown ctr = 2
APSubset: loop past intarr boundry
0 1 2 3 4 APSubset: try-catch IndexOutOfBoundsException: 5
APSubset: finally clause executed: j = 2
APSubset: try-catch Exception: exeptionGenerator Method: ctr = 3
APSubset: finally clause executed: j = 3
APSubset: java.lang.Object
APSubset:  
APSubset: java.lang.Integer
APSubset: Integer myint = new Integer(55) therefore myint.intValue() = 55
APSubset: Integer.MIN_VALUE = -2147483648
APSubset: Integer.MAX_VALUE - 2147483647
APSubset:  
APSubset: java.lang.Double
APSubset: Double mydub = new Double(35.75) therefore mydub.doubleValue() = 35.75
APSubset:  
APSubset: java.lang.String
APSubset: String test_str = "this has 22 characters"
APSubset: test_str.length = 22
APSubset: test_str.substring(4,10) =  has 2
APSubset: test_str.substring(4) -  has 22 characters
APSubset: test_str.indexOf("has") = 5
APSubset: test_str.compareTo("this has 22 characters") = 0
APSubset: test_str.compareTo("this has 22 characters") = 19
APSubset: test_str.compareTo("this has 22 characters") = -6
APSubset:  
APSubset: java.lang.Math
APSubset: Math.abs(-3) = 3
APSubset: Math.abs(-3.56) = 3.56
APSubset: Math.pow(2.0,5.0) = 32.0
APSubset: Math.sqrt(2.0) = 1.4142135623730951
APSubset: Math.random() = 0.025126650838768416
APSubset: Math.random() = 0.8468764801673784
APSubset: Math.random() = 0.5932715934489992
APSubset:  
APSubset: Added values to end of list in succession: 
1 2 3  
APSubset: intList.size() = 3
APSubset: Added 4 to end of list: inList.size() = 4
APSubset: intList.get(2) = 3
APSubset: intList.add(2,5): 
1 2 5 3 4  
APSubset: Added 5 to each value using intList set: 
6 7 10 8 9  
APSubset: intList.remove(1): 
6 10 8 9  
APSubset: intList.remove(2): 
6 10 9  
APSubset: Because remove shifts the elements the 2 method calls end up removing
APSubset: elements at index 1 and 3 of the original array
BUILD SUCCESSFUL (total time: 1 second)

APSubset JavaDoc

A pdf of the JavaDoc Generated from netbeans can be downloaded from:
APSubset JavaDoc

Conclusion

There are still some things from the AP document not coded. Some of them were outside the scope of this type of study guide. Some I couldn't think of a simple yet elegant example. I've marked those in the comments of the APSubset code. Most of them you should have been exposed to in projects you've done in your class.
This study guide is meant to remind you of the functional elements of Java available to you during your AP Test. I think it is more of a guide for the free response problems. Helping you to cast your answers in the subset so that you don't over think the problem or over utilize functionality available in advanced libraries.
I did not cover the Grid World case study in this and certainly that is something you need to look over and understand. The idea here was to cover the foundational elements of Java by way of a program so you may remember them if you need them.

References

  1. https://apstudent.collegeboard.org/apcourse/ap-computer-science-a/course-details "Course Details." AP Computer Science A. N.p., n.d. Web. 29 Mar. 2013.
Author: Nasty Old Dog
-->

Tuesday, April 16, 2013

Blackjack Scoring: Aces 1 or 11

AP Computer Science Finishing Blackjack Scoring

AP Computer Science Finishing Blackjack Scoring

Introduction

In the last version of Blackjack ACEs were scored as 11 all the time. This provided a testing platform for the sorting of hands and scoring of cards in general. However in real Blackjack ACEs can be 11 or 1 to the advantage of obtaining a winning hand. For the scoring algorithm so far all that is needed is some code to handle ACEs.

Aside from the ACE scoring problem there are a couple of small items to fix. First if you look at the prompts and scanner code. The prompts have lower case text for hit and stand but expect all capitals. They also require that you spell the whole word. It would be nice to except any of the following input:

  • h,H,hit,HIT,s,S,stand,STAND

I will cheat and look at only the first letter of the entry if it's an 'h' or 'H' the input will be a HIT, if it's 's' or 'S' it will be accepted as STAND.

Finally when the player reaches 21 the computer shouldn't ask if you want to HIT or STAND it should automatically go to the dealer code.

The new scoring algorithm

The new scoring algorithm uses the cardvalue function. When an 11 is detected that is an ACE and an if statement is executed to handle ACE scoring. I did only a minor amount of analysis but I believe that checking the score of the sorted hand when an ACE is encountered (being greater than or equal to 11) is sufficient for the proper handling of ACEs. So score of hand >= 11 ACEs are 1 otherwise the ACE is 11. The new scorehand method follows:

public int scoreHand(int[] hnd, int size) {
    int tmp_hnd[] = new int[size];
    // Copy hand into a new array to play with without disturbing the
    // original hand
    for (int i = 0; i < size; i++) {
        tmp_hnd[i] = hnd[i];
    }
    this.sortHand(tmp_hnd);
    int score = 0;
    for (int i : tmp_hnd) {
        // Need to test each card to see if it is an ACE
        // If an ACE and score is < 11 use 11 as ACE value otherwise use 1
        // I haven't done a proof but I believe that checking the score
        // less than 11 is sufficient to handle ACEs and you won't bust a
        // hand incorrectly
        if (card_value(i) == 11) {
            // Processing ACE
            if (score >= 11) {
                // ACEs must all be 1
                score += 1;
            }
            else {
                score += 11;
            }
        }
        else {
            // Just add card_value it's not an ACE
            score += card_value(i);
        }
    }
    return score;
}

The minor fixes

To cheat on the input just check the first character and test it for 'h', 'H','s','S'. It turns out that a little annoyance we left in the user input code will cause a problem when we go to run the code. But I found it after I made the changes to HIT and STAND so read on to find out the problem.

The following is the code of the player hand input loop in the main method:

while (true) {
    System.out.print("Player Hand hit or stand? ");
    user_inp = uinp.nextLine();
    String firstch = user_inp.substring(0,1);
    if (firstch.equals("H") || firstch.equals("h")) {
        card.dealPlayer();
        card.displayHands();
        scr = card.scoreHand(card.playerHand, card.pcards);
        if (scr > 21) {
            // Player has gone bust
            bust = true;
            break;
        }

    } else if (firstch.equals("S") || firstch.equals("s")) {
        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);
    }
}

Output 1

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

Player score = 16
Dealer score = 13
Bankroll = 1000
Enter the amount you want to bet: 100
Player Hand  
JS QS 
Dealer Hand:  
4S 3D 

Player Hand hit or stand? Stand
Dealer Hand 16 or less: Must HIT
Player Hand  
JS QS 
Dealer Hand:  
4S 3D JD 

Player score: 20   Dealer: 17
You Win!!!
Bankroll = 1100
Enter the amount you want to bet: 100
Player Hand  
7S TS 
Dealer Hand:  
2D AD 

Player Hand hit or stand? Hit
Player Hand  
7S TS 9S 
Dealer Hand:  
2D AD 

BUST!! LOSER!!
Bankroll = 1000
Enter the amount you want to bet: 0
BUILD SUCCESSFUL (total time: 1 minute 28 seconds)

To get the program to work I had to fix a minor problem that has been plagueing the program since we added the user input. Notice that in the output of the game the line 'I don't understand:' doesn't appear after the bet is input. It turns out that when we get the integer for the bet it doesn't eat up the whole line (this is not knowledge you need for the AP but interesting never the less). So I added a uinp.nextLine(); method call.

            System.out.print("Enter the amount you want to bet: ");
//            user_inp = uinp.nextLine();
//            bet = Integer.getInteger(user_inp).intValue();
            bet = uinp.nextInt();
            uinp.nextLine();    // **New line added to eat the rest of the input line

Indeed if you look at the commented out lines I tried to handle the input originally by grabbing the whole line and then try to parse the integer out of it. It never worked well and I didn't feel like investigating because the change to the scanner methods made the problem go away.

Stop asking silly questions!

When the player gets to 21 the computer can be smart enough to check and continue to the dealer processing without asking for HIT or STAND. An extra if statement is all that's needed, right after we check for a 'bust'.

if (firstch.equals("H") || firstch.equals("h")) {
    card.dealPlayer();
    card.displayHands();
    scr = card.scoreHand(card.playerHand, card.pcards);
    if (scr > 21) {
        // Player has gone bust
        bust = true;
        break;
    }
    // Check if player at 21 and stop asking questions
    if (scr == 21) {
        break;
    }

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

Player score = 8
Dealer score = 14
Bankroll = 1000
Enter the amount you want to bet: 100
Player Hand  
2H 8C 
Dealer Hand:  
QD 6D 

Player Hand hit or stand? h
Player Hand  
2H 8C 4H 
Dealer Hand:  
QD 6D 

Player Hand hit or stand? h
Player Hand  
2H 8C 4H 7H 
Dealer Hand:  
QD 6D 

Dealer Hand 16 or less: Must HIT
Player Hand  
2H 8C 4H 7H 
Dealer Hand:  
QD 6D 4C 

Player score: 21   Dealer: 20
You Win!!!
Bankroll = 1100
Enter the amount you want to bet: 0
BUILD SUCCESSFUL (total time: 37 seconds)

There you have it the computer moves right along once the player hits to 21. The only thing not checked for is if the player has blackjack from the beginning. So I changed the player input while loop to loop while scr != 21. Which makes the if statement a little redundant but if you were going to make this program more like Vegas blackjack the payout is 1.5 times for 21 dealt on first 2 cards. I'll leave it in. It may come in handy later on if you want to make this game more realistic. Look at the full code at the end for the above change.

Conclusion

The point of this exercise was to show the AP student that with only the programming skills they have learned in AP Computer Science they can put together the start of a real card game. I believe the only thing we used that is not part of the AP test is the Scanner class. Many teachers introduce this class anyway as it's an easy way to accept user input. In the AP test they will generally tell you that user input is accepted and what form it comes in, they won't expect you to know the specific code. They do expect you to understand that computers accept user input.

I will revisit this program in order to show you how I would refactor (ie. redesign) this code to make it object oriented. Hopefully you have your own ideas at this point for what I did wrong from an Object Oriented perspective. It's very close to the 2013 AP exam date so I will try to hurry this next article.

You may be wondering if I would have coded this program the same way if I were trying to make a Java based blackjack program. The answer is yes and no. I would have designed some objects in the beginning that seemed obvious. But then some of the insight into how to solve a problem comes from getting the code down and seeing how it works. If an idea comes to mind I usually try to capture it in code. Then I will refactor it into the Object Model. Understand though that an experienced Object Oriented Programmer may naturally start with a better initial object model than a less experienced programmer. In the end, however, any code that works properly and gives a seamless user experience is sufficient by definition object oriented or not.

Don't let the constraints of programming mess with your creativity. In the end the people who are really successful at this craft are the creative programmers the elegance of their coding doesn't really matter. Think about it do you care if "Angry Birds" has the most elegant object oriented design? No you play it because it's fun not because the code is elegant!

Final Code

package apcompsci;

/**
 *
 * @author Nasty Old Dog
 */
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 int card_value(int c) {
        // I need an array of sort values 11,2,3,4,5,6,7,8,9,10,10,10,10
        int card_score[] = {11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10};
        // I will use modulo 13 again to take a card and convert to face value
        // then use that to index into the card_score array for the sort value
        return card_score[c % 13];
    }

    public void sortHand(int[] hnd) {
        // sort hand make Aces 11 for sorting purposes
        // Use the insertion sort code and modify it by using the card_value
        // method as the way to sort

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

    public int scoreHand(int[] hnd, int size) {
        int tmp_hnd[] = new int[size];
        // Copy hand into a new array to play with without disturbing the
        // original hand
        for (int i = 0; i < size; i++) {
            tmp_hnd[i] = hnd[i];
        }
        this.sortHand(tmp_hnd);
        int score = 0;
        for (int i : tmp_hnd) {
            // Need to test each card to see if it is an ACE
            // If an ACE and score is < 11 use 11 as ACE value otherwise use 1
            // I haven't done a proof but I believe that checking the score
            // less than 11 is sufficient to handle ACEs and you won't bust a
            // hand incorrectly
            if (card_value(i) == 11) {
                // Processing ACE
                if (score >= 11) {
                    // ACEs must all be 1
                    score += 1;
                }
                else {
                    score += 11;
                }
            }
            else {
                // Just add card_value it's not an ACE
                score += card_value(i);
            }
        }
        return score;
    }

    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();
        System.out.println("Player score = " + card.scoreHand(card.playerHand, card.pcards));
        System.out.println("Dealer score = " + card.scoreHand(card.dealerHand, card.dcards));
        // 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();
            uinp.nextLine();
            // 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
            boolean bust = false;
            int scr = scr = card.scoreHand(card.playerHand, card.pcards);
            while (scr != 21) {
                System.out.print("Player Hand hit or stand? ");
                user_inp = uinp.nextLine();
                String firstch = user_inp.substring(0,1);
                if (firstch.equals("H") || firstch.equals("h")) {
                    card.dealPlayer();
                    card.displayHands();
                    scr = card.scoreHand(card.playerHand, card.pcards);
                    if (scr > 21) {
                        // Player has gone bust
                        bust = true;
                        break;
                    }
                    // Check if player at 21 and stop asking questions
                    if (scr == 21) {
                        break;
                    }

                } else if (firstch.equals("S") || firstch.equals("s")) {
                    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);
                }
            }
            if (bust) {
                System.out.println("BUST!! LOSER!!");
                // deduct bet from bankroll
                bankroll -= bet;
                // reset hands for next game
                card.resetHands();
                continue; // go back to top of main loop and start new game
            }
            // Manually control dealer hand the same way
            // We will swap this out for code that will run the dealer rules 
            // automatically
            int dscr = dscr = card.scoreHand(card.dealerHand, card.dcards);
            while (true) {
                if (dscr < 17) {
                    System.out.println("Dealer Hand 16 or less: Must HIT");
                    card.dealDealer();
                    card.displayHands();
                    dscr = card.scoreHand(card.dealerHand, card.dcards);
                } else {
                    break;
                }
            }

            // Code to score the game and settle the bet will go here
            // For now assume we win every time
            System.out.println("Player score: " + scr + "   Dealer: " + dscr);
            if (scr > dscr) {
                System.out.println("You Win!!!");
                bankroll = bankroll + bet;
            } else if (dscr > 21) {
                System.out.println("You Win!! Dealer has BUSTED");
                bankroll += bet;
            } else if (scr == dscr) {
                System.out.println("PUSH");
            } else {
                System.out.println("LOSER!!!");
                bankroll -= bet;
            }
            // reset hands to play a new game
            card.resetHands();
        }
    }
}

Author: Nasty Old Dog

Sunday, March 31, 2013

AP Computer Science Study Guide

AP Computer Science Study Guide

AP Computer Science Study Guide

Introduction

Java is a good language for programming. It has a wealth of features and large libraries of code for almost anything you could want to do with a program. Had I had a year with a class I would have endeavored to teach them as much of Java as I could. Luckily for AP Computer Science students I am not in charge of the test. Instead you have a much smaller scope of knowledge to deal with. I have said before you should download the AP course description from the College Board website. It details exactly what subject matter you should be familiar with.

Test Taking Strategy

There are no point reductions for wrong answers so you should strive to answer all the multiple choice questions. With 5 minutes left to go you should stick in any answer in the blank problems then go back and see how many you can answer. Every question should have an answer! Don't take so much time that you have blanks on your computer answer sheet.

You have 2 minutes per problem (less really). You can't get stuck for 5 minutes on any one problem. You should quickly go through the test and find all questions you can answer quickly and easily. The worst thing you can do is get stuck on a problem and leave 5 easy questions unanswered at the end of the test.

When you take practice tests you should compile a list of which type of problems take you the longest and which type are you more inclined to get wrong. Then save these for last. Once you realize a question falls into that category guess an answer (put down D or E or something) don't even do an educated guess. Mark the problem to come back to and continue. Once you get through the test the first time now go back and answer the questions you had to guess on. Now you can take a little bit more time on each problem. You will be confident that you have found all the easy "get-able" questions and now you are just working to improve your score.

DANGER: Don't missalign problems in your bubble sheet because you skipped them. You should certainly practice this method on a couple of practice tests before you do it on the real exam. By practice I mean get a bubble sheet and take the test on the bubble sheet then check your answers to make sure you did not misalign anything.

The AP Computer Science Java Subset

Base types

  • int, double, boolean

Arithmetic operators

OperatorName
+addition
-subtraction
*muliplication
/division
%modulo

Comparison Operators

OperatorNameFunction
==equalstest if equal to
!=not equalstest if not equal to
<less thantest if left value 'less than' right value
<=less than or equal totest if left 'less than or equal to' right
>greater thantest if left 'greater than' right
>=greater than or equal totest if left 'greater than or equal to' right

Logical Comparisons

OperatorNameFunction
&&andreturns true if both left and right values are true otherwise it returns false
||orreturns false if both left and right values are false otherwise it returns true
!notreturns the opposite of the right hand value true becomes false and vise versa
NOTE: The && and || 'short circuit' because of the fact that any false value in && makes the whole statement false further processing does not have to occur the compiler can immediately choose the else clause. The same but opposite happens for || except as soon as the compiler finds a true value it can go into the next statement in the if portion of an if-then-else statement

Assignment Operators

OperatorFunction
=assign value of right hand side (RHS) to variable on left hand side (LHS)
+=LHS = LHS + RHS
-=LHS = LHS - RHS
*=LHS = LHS * RHS
/=LHS = LHS / RHS
%=LHS = LHS % RHS
(int)truncates double giving the int portion: int myvar = (int) 32.25 //myvar = 32
(double)makes a double value out of an int value so +-*/ operations return double values

The Study Guide in Code

To help you study for the AP exam I have gone through the subset and placed comments for each of the subset items. Then for a portion of it I have implemented examples of the subset. To save some typing I have implemented 'log' methods to simplify the output. Between the code and the output you should have a pretty good idea of what the subset entails and what you are responsible to know. Hopefully I will have time to provide you a completed sheet that way you may have some extra examples of code going into the AP test.

Don't forget to check out the updated version in the blog post at the following link:
Study Guide take 2

/*
 * This Class definition is to give an example of using everything in 
 * the Java subset used on the AP exam. Use this as a learning tool and 
 * add in code from test questions where you weren't sure how the compiler
 * would handle the code. It will become your study guide for the AP exam.
 * This is not a substitute for reading the course pdf file on the College
 * Board site. 
 */
package apcompsci;

/**
 *
 * @author nasty old dog
 */
public class APSubset {

    public static void log(String str)
    {
        System.out.print("APSubset: ");
        System.out.println(str);
    }

    public static void log_array(String str, int[] arr)
    {
        System.out.print("APSubset: ");
        System.out.print(str);
        for (int i : arr){
            System.out.print(i + "  ");
        }
        System.out.println();
    }

    public static void main (String[] args)
    {
        // Basic types: int, double, boolean
        int a = 0;
        double b = 0.0;
        boolean c = false;
        log("BASIC TYPES");
        log("int a = " + a);
        log("double b = " + b);
        log("boolean c = " + c);

        // Basic operators: +, -, *, /, %
        log("\n");
        log("BASIC OPERATORS");
        a = 1 + 2;
        log("int a = 1 + 2 = " + a);
        b = 2.0 + 3.5;
        log("double b = 2.0 + 3.5 = " + b);
        a = 2 - 3;
        log("int a = 2 - 3 = " + a);
        b = 2.0 - 3.5;
        log("double b = 2.0 - 3.5 = " + b);
        a = 2 * 3;
        log("int a = 2 * 3 = " + a);
        b = 2.0 * 3.5;
        log("double b = 2.0 * 3.5 = " + b);
        a = 3 / 2;
        log("int a = 3 / 2 = " + a);
        b = 3.5 / 2.0;
        log("double b = 3.5 / 2.0 = " + b);
        a = 17 % 5;
        log("int a = 17 % 5 = " + a);
        b = 17.0 % 6.0;
        log("double b = 17.0 % 6.0 = " + b);

        // To show modulo(remainder) lets show the division first

        // preincrement/postincrement predecrement/postdecrement
        // These are used for their side effects and never inside an expression
        // mainly for loop increment/decrement
        log("\n");
        log("Pre/Post-increment and Pre/Post-decrement");
        log("int a = " + a);
        log("a++ = " + a++);
        log("int a = " + a);
        log("++a = " + ++a);
        log("int a = " + a);
        log("a-- = " + a--);
        log("int a = " + a);
        log("--a = " + --a);
        log("int a = " + a);

        log("double b = " + b);
        log("b++ = " + b++);
        log("double b = " + b);
        log("++b = " + ++b);
        log("double b = " + b);
        log("b-- = " + b--);
        log("double b = " + b);
        log("--b = " + --b);
        log("double b = " + b);

        // Assignment operators: +=, -=, *=, /=, %=
        log("\n");
        log("Assignment operators +=, -=, *=, /=, %=");
        a = 13;
        log ("int a = " + a);
        b = 13.0;
        log ("double b = " + b);
        a += 7;
        log ("int a += 7 = " + a);
        b += 7.5;
        log ("double b += 7.5 = " + b);
        a -= 3;
        log ("int a -= 3 = " + a);
        b -= 3.5;
        log ("double b -= 3.5 = " + b);
        a *= 2;
        log ("int a *= 2 = " + a);
        b *= 2.0;
        log ("double b *= 2.0 = " + b);
        a /= 2;
        log ("int a /= 2 = " + a);
        b /= 2.0;
        log("double b /= 2.0 = " + b);
        a %= 5;
        log("int a %= 5 = " + a);
        b %= 6.0;
        log("double b %= 6.0 = " + b);

        // Relational operators: == != < <= > >=
        c = 1 == 1;
        log("boolean c = 1 == 1 = " + c);
        c = 2 != 3;
        log("boolean c = 2 != 3 = " + c);
        c = 2 < 1;
        log("boolean c = 2 < 1 = " + c);
        c = 2 < 3;
        log("boolean c = 2 < 3 = " + c);
        c = 2 <= 4;
        log("boolean c = 2 <= 4 = " + c);
        c = 2 <= 2;
        log("boolean c = 2 <= 2 = " + c);
        c = 4 > 1;
        log("boolean c = 4 > 1 = " + c);
        c = 4 >= 5;
        log("boolean c = 4 >= 5 = " + c);
        c = 5 >= 5;
        log("boolean c = 5 >= 5 = " + c);
        // Logic operators || && ! short circuit evaluation
        log("\n");
        log("Logical Operators ||, &&, !");
        c = true || true;
        log("boolean c = true || true = " + c);
        c = true || false;
        log("boolean c = true || false = " + c);
        c = false || false;
        log("boolean c = false || false = " + c);
        c = true && true;
        log("boolean c = true && true = " + c);
        c = true && false;
        log("boolean c = true && false = " + c);
        c = false && false;
        log("boolean c = false && false = " + c);
        int d[] = null;
        if (d != null && d[1]==2) {
            // The d[1] is an illegal operation ArrayOutofBounds error
            // But because d == null it never gets executed due to the 
            // short circuit
        }
        else {
            log("int[] d = null: in else clause due to short circuit");
        }
        d = new int[] {1,2,3,4,5};
        if (d != null && d[1]==2) {
            // The d[1] is an illegal operation ArrayOutofBounds error
            // But because d == null it never gets executed due to the 
            // short circuit
            log_array("int[] d = ",d);
        }
        // numeric casts (int) and (double))
        b = 5.0 / 2;
        log("double b = 5.0/2 = " + b);
        b = (int) b;
        log ("double b = (int) b = " + b);
        a = (int) 5.0/2;
        log ("int a = (int) 5.0/2 = " + a);
        b = 5.0 / (int) 2;
        log("double b = 5.0/(int) 2 = " + b);
        b = (int) 5.0 / (int) 2;
        log("double b = (int) 5.0/(int) 2 = " + b);
        b = ((int) 5.0) / (double) 2;
        log("double b = ((int) 5.0)/(double) 2 = " + b);
        b = ((int) 5.0) / 2;
        log("double b = ((int) 5.0)/ 2 = " + b);

        // String concatenation
        // String escape sequences: \\, \n, \"
        // One Dimensional Arrays
        // Two Dimensional Arrays
        // if stm
        // if-else stm
        // while
        // for
        // for each
        // method over loading
        // new operator
        // public and private
        // java comments /* // and /** @param and @return
        // final for variables and final class scope
        // static methods static variables
        // null
        // this forget what I told you they don't care about it.
        // Super
        // Initialize all variables in constructors implicit initialization is not in subset
        // extend classes and implement interfaces method overriding and polymorphism
        // interface and abstract classes
        // difference between = and ==
        // Conversion from Subclass to Superclass and Class casts from Object to another class
        // import specific classes
        // Generic Class (need to know how it works won't be required to implement)
        // String.compareTo()
        // Exceptions
        // Standard Classes: String, Math, List, ArrayList
        // Wrapper classes: Integer, Double
        // Class java.lang.Object: equals(Object other) toString()
        // Class java.lang.Integer
        // Class java.lang.Double
        // Class java.lang.String
        // Class java.lang.Math
        // Interface java.util.List<E>
        // Interface java.util.ArrayList<E>
    }
}

Output

run:
APSubset: BASIC TYPES
APSubset: int a = 0
APSubset: double b = 0.0
APSubset: boolean c = false
APSubset: 

APSubset: BASIC OPERATORS
APSubset: int a = 1 + 2 = 3
APSubset: double b = 2.0 + 3.5 = 5.5
APSubset: int a = 2 - 3 = -1
APSubset: double b = 2.0 - 3.5 = -1.5
APSubset: int a = 2 * 3 = 6
APSubset: double b = 2.0 * 3.5 = 7.0
APSubset: int a = 3 / 2 = 1
APSubset: double b = 3.5 / 2.0 = 1.75
APSubset: int a = 17 % 5 = 2
APSubset: double b = 17.0 % 6.0 = 5.0
APSubset: 

APSubset: Pre/Post-increment and Pre/Post-decrement
APSubset: int a = 2
APSubset: a++ = 2
APSubset: int a = 3
APSubset: ++a = 4
APSubset: int a = 4
APSubset: a-- = 4
APSubset: int a = 3
APSubset: --a = 2
APSubset: int a = 2
APSubset: double b = 5.0
APSubset: b++ = 5.0
APSubset: double b = 6.0
APSubset: ++b = 7.0
APSubset: double b = 7.0
APSubset: b-- = 7.0
APSubset: double b = 6.0
APSubset: --b = 5.0
APSubset: double b = 5.0
APSubset: 

APSubset: Assignment operators +=, -=, *=, /=, %=
APSubset: int a = 13
APSubset: double b = 13.0
APSubset: int a += 7 = 20
APSubset: double b += 7.5 = 20.5
APSubset: int a -= 3 = 17
APSubset: double b -= 3.5 = 17.0
APSubset: int a *= 2 = 34
APSubset: double b *= 2.0 = 34.0
APSubset: int a /= 2 = 17
APSubset: double b /= 2.0 = 17.0
APSubset: int a %= 5 = 2
APSubset: double b %= 6.0 = 5.0
APSubset: boolean c = 1 == 1 = true
APSubset: boolean c = 2 != 3 = true
APSubset: boolean c = 2 < 1 = false
APSubset: boolean c = 2 < 3 = true
APSubset: boolean c = 2 <= 4 = true
APSubset: boolean c = 2 <= 2 = true
APSubset: boolean c = 4 > 1 = true
APSubset: boolean c = 4 >= 5 = false
APSubset: boolean c = 5 >= 5 = true
APSubset: 

APSubset: Logical Operators ||, &&, !
APSubset: boolean c = true || true = true
APSubset: boolean c = true || false = true
APSubset: boolean c = false || false = false
APSubset: boolean c = true && true = true
APSubset: boolean c = true && false = false
APSubset: boolean c = false && false = false
APSubset: int[] d = null: in else clause due to short circuit
APSubset: int[] d = 1  2  3  4  5  
APSubset: double b = 5.0/2 = 2.5
APSubset: double b = (int) b = 2.0
APSubset: int a = (int) 5.0/2 = 2
APSubset: double b = 5.0/(int) 2 = 2.5
APSubset: double b = (int) 5.0/(int) 2 = 2.0
APSubset: double b = ((int) 5.0)/(double) 2 = 2.5
APSubset: double b = ((int) 5.0)/ 2 = 2.0
BUILD SUCCESSFUL (total time: 2 seconds)

Conclusion

You shouldn't wait for me to finish this. Go ahead and take on the task yourself. By implementing each part of the Java AP subset you will further enhance your knowledge. In previous articles I have deviated from the subset to help you understand some basic programming concepts and constructs. But you should start to tailor your studying specifically for the AP (at this time the AP is about a month away for 2013).

If you haven't started doing practice test you should start. Anycode you had problems with you should add to this study guide. By the time you get through 3 or 4 tests you should be an expert on the AP subset and know exactly what to expect in May. Remember in the free response questions to limit yourself to the AP subset. If your course was taught properly you should have learned more Java than you need for the test. Now however it's time to focus on the subset.

You should develop your test taking strategy as you take practice exams. Make sure you time yourself to the amount of time the AP exam allows for each section (at least on a couple of practice tests). Your strategy is working if you 1) answer all questions and 2) did not have to guess on otherwise easy problems.

References

  1. https://apstudent.collegeboard.org/apcourse/ap-computer-science-a/course-details "Course Details." AP Computer Science A. N.p., n.d. Web. 29 Mar. 2013.

Author: Nasty Old Dog