AP CSA Units 1-9 Notes


Unit 1: Primitive Types

  • Data Types: int, double, boolean, char
  • Variable Declaration: int x = 5;
  • Arithmetic: +, -, *, /, %, precedence rules (PEMDAS)
  • Casting: int to double, double to int (truncation)
  • Input: Scanner sc = new Scanner(System.in);
  • Output: System.out.println();

Unit 2: Using Objects

  • Objects: Created with new
  • Strings: String str = “hello”;
    • Methods: length(), substring(), indexOf(), charAt()
  • Null References: null
  • Equality: == (reference), .equals() (content)
  • Math Class: Math.pow(), Math.sqrt(), Math.random()

Unit 3: Boolean Expressions and if Statements

  • Boolean Operators: &&, !, (when i do the or statement itll make a table for md)
  • Comparison Operators: <, >, <=, >=, ==, !=
  • If Statements:
    • if, else if, else
    • Nesting: Placing conditions inside other conditions
  • Logical Expressions: Combine multiple conditions for more complex checks

Unit 4: Iteration

  • Loops:
    • while(condition) { }
    • for(initialization; condition; update) { }
    • do { } while(condition);
  • Break/Continue: Exit or skip loop iteration
  • Nested Loops: Loop inside another loop
  • Loop Applications: Traversing arrays, searching, counting

Unit 5: Writing Classes

  • Class Anatomy: Fields, methods, constructors
  • Constructor: Initializes object state
    • public ClassName(type parameter) { }
  • Accessors (Getters): Return field value
  • Mutators (Setters): Modify field value
  • Static Members: Shared across all instances
  • Encapsulation: Use private fields and public methods

Unit 6: Array

  • Declaration: type[] arrayName = new type[size];
  • Access Elements: array[index]
  • Iteration: Use loops to traverse arrays
  • Common Operations: Finding max/min, sum, average
  • Bounds Checking: Avoid ArrayIndexOutOfBoundsException

Unit 7: ArrayList

  • ArrayList Declaration: ArrayList list = new ArrayList<>();
  • Methods:
    • add(), remove(), set(), get(), size()
  • Dynamic Resizing: Can grow or shrink as needed
  • Iteration: For-each or standard for loop
  • Autoboxing/Unboxing: Convert between primitives and wrapper objects

Unit 8: 2D Arrays

  • Declaration: type[][] arrayName = new type[rows][cols];
  • Access Elements: array[row][col]
  • Iteration: Use nested loops for row-column traversal
  • Applications: Grids, matrices
  • Common Algorithms: Row-wise, column-wise processing

Unit 9: Inheritance

  • Inheritance: class Subclass extends Superclass
  • Subclass: Inherits fields/methods from superclass
  • Method Overriding: Redefine superclass method in subclass
  • Super Keyword: Call superclass constructor/method
  • Polymorphism: Use superclass reference for subclass object
  • Object Class: All classes inherit from Object

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;

public class GameBase { // this is the parent class 
    // defining 2 primitive types and an arraylist
    public int secretNumber;
    public int attempts;
    public ArrayList<Integer> previousGuesses;

    public GameBase(int range) {
        this.secretNumber = (int) (Math.random() * range) + 1; // doing Aadit's lesson(Unit2) the math.random function was there
        this.attempts = 0;
        this.previousGuesses = new ArrayList<>(); 
    }

    public void play(BufferedReader reader) throws IOException {
        int userGuess = 0;
        while (userGuess != secretNumber) {
            System.out.print("Enter your guess: ");
            userGuess = Integer.parseInt(reader.readLine()); //scanner was covered
            makeGuess(userGuess); 
        }
    }

    public void makeGuess(int guess) {
        attempts++;
        addGuess(guess);
        if (guess < secretNumber) {
            System.out.println("Too low!");
        } else if (guess > secretNumber) {
            System.out.println("Too high!");
        } else {
            System.out.println("Correct! It took you " + attempts + " attempts.");
            System.out.print("Your guesses: ");
            printSortedGuesses();
        }
    }

    public void addGuess(int guess) {
        int index = Collections.binarySearch(previousGuesses, guess); // search for the guess with index binary search and this way it will inherently find the closest guess's index and add it inside there
        if (index < 0) {
            index = -(index + 1);
        }
        previousGuesses.add(index, guess);
        System.out.println(previousGuesses); //we insert the guess in the correct spot so the array is still numerically ordered
    }

    public void printSortedGuesses() {
        for (int guess : previousGuesses) {
            System.out.print(guess + " ");
        }
        System.out.println();
    }
}

class EasyGame extends GameBase { // this is the child class for easy game
    public EasyGame() {
        super(10);
    }

    @Override
    public void play(BufferedReader reader) throws IOException {
        System.out.println("Playing Easy Game (1-10)");
        super.play(reader); // Call the base class play method
    }
}

class MediumGame extends GameBase { // this is the child class for medium game
    public MediumGame() {
        super(50);
    }

    @Override
    public void play(BufferedReader reader) throws IOException {
        System.out.println("Playing Medium Game (1-50)");
        super.play(reader); // Call the base class play method
    }
}

class HardGame extends GameBase { // this is the child class for hard game
    public HardGame() {
        super(100);
    }

    @Override
    public void play(BufferedReader reader) throws IOException { 
        System.out.println("Playing Hard Game (1-100)");
        super.play(reader); // Call the base class play method
    }
}

public class NumberGuessingGame {
    public static void main(String[] args) throws IOException { 
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); // Buffere reader is faster than scanner
        System.out.println("Welcome to the Number Guessing Game!");

        System.out.println("Select difficulty level: ");
        System.out.println("1. Easy (1-10)");
        System.out.println("2. Medium (1-50)");
        System.out.println("3. Hard (1-100)");

        int choice = Integer.parseInt(reader.readLine());
        GameBase game;

        switch (choice) { // shows a usecase for polymorphism and also switch cases which I don't believe was fully covered from what I remember
            case 1:
                game = new EasyGame();
                break;
            case 2:
                game = new MediumGame();
                break;
            case 3:
                game = new HardGame();
                break;
        }

        game.play(reader);
    }
}

NumberGuessingGame.main(null);
Welcome to the Number Guessing Game!
Select difficulty level: 
1. Easy (1-10)
2. Medium (1-50)
3. Hard (1-100)
Playing Medium Game (1-50)
Enter your guess: [1]
Too low!
Enter your guess: [1, 2]
Too low!
Enter your guess: [1, 2, 3]
Too low!
Enter your guess: [1, 2, 3, 10]
Too low!
Enter your guess: [1, 2, 3, 5, 10]
Too low!
Enter your guess: 


---------------------------------------------------------------------------

java.lang.NumberFormatException: For input string: ""

	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)

	at java.base/java.lang.Integer.parseInt(Integer.java:678)

	at java.base/java.lang.Integer.parseInt(Integer.java:786)

	at GameBase.play(#17:1)

	at MediumGame.play(#19:1)

	at NumberGuessingGame.main(#40:1)

	at .(#43:1)