06 — Extended Portfolio

Full Case Studies

A full rundown of what each project actually does — the mechanics, the data handling, and the details that don't fit on the homepage cards.

Featured / 001

Java Battle Game

A two-player turn-based battle game with attack, defend, and heal mechanics, a coin betting pot, and randomized critical hits. Each action triggers its own sound effect, played on a background thread so the game never stalls.

Java OOP Multithreading Game Logic

⚙️ Key Features

  • Interactive two-player turn-based combat driven entirely by user input
  • Attack deals randomized damage with a 20% chance of a critical hit (2× damage)
  • Defend halves incoming damage for one turn, then resets
  • Heal restores HP up to the max, capped at 3 uses per player
  • A coin betting pot is settled once a winner is decided
  • Every action — attack, heal, invalid input, victory — triggers its own sound effect on a background thread

📚 What I Learned

  • Managing player state (HP, defending flag, heal count) with parallel arrays
  • Structuring a game loop with while and switch-case for player actions
  • Using static final constants for fixed values like MAX_HP and MAX_HEAL
  • Running sound playback on a separate thread so it never blocks the game loop
  • Integrating an external library (JLayer) for MP3 playback
Project1.java
import java.io.FileInputStream;
import java.util.Random;
import java.util.Scanner;

import javazoom.jl.player.Player;

public class Project1 {

    static final int MAX_HP = 100;
    static final int MAX_HEAL = 3;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Random r = new Random();

        int[] hp = { MAX_HP, MAX_HP };
        boolean[] defending = { false, false };
        int[] healcount = { 0, 0 };
        String[] p = new String[2];

        int current = 0;

        System.out.print("Enter Player 1 Name: ");
        p[0] = sc.nextLine();
        playSound("rizz-sound-effect.mp3");

        System.out.print("Enter Player 2 Name: ");
        p[1] = sc.nextLine();
        playSound("rizz-sound-effect.mp3");

        int total = getBet(sc, p[0]) + getBet(sc, p[1]);

        while (hp[0] > 0 && hp[1] > 0) {
            int opponent = 1 - current;

            displayStatus(p, hp, defending, healcount);

            System.out.println("\n" + p[current] + "'s Turn");
            System.out.println("1. Attack  2. Defend  3. Heal");

            int choice = sc.nextInt();

            switch (choice) {
            case 1:
                attack(r, p, hp, defending, current, opponent);
                break;

            case 2:
                defending[current] = true;
                System.out.println(p[current] + " is defending!");
                break;

            case 3:
                heal(r, p, hp, healcount, current);
                break;

            default:
                System.out.println("Invalid choice!");
                playSound("vine-boom.mp3");
                continue;
            }

            if (hp[opponent] <= 0)
                break;

            current = opponent;
        }

        System.out.println("\n===== GAME OVER =====");
        if (hp[0] <= 0) {
            System.out.println(p[1] + " Wins!");
        } else {
            System.out.println(p[0] + " Wins!");
        }
        playSound("rizz-sound-effect.mp3");
        System.out.println("CONGRALUTIONS YOU WIN ¥" + total);

    }

    static void attack(Random r, String[] p, int[] hp, boolean[] defending, int current, int opponent) {
        int damage = r.nextInt(11) + 10;
        if ((r.nextInt(2) == 0)) {
            playSound("重いキック1.mp3");
        } else {
            playSound("punch-gaming-sound-effect-hd_RzlG1GE.mp3");
        }

        if (r.nextInt(100) < 20) {
            damage *= 2;
            System.out.println("🔥 CRITICAL HIT!");
            playSound("bone-crack.mp3");
        }

        if (defending[opponent]) {
            damage /= 2;
            defending[opponent] = false;
            playSound("rizz-sound-effect.mp3");
        }

        hp[opponent] -= damage;
        System.out.println(p[current] + " attacked for " + damage + " damage!");
    }

    static void heal(Random r, String[] p, int[] hp, int[] healcount, int current) {
        if (healcount[current] >= MAX_HEAL) {
            System.out.println("❌ No heals left!");
            playSound("fahhhhhhhhhhhhhh.mp3");
            return;
        }

        int heal = r.nextInt(20) + 5;
        hp[current] = Math.min(MAX_HP, hp[current] + heal);
        healcount[current]++;

        playSound("anime-wow-sound-effect.mp3");
        System.out.println(p[current] + " healed " + heal + " HP!");
    }

    static int getBet(Scanner sc, String player) {
        System.out.print(player + ", enter your bet: ");
        int bet = sc.nextInt();

        if (bet < 1000) {
            playSound("999-social-credit-siren.mp3");
        } else {
            playSound("anime-wow-sound-effect.mp3");
        }

        return bet;
    }

    static void displayStatus(String[] p, int[] hp, boolean[] defending, int[] healcount) {
        for (int i = 0; i < 2; i++) {
            System.out.println(p[i] + " HP: " + hp[i] +
                    (defending[i] ? " (Defending)" : "") +
                    " | Heals left: " + (MAX_HEAL - healcount[i]));
        }
    }

    static void playSound(String fileName) {
        new Thread(() -> {
            try {
                FileInputStream file = new FileInputStream(fileName);
                Player sound = new Player(file);
                sound.play();
            } catch (Exception e) {
                System.out.println("⚠ Sound error: " + fileName);
            }
        }).start();
    }
}
011

Expense Tracker

A console-based personal finance tool for logging daily spending. Add, delete, and search expenses by year, month, or category, with every record persisted to a CSV file and totals calculated on demand.

Java File I/O CSV ArrayList

⚙️ Key Features

  • Add an expense with amount, category, date, and note — IDs auto-increment from existing records
  • View every expense as an aligned table in the console
  • Delete an expense by ID, rewriting the CSV without that row
  • Search expenses by year, month, or category
  • Calculate and display the running total across all expenses
  • Data survives between sessions in a plain CSV file (Expensesdb.csv)

📚 What I Learned

  • Splitting responsibilities across Manager, Database, and Model classes
  • Reading and writing structured data to a CSV file with BufferedReader/FileWriter
  • Rebuilding a file's contents in place to support deletion by ID
  • Filtering an ArrayList of objects by year, month, or category
Project2.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Scanner;

public class Project2 {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        ViewScreen view = new ViewScreen();
        ExpensesManager em = new ExpensesManager();

        while (true) {
            System.out.println("\n1.Add New Expenses");
            System.out.println("2.Show All Expenses");
            System.out.println("3.Delete Expense");
            System.out.println("4.Search");
            System.out.println("5.Show Total Amount");
            System.out.println("6.Exit");
            System.out.println("Enter the number: ");

            int menu = sc.nextInt();
            sc.nextLine();

            if (menu == 1) {

                System.out.println("Enter the Amount");
                double amount = sc.nextDouble();
                sc.nextLine();

                System.out.println("Enter the category");
                String category = sc.nextLine();

                System.out.println("Enter the date (yyyy-MM-dd)");
                String date = sc.nextLine();

                System.out.println("Enter the note");
                String note = sc.nextLine();

                String[] parts = date.split("-");
                int year = Integer.parseInt(parts[0]);
                int month = Integer.parseInt(parts[1]);

                ArrayList<Expenses> list = em.getAllExpenses();
                int id = 1;
                for (Expenses exp : list) {
                    if (exp.getId() >= id) {
                        id = exp.getId() + 1;
                    }
                }

                Expenses e = new Expenses();
                e.setId(id);
                e.setAmount(amount);
                e.setCategory(category);
                e.setDate(date);
                e.setNote(note);
                e.setMonth(month);
                e.setYear(year);

                em.addExpense(e);

                System.out.println("Expense Added!");

            } else if (menu == 2) {

                view.itemList(em.getAllExpenses());

            } else if (menu == 3) {

                System.out.println("Enter ID to delete:");
                int id = sc.nextInt();
                em.delete(id);

            } else if (menu == 4) {

                System.out.println("Search by:");
                System.out.println("1.By Year");
                System.out.println("2.By Month");
                System.out.println("3.By Category");

                int smenu = sc.nextInt();
                sc.nextLine();

                if (smenu == 1) {
                    System.out.println("Enter the Year:");
                    int year = sc.nextInt();
                    view.itemList(em.searchByYear(year));

                } else if (smenu == 2) {
                    System.out.println("Enter the Month:");
                    int month = sc.nextInt();
                    view.itemList(em.searchByMonth(month));

                } else if (smenu == 3) {
                    System.out.println("Enter the Category:");
                    String category = sc.nextLine();
                    view.itemList(em.searchByCategory(category));
                }

            } else if (menu == 5) {

                view.showTotal();

            } else {
                System.out.println("Exiting...");
                break;
            }
        }
    }
}

class ViewScreen {

    ExpensesManager em = new ExpensesManager();

    public void showTotal() {
        System.out.println("Total Expenses : " + em.getTotal());
    }

    public void itemList(ArrayList<Expenses> expense) {

        if (expense.isEmpty()) {
            System.out.println("No data found.");
            return;
        }

        System.out.printf("%-5s %-10s %-15s %-12s %-20s\n",
                "ID", "Amount", "Category", "Date", "Note");
        System.out.println("---------------------------------------------------------------");

        for (Expenses e : expense) {
            System.out.printf("%-5d %-10.2f %-15s %-12s %-20s\n",
                    e.getId(),
                    e.getAmount(),
                    e.getCategory(),
                    e.getDate(),
                    e.getNote());
        }
    }
}

class ExpensesManager {

    private ExpensesDatabase ed = new ExpensesDatabase();

    public void addExpense(Expenses e) {
        ed.insertExpense(e);
    }

    public ArrayList<Expenses> getAllExpenses() {
        return ed.getExpenses();
    }

    public ArrayList<Expenses> searchByYear(int year) {
        return ed.filterByYear(ed.getExpenses(), year);
    }

    public ArrayList<Expenses> searchByMonth(int month) {
        return ed.filterByMonth(ed.getExpenses(), month);
    }

    public ArrayList<Expenses> searchByCategory(String category) {
        return ed.filterByCategory(ed.getExpenses(), category);
    }

    public double getTotal() {
        return ed.calTotal(ed.getExpenses());
    }

    public void delete(int id) {
        ed.deleteExpenses(id);
    }
}

class ExpensesDatabase {

    public double calTotal(ArrayList<Expenses> expense) {
        double total = 0;
        for (Expenses e : expense) {
            total += e.getAmount();
        }
        return total;
    }

    public ArrayList<Expenses> filterByYear(ArrayList<Expenses> expense, int year) {
        ArrayList<Expenses> result = new ArrayList<>();
        for (Expenses e : expense) {
            if (e.getYear() == year)
                result.add(e);
        }
        return result;
    }

    public ArrayList<Expenses> filterByMonth(ArrayList<Expenses> expense, int month) {
        ArrayList<Expenses> result = new ArrayList<>();
        for (Expenses e : expense) {
            if (e.getMonth() == month)
                result.add(e);
        }
        return result;
    }

    public ArrayList<Expenses> filterByCategory(ArrayList<Expenses> expense, String category) {
        ArrayList<Expenses> result = new ArrayList<>();
        for (Expenses e : expense) {
            if (e.getCategory().equalsIgnoreCase(category)) {
                result.add(e);
            }
        }
        return result;
    }

    public void insertExpense(Expenses e) {
        try {
            FileWriter fw = new FileWriter("Expensesdb.csv", true);

            fw.write("\n" +
                    e.getId() + "," +
                    e.getAmount() + "," +
                    e.getCategory() + "," +
                    e.getDate() + "," +
                    e.getNote() + "," +
                    e.getMonth() + "," +
                    e.getYear() + "\n");

            fw.close();

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void deleteExpenses(int id) {
        try {
            BufferedReader br = new BufferedReader(new FileReader("Expensesdb.csv"));
            ArrayList<String> lines = new ArrayList<>();
            String line;

            while ((line = br.readLine()) != null) {
                String[] data = line.split(",");
                if (Integer.parseInt(data[0]) != id) {
                    lines.add(line);
                }
            }
            br.close();

            FileWriter fw = new FileWriter("Expensesdb.csv");
            for (String l : lines) {
                fw.write(l + "\n");
            }
            fw.close();

            System.out.println("Deleted successfully!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public ArrayList<Expenses> getExpenses() {
        ArrayList<Expenses> list = new ArrayList<>();

        try {
            BufferedReader br = new BufferedReader(new FileReader("Expensesdb.csv"));
            String line;

            while ((line = br.readLine()) != null) {
                String[] d = line.split(",");
                if (d.length < 7)
                    continue;

                Expenses e = new Expenses();
                e.setId(Integer.parseInt(d[0]));
                e.setAmount(Double.parseDouble(d[1]));
                e.setCategory(d[2]);
                e.setDate(d[3]);
                e.setNote(d[4]);
                e.setMonth(Integer.parseInt(d[5]));
                e.setYear(Integer.parseInt(d[6]));

                list.add(e);
            }

            br.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }
}

class Expenses {

    private int id;
    private double amount;
    private String category;
    private String date;
    private String note;
    private int month;
    private int year;

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public double getAmount() { return amount; }
    public void setAmount(double amount) { this.amount = amount; }
    public String getCategory() { return category; }
    public void setCategory(String category) { this.category = category; }
    public String getDate() { return date; }
    public void setDate(String date) { this.date = date; }
    public String getNote() { return note; }
    public void setNote(String note) { this.note = note; }
    public int getMonth() { return month; }
    public void setMonth(int month) { this.month = month; }
    public int getYear() { return year; }
    public void setYear(int year) { this.year = year; }
}
003

Cafe Ordering System

A console cafe simulation with a browsable menu, multi-item orders via a running cart, automatic bill calculation, and a printed receipt — fully localized in Japanese.

Java OOP HashMap Console

⚙️ Key Features

  • Browsable menu of 10 items, each with a name, price, star rating, and description
  • Separate list view and detail view for individual menu items
  • Multi-item ordering with quantities tracked in a HashMap keyed by item number
  • A balance check that blocks checkout if the customer can't cover the total
  • A printed receipt breaking down each item, quantity, and subtotal

📚 What I Learned

  • Modeling real-world roles (Customer, Waiter, Menu, Bill) as separate classes
  • Using a HashMap to track order quantities keyed by menu item number
  • Validating a purchase against available balance before charging
PracofCafe.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public class PracofCafe {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        Customer c = new Customer();
        Waiter w = new Waiter();

        System.out.println("━━━☕ Caffeine Lab ☕━━━");

        w.sayGreet();
        int members = c.tellMembers();
        w.confirmMembers(members);

        CafeDatabase db = new CafeDatabase();
        ArrayList<Menu> menu = db.getMenu();

        w.giveMenu(menu);

        CafeView view = new CafeView();

        while (true) {
            System.out.println("\n1️⃣ 一覧  2️⃣ 詳細  3️⃣ 注文へ");
            System.out.print("👉 選択: ");
            int choice = sc.nextInt();

            if (choice == 1) {
                view.showList(menu);
            } else if (choice == 2) {
                System.out.print("👉 商品番号: ");
                int no = sc.nextInt();
                if (no > 0 && no <= menu.size()) {
                    view.showDetails(menu.get(no - 1));
                }
            } else if (choice == 3) {
                break;
            } else {
                System.out.println("❌ 無効な選択");
            }
        }

        w.takeOrder();
        HashMap<Integer, Integer> orders = c.sayOrder(menu);

        int total = w.confirmOrder(orders, menu);

        if (c.getMoney() < total) {
            System.out.println("❌ お金が足りません!");
            return;
        }

        Bill b = new Bill();
        b.showBill(orders, menu, total);

        c.askBill();
        c.paybill(total);

        w.sayThanks();
    }
}

class Bill {

    public void showBill(HashMap<Integer, Integer> orders, ArrayList<Menu> menu, int total) {

        System.out.println("\n━━━━━━━━━━━━━━━━━━━━");
        System.out.println("🧾 レシート");
        System.out.println("━━━━━━━━━━━━━━━━━━━━");

        for (int key : orders.keySet()) {
            Menu m = menu.get(key - 1);
            int qty = orders.get(key);

            System.out.println("🍽️ " + m.getName() + " × " + qty + " = " + (m.getPrice() * qty) + "円");
        }

        System.out.println("━━━━━━━━━━━━━━━━━━━━");
        System.out.println("💰 合計: " + total + "円");
        System.out.println("━━━━━━━━━━━━━━━━━━━━");
    }
}

class CafeDatabase {

    public ArrayList<Menu> getMenu() {

        ArrayList<Menu> menu = new ArrayList<>();

        menu.add(new Menu("Cappuccino", 450, 4.5, "Espresso with milk foam"));
        menu.add(new Menu("Latte", 500, 4.6, "Smooth coffee with milk"));
        menu.add(new Menu("Espresso", 350, 4.3, "Strong black coffee"));
        menu.add(new Menu("Mocha", 550, 4.7, "Chocolate coffee"));
        menu.add(new Menu("Iced Coffee", 400, 4.2, "Cold coffee"));
        menu.add(new Menu("Cheesecake", 600, 4.8, "Creamy cake"));
        menu.add(new Menu("Chocolate Cake", 580, 4.7, "Rich chocolate"));
        menu.add(new Menu("Croissant", 300, 4.1, "Buttery pastry"));
        menu.add(new Menu("Sandwich", 500, 4.3, "Fresh sandwich"));
        menu.add(new Menu("Pancakes", 650, 4.6, "Soft pancakes"));

        return menu;
    }
}

class CafeView {

    public void showList(ArrayList<Menu> menu) {

        for (int i = 0; i < menu.size(); i++) {
            Menu m = menu.get(i);

            System.out.println("━━━━━━━━━━━━━━━━━━━━");
            System.out.println("🍽️ No." + (i + 1));
            System.out.println("📌 " + m.getName());
            System.out.println("💰 " + m.getPrice() + "円");
        }
    }

    public void showDetails(Menu m) {

        System.out.println("━━━━━━━━━━━━━━━━━━━━");
        System.out.println("🍽️ " + m.getName());
        System.out.println("💰 " + m.getPrice() + "円");

        System.out.print("⭐ " + m.getRating() + " ");
        for (int i = 0; i < (int) m.getRating(); i++) {
            System.out.print("★");
        }
        System.out.println();

        System.out.println("📝 " + m.getDetail());
        System.out.println("━━━━━━━━━━━━━━━━━━━━");
    }
}

class Menu {
    private String name;
    private int price;
    private double rating;
    private String detail;

    public Menu(String name, int price, double rating, String detail) {
        this.name = name;
        this.price = price;
        this.rating = rating;
        this.detail = detail;
    }

    public String getName() { return name; }
    public int getPrice() { return price; }
    public double getRating() { return rating; }
    public String getDetail() { return detail; }
}

class Customer {

    private int money = 2000;
    Scanner sc = new Scanner(System.in);

    public int getMoney() {
        return money;
    }

    public int tellMembers() {
        System.out.print("👉 何名様ですか?: ");
        return sc.nextInt();
    }

    public HashMap<Integer, Integer> sayOrder(ArrayList<Menu> menu) {

        HashMap<Integer, Integer> orders = new HashMap<>();

        while (true) {
            System.out.println("\n1️⃣ 注文する  2️⃣ 終了");
            System.out.print("👉 選択: ");
            int choice = sc.nextInt();

            if (choice == 1) {
                System.out.print("👉 商品番号: ");
                int item = sc.nextInt();

                if (item < 1 || item > menu.size()) {
                    System.out.println("❌ 無効");
                    continue;
                }

                System.out.print("👉 数量: ");
                int qty = sc.nextInt();

                orders.put(item, orders.getOrDefault(item, 0) + qty);
                System.out.println("✅ 追加しました!");

            } else if (choice == 2) {
                break;
            }
        }
        return orders;
    }

    public void askBill() {
        System.out.println("🧑‍💼 お会計お願いします。");
    }

    public void paybill(int total) {
        System.out.println("💳 支払い中...");
        money -= total;
        System.out.println("💸 残高: " + money + "円");
    }
}

class Waiter {

    public void sayGreet() {
        System.out.println("👨‍🍳 いらっしゃいませ!");
    }

    public void confirmMembers(int members) {
        System.out.println("👨‍🍳 " + members + "名様ですね。お席へご案内します。");
    }

    public void giveMenu(ArrayList<Menu> menu) {
        System.out.println("📖 メニューになります。");
    }

    public void takeOrder() {
        System.out.println("👨‍🍳 ご注文をお伺いします。");
    }

    public int confirmOrder(HashMap<Integer, Integer> orders, ArrayList<Menu> menu) {

        int total = 0;

        System.out.println("\n━━━━━━━━━━━━━━━━━━━━");
        System.out.println("✅ ご注文確認");

        for (int key : orders.keySet()) {
            Menu m = menu.get(key - 1);
            int qty = orders.get(key);

            System.out.println("🍽️ 「" + m.getName() + "」× " + qty);
            total += m.getPrice() * qty;
        }

        System.out.println("━━━━━━━━━━━━━━━━━━━━");
        return total;
    }

    public void sayThanks() {
        System.out.println("🙏 ありがとうございました!またお越しください!");
    }
}
004

Student Management System

A console app for managing student records — add new students, list everyone on file, or search by name or country — with all data persisted to a CSV file between sessions.

Java File I/O ArrayList

⚙️ Key Features

  • Add a student with student number, name, age, and country
  • List every registered student
  • Search students by a partial, case-insensitive match on name or country
  • Data persists across runs via a CSV file (Students.csv)

📚 What I Learned

  • Separating concerns into Screen (view), StudentDatabase (persistence), and Student (model)
  • Appending to and reading from a CSV file with try-with-resources
  • Handling a missing data file gracefully on first run
School.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Scanner;

public class School {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        StudentDatabase sd = new StudentDatabase();
        Screen view = new Screen();

        while (true) {
            System.out.println("\n1. Student List  2. Student Details  3. Add Student  0. End");
            int menu = sc.nextInt();
            sc.nextLine();

            if (menu == 1) {
                ArrayList<Student> students = sd.getStudents();
                view.displayList(students);

            } else if (menu == 2) {
                ArrayList<Student> students = sd.getStudents();
                System.out.println("Enter Name or Country:");
                String word = sc.nextLine();
                view.displayDetails(students, word);

            } else if (menu == 3) {

                Student s = new Student();
                System.out.println("Enter the Student NO:");
                String studentNo = sc.nextLine();

                System.out.println("Enter the name:");
                String name = sc.nextLine();

                System.out.println("Enter the age:");
                int age = sc.nextInt();
                sc.nextLine();

                System.out.println("Enter the country:");
                String country = sc.nextLine();

                s.setStudentNo(studentNo);
                s.setName(name);
                s.setAge(age);
                s.setCountry(country);

                sd.insertData(s);

                System.out.println("✅ Student Added Successfully!");

            } else if (menu == 0) {
                System.out.println("Exiting...");
                break;

            } else {
                System.out.println("❌ Invalid Choice");
            }
        }

    }
}

class Screen {

    public void displayDetails(ArrayList<Student> students, String word) {
        boolean found = false;

        for (Student s : students) {
            if (s.getName().toLowerCase().contains(word.toLowerCase())
                    || s.getCountry().toLowerCase().contains(word.toLowerCase())) {

                System.out.println("[StudentNO] " + s.getStudentNo());
                System.out.println("[Name] " + s.getName());
                System.out.println("[Age] " + s.getAge());
                System.out.println("[Country] " + s.getCountry());
                System.out.println("--------------------------");

                found = true;
            }
        }

        if (!found) {
            System.out.println("No matching student found.");
        }
    }

    public void displayList(ArrayList<Student> students) {
        if (students.isEmpty()) {
            System.out.println("No students found.");
            return;
        }

        for (Student s : students) {
            System.out.println("[StudentNO] " + s.getStudentNo());
            System.out.println("[Name] " + s.getName());
            System.out.println("---------------------");
        }
    }
}

class StudentDatabase {

    public void insertData(Student s) {
        try (FileWriter fw = new FileWriter("Students.csv", true)) {

            fw.write(s.getStudentNo() + "," +
                    s.getName() + "," +
                    s.getAge() + "," +
                    s.getCountry() + "\n");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public ArrayList<Student> getStudents() {

        ArrayList<Student> students = new ArrayList<>();

        try (BufferedReader br = new BufferedReader(new FileReader("Students.csv"))) {

            String line;

            while ((line = br.readLine()) != null) {
                String[] arr = line.split(",");

                if (arr.length < 4)
                    continue;

                Student s = new Student();

                s.setStudentNo(arr[0]);
                s.setName(arr[1]);
                s.setAge(Integer.parseInt(arr[2]));
                s.setCountry(arr[3]);

                students.add(s);
            }

        } catch (Exception e) {
            System.out.println("No data file found yet.");
        }

        return students;
    }
}

class Student {

    private String studentNo;
    private String name;
    private int age;
    private String country;

    public String getStudentNo() { return studentNo; }
    public void setStudentNo(String studentNo) { this.studentNo = studentNo; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getCountry() { return country; }
    public void setCountry(String country) { this.country = country; }
}
005

Osaka Tourism Website

A multi-page site introducing Osaka's culture, food, and top attractions, complete with a live embedded weather widget and a quick-facts table covering population and highlights.

HTML CSS Weather Widget

⚙️ Key Features

  • Hero section with a full-width image and overlaid intro text
  • Sections covering Osaka's culture, access by shinkansen, must-see spots, and basic facts
  • A live weather widget embedded via external JavaScript
  • In-page navigation to related pages (food culture, attractions) with hover effects

📚 What I Learned

  • Structuring a multi-page site with consistent navigation
  • Layering styled text over a background image with absolute positioning
  • Embedding a third-party JavaScript widget into a static page
osaka.html (snippet)
<div style="position: relative;">
  <img src="osaka.jpg" width="100%">
  <p style="position:absolute;
    top:20px; left:20px;">
    Osaka is a charming, relaxed city...
  </p>
</div>
View Page
006

Ramen Menu Website

A restaurant-style ramen menu page inspired by Ippudo, featuring hover-animated dish cards with images, prices, and short descriptions for each bowl.

HTML CSS UI Design

⚙️ Key Features

  • Menu items displayed as image-and-text cards for each ramen dish
  • Flexbox layout placing dish photos beside name, tagline, and description
  • A hover animation that lifts each card slightly on mouseover
  • Ippudo-inspired branding and typography

📚 What I Learned

  • Building card-based layouts with Flexbox
  • Using CSS transitions and transform for hover interactions
  • Combining imagery and typography to evoke a restaurant brand
ramenp.css (snippet)
.menu-item {
  display: flex;
  gap: 20px;
  transition: 0.3s;
}
.menu-item:hover {
  transform: translateY(-5px);
}
View Page
007

Slot Machine Game

A console-based slot machine game where players bet coins and spin random symbols to win rewards.

Java Random Console

⚙️ Key Features

  • Starts with a 1000-coin balance
  • Player chooses a bet amount before each spin
  • Three random animal symbols are generated per spin
  • Matching all three pays out bet × 100; a non-match subtracts the bet
  • A short delay between symbol reveals for spin-style pacing

📚 What I Learned

  • Generating and comparing random values across an array
  • Using Thread.sleep() to pace output and simulate a spinning reel
  • Validating bets against the current balance
Test14.java
import java.util.Random;
import java.util.Scanner;

public class Test14 {

    public static void main(String[] args) throws Exception {
        Random r = new Random();
        Scanner sc = new Scanner(System.in);

        System.out.println("ASE GAMBLE!!!!");

        String[] animals = { "😺", "🐶", "🦁", "🐎", };
        int[] result = new int[3];

        int money = 1000;

        while (true) {

            System.out.println("BALANCE : " + money);
            System.out.println("YOU CAN CHOOSE AMOUNT PER SPIN");
            int spin = sc.nextInt();
            if (spin > money) {
                System.out.println("INSUFFICIENT BALANCE");
                System.out.println("DO YOU WANNA CONTINUE. 1.YES  2.NO");
                int ans = sc.nextInt();
                if (ans == 2) {
                    System.out.println("THANK YOU FOR PLAYING");
                    break;
                }
                System.out.println("YOU CAN CHOOSE AMOUNT PER SPIN");
                spin = sc.nextInt();
            }
            for (int i = 0; i < 3; i++) {
                int n = r.nextInt(animals.length);
                new Thread().sleep(1000);
                System.out.print(animals[n]);
                result[i] = n;
            }
            System.out.println();

            if (result[0] == result[1] && result[1] == result[2]) {

                System.out.println("YOU WON");
                money = spin * 100;

            } else {
                System.out.println("TRY AGAIN!!");
                money -= spin;
            }
            System.out.println("DO YOU WANNA CONTINUE. 1.YES  2.NO");
            int ans = sc.nextInt();
            if (ans == 2) {
                System.out.println("THANK YOU FOR PLAYING");
                break;
            }
        }

    }
}
008

Rock-Paper-Scissors Betting Game

A betting game where players compete against the computer and gain or lose coins based on results.

Java Game Logic Random

⚙️ Key Features

  • Starts with a 1000-yen balance and tracks win/loss counts
  • Player bets an amount, then picks rock, paper, or scissors
  • The computer's move is chosen at random
  • Win pays triple the bet, loss forfeits the bet, draw leaves the balance unchanged
  • A short 'thinking' animation plays before the result

📚 What I Learned

  • Implementing full win/lose/draw logic with chained conditionals
  • Tracking cumulative stats (wins, losses) across a game loop
  • Adding small delays and emoji to improve the console UX
Test29.java
import java.util.Random;
import java.util.Scanner;

public class Test29 {

    public static void main(String[] args) throws Exception {

        Random r = new Random();
        Scanner sc = new Scanner(System.in);

        System.out.println("✊🖐️✌️ゲーム");

        int money = 1000;
        int win = 0;
        int lose = 0;

        System.out.println("BALANCE:¥" + money);

        while (true) {
            if (money == 0) {
                System.out.println("お金が無くなりました");
                break;
            }

            System.out.println("いっかいいくら賭けますか?");
            int bet = sc.nextInt();

            if (bet > money) {
                System.out.println("お金足りません");
            }

            System.out.println("1:✊グー 2:✌️チョキ 3:🖐️パー");
            int a = sc.nextInt();

            for (int i = 1; i <= 5; i++) {
                System.out.print("🤔");
                new Thread().sleep(500);
            }
            System.out.println();

            int b = r.nextInt(3);

            if (a == 1 && b == 0) {
                System.out.println("DRAW RESULT あなたは✊グー PCも✊グー");
            } else if (a == 1 && b == 1) {
                System.out.println("WIN RESULT あなたは✊グー PCは✌️チョキ");
                money += bet * 3;
                win++;
            } else if (a == 1 && b == 2) {
                System.out.println("LOSE RESULT あなたは✊グー PCも🖐️パー");
                money -= bet;
                lose++;
            } else if (a == 2 && b == 1) {
                System.out.println("DRAW RESULT あなたは✌️チョキー PCも✌️チョキー");
            } else if (a == 2 && b == 2) {
                System.out.println("WIN RESULT あなたは✌️チョキ PCは🖐️パー");
                money += bet * 3;
                win++;
            } else if (a == 2 && b == 0) {
                System.out.println("LOSE RESULT あなたは✌️チョキ PCは✊グー");
                money -= bet;
                lose++;
            } else if (a == 3 && b == 2) {
                System.out.println("DRAW RESULT あなたは🖐️パー PCも🖐️パー");
            } else if (a == 3 && b == 0) {
                System.out.println("WIN RESULT あなたは🖐️パー PCは✊グー");
                money += bet * 3;
                win++;
            } else if (a == 3 && b == 1) {
                System.out.println("LOSE RESULT あなたは🖐️パー PCは✌️チョキー");
                money -= bet;
                lose++;
            }
            System.out.println("お金:¥" + money);

            System.out.println("1:もう一回する 2:終わる");
            int p = sc.nextInt();
            if (p == 2) {
                System.out.println("YOU HAVE ¥" + money);
                System.out.println(win + "回勝ちました");
                System.out.println(lose + "回負けました");
                break;

            }

        }

    }

}
008

ASE Shop

A team-built e-commerce app. The Java backend reads a product catalog from SQLite and generates a live storefront across 12 categories, while an embedded HTTP server handles cart actions, stock validation, and checkout directly in the browser — including delivery date estimates and per-item subtotals.

Java SQLite/JDBC MVC HTTP Server

⚙️ Key Features

  • Products loaded from a SQLite database and rendered into a browsable HTML storefront across 12 categories
  • An embedded HTTP server (com.sun.net.httpserver) serves the cart, add/remove/decrease actions, and checkout as live web routes
  • Cart state is a synchronized list, checked against live stock before an item can be added or purchased
  • Checkout decrements stock per item, rolls back items that fail, and shows a total plus a randomized delivery date
  • Star ratings and review counts are generated deterministically per product as sample data

📚 What I Learned

  • Standing up a lightweight HTTP server in plain Java without a framework
  • Coordinating shared mutable state (the cart) safely across concurrent requests with synchronized blocks
  • Separating business logic (CartService) from the web layer (CartServer) so the console app and the browser share the same rules
  • Working as a team on a shared MVC codebase split across entity, model, view, controller, and web packages
CartService.java
public class CartService {

    private final ProductModel model;
    private final List<CartItem> cart;

    public String addToCart(int productId, int quantity) {
        synchronized (cart) {
            Product product = model.findById(productId);
            if (product == null) {
                return "該当する商品が見つかりませんでした。";
            }

            CartItem existing = findInCart(product.getProductid());
            int alreadyInCart = (existing != null) ? existing.getQuantity() : 0;
            int available = product.getStock() - alreadyInCart;

            if (quantity <= 0 || quantity > available) {
                return "在庫が足りません。追加できる数量: " + available;
            }

            if (existing != null) {
                existing.setQuantity(existing.getQuantity() + quantity);
            } else {
                cart.add(new CartItem(product, quantity));
            }

            return product.getName() + "をカートに追加しました。";
        }
    }

    public CheckoutResult checkout() {
        synchronized (cart) {
            if (cart.isEmpty()) {
                return new CheckoutResult(false, 0, "カートが空です。商品を追加してください。", null);
            }

            List<CartItem> purchased = new ArrayList<CartItem>();
            StringBuilder failures = new StringBuilder();

            for (CartItem item : cart) {
                boolean ok = model.decreaseStock(item.getProduct().getProductid(), item.getQuantity());
                if (ok) {
                    purchased.add(item);
                } else {
                    failures.append(item.getProduct().getName())
                            .append("は在庫不足のため注文できませんでした。カートに残しています。 ");
                }
            }

            int total = 0;
            for (CartItem item : purchased) {
                total += item.getSubtotal();
            }

            cart.removeAll(purchased);

            String message = failures.length() > 0 ? failures.toString().trim() : null;
            return new CheckoutResult(true, total, message, purchased);
        }
    }
}
009

Employee Management System

A console-based employee database app with full CRUD — list, keyword search, ID lookup, add, update, and delete — all backed by a real SQLite database accessed through JDBC with parameterized queries.

Java JDBC SQLite CRUD

⚙️ Key Features

  • Full CRUD menu: list all, keyword search, ID lookup, add, update, and delete employee records
  • Every query uses a PreparedStatement with bound parameters, avoiding SQL injection
  • Keyword search runs a LIKE query so a partial name match still finds the employee
  • Insert retrieves the auto-generated employee ID back from SQLite after the row is created
  • Update pre-fills each prompt with the employee's current value so nothing has to be retyped from scratch

📚 What I Learned

  • Writing parameterized SQL with JDBC instead of concatenating strings
  • Reading auto-generated keys back from an INSERT with Statement.RETURN_GENERATED_KEYS
  • Keeping the model layer (SQL) fully separate from the controller (menu flow) and view (console output)
EmployeeModel.java
public class EmployeeModel {

    public ArrayList<Employee> findByKeyword(String word) {

        ArrayList<Employee> employees = new ArrayList<Employee>();

        try {
            Class.forName("org.sqlite.JDBC");
            Connection conn = DriverManager.getConnection("jdbc:sqlite:sample.db");

            String sql = "select * from employees where employeename like ?";
            PreparedStatement stmt = conn.prepareStatement(sql);
            stmt.setString(1, "%" + word + "%");

            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                employees.add(mapRow(rs));
            }

            conn.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return employees;
    }

    public boolean insert(Employee employee) {

        try {
            Class.forName("org.sqlite.JDBC");
            Connection conn = DriverManager.getConnection("jdbc:sqlite:sample.db");

            String sql = "insert into employees "
                    + "(employeename, height, email, weight, hirefiscalyear, birthday, bloodtype) "
                    + "values (?, ?, ?, ?, ?, ?, ?)";

            PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            stmt.setString(1, employee.getEmployeeName());
            stmt.setDouble(2, employee.getHeight());
            stmt.setString(3, employee.getMail());
            stmt.setDouble(4, employee.getWeight());
            stmt.setInt(5, employee.getHiredfiscalyear());
            stmt.setString(6, employee.getDOB());
            stmt.setString(7, employee.getBloodType());

            int count = stmt.executeUpdate();

            if (count > 0) {
                ResultSet keys = stmt.getGeneratedKeys();
                if (keys.next()) {
                    employee.setEmployeeId(keys.getInt(1));
                }
            }

            conn.close();
            return count > 0;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }
}
010

Robocode AI Combat Bot

An AI-controlled combat robot for the Robocode battle simulator. Duels run on a segmented GuessFactor targeting gun with a hit-rate-based linear-targeting fallback, paired with wave-surfing movement that kinematically simulates its own dodge options in real time. Free-for-all melee rounds switch to separate nearest/weakest-target logic and risk-scored waypoint movement around a home corner.

Java Robocode API AI/Targeting Simulation

⚙️ Key Features

  • Segmented GuessFactor gun tracking hit outcomes across 9 distance/velocity buckets, with older data decayed each update so the bot keeps adapting if an opponent changes pattern mid-match
  • A linear-targeting fallback gun chosen per-segment whenever its live hit rate beats the GuessFactor gun's, with hysteresis so a few noisy shots don't flip the aim angle every turn
  • Wave-surfing movement that kinematically simulates its own forward motion to predict danger from every incoming bullet wave in flight, then orbits in whichever direction scores safer
  • Melee mode scores targets by distance plus energy to prefer finishing off weak nearby enemies, and roams a risk-scored pocket around a fixed home corner instead of pure potential-field movement
  • Collision recovery that breaks toward the battlefield center after repeated stalls instead of endlessly retrying the same stuck move

📚 What I Learned

  • Turning a segmented GuessFactor targeting approach into working Java state kept per distance/velocity bucket
  • Running a kinematic forward simulation to predict my own future position instead of reacting only to the robot's current state
  • Designing hysteresis thresholds so a gun or target choice doesn't thrash on noisy, small-sample data
  • Structuring one robot class to cleanly branch between two very different game modes — 1v1 duels and free-for-all melee
B0347.java
int segment = segmentIndex(enemyDistance, Math.abs(enemyVelocity));

double gfRate = gfShotsFired[segment] < 5
        ? 1.0 : (double) gfHits[segment] / gfShotsFired[segment];
double linearRate = linearShotsFired[segment] < 5
        ? 1.0 : (double) linearHits[segment] / linearShotsFired[segment];

boolean useGf = currentGunIsGf[segment];
if (useGf && linearRate > gfRate + 0.1) {
    useGf = false;
} else if (!useGf && gfRate > linearRate + 0.1) {
    useGf = true;
}
currentGunIsGf[segment] = useGf;

double aimAngle;
if (useGf) {
    int bestIndex = indexOfMaxOrMiddle(gunStats[segment]);
    double guessFactor = (bestIndex - MID) / MID;
    aimAngle = absBearingNow + enemyLatDirection * guessFactor * maxEscapeAngle;
} else {
    aimAngle = linearAimAngle(myX, myY, enemyLocation.x, enemyLocation.y,
            enemyVelocity, enemyHeading, bulletVelocity);
}
012

Things To Do Together

An interactive date-activity planner servlet. Search 23 seeded activities by name, filter by budget tier, select multiple to total up the cost, and add new activities through a form — all rendered as a dynamic HTML page generated on the fly, no database involved.

Java Servlet HTML Forms Filtering

⚙️ Key Features

  • 23 seeded activities (name, budget in yen, category, duration, photo) held in an in-memory list shared across requests
  • Accent-insensitive search by name, normalizing text like "café" and "cafe" to the same match via Unicode decomposition
  • Budget filter pills — All / Free / Under ¥1,000 / Under ¥3,000 — combined with the search term through query parameters
  • Checkbox-select across the filtered list, then "Calculate Total Budget" sums the selected activities' cost
  • A form posts new activities (name, price, image URL, category, duration) straight into the shared list, visible on the next page load

📚 What I Learned

  • Building a GET/POST servlet that renders and mutates state through plain query parameters and form fields, with no framework involved
  • Writing accent-insensitive search with Unicode NFD normalization instead of a naive substring match
  • Escaping user-supplied values before writing them into generated HTML so form input can't break the markup
  • Round-tripping filter state (search text, budget tier) through hidden form fields across both the search form and the select/calculate form
Test03Controller.java
private static String normalize(String s) {
    String decomposed = Normalizer.normalize(s, Normalizer.Form.NFD);
    return decomposed.replaceAll("\\p{M}", "").toLowerCase(Locale.ROOT);
}

List<Activity> filtered = new ArrayList<>();
for (Activity a : activities) {
    boolean matchesSearch = q.isEmpty() || normalize(a.name).contains(normalize(q));
    boolean matchesBudget;
    switch (budgetFilter) {
        case "free": matchesBudget = a.budget == 0; break;
        case "under1000": matchesBudget = a.budget < 1000; break;
        case "under3000": matchesBudget = a.budget < 3000; break;
        default: matchesBudget = true;
    }
    if (matchesSearch && matchesBudget) filtered.add(a);
}
013

Omikuji Fortune Draw

An animated Japanese fortune-slip (omikuji) web app rendered entirely from a Java servlet. Click the wooden box to shake and draw one of seven weighted fortune tiers, each revealed through a card-unfold animation, with dark mode and a full reduced-motion fallback for accessibility.

Java Servlet CSS Animation Accessibility

⚙️ Key Features

  • Seven fortune tiers, from 大吉 (best) down to 大凶 (worst), each with a kanji rank, romaji reading, name, and description, picked by a weighted random roll (best/worst tiers are deliberately rarer)
  • The whole page — HTML, CSS, and inline JS — is rendered server-side from a single Java text-block template, with the chosen fortune's fields substituted in before the response is written
  • Click-to-shake animation sequence — box shake, then stick emergence, then fortune card unfold — with an ARIA live region announcing the result for screen readers
  • Dark mode via prefers-color-scheme, plus a full prefers-reduced-motion fallback that skips straight to the revealed state
  • "Draw again" reloads the page for a fresh server-side roll rather than re-randomizing on the client

📚 What I Learned

  • Using Java text blocks to template a full HTML/CSS/JS page server-side with simple string substitution, instead of a view engine
  • Weighting a random roll across unequal-probability outcomes, since the best and worst fortune tiers are intentionally rarer than the middle ones
  • Writing CSS keyframe animations that respect prefers-reduced-motion, not just prefers-color-scheme
  • Wiring an aria-live region so a purely visual reveal animation still announces its result to screen reader users
Test05Controller.java
Random r = new Random();
int num = r.nextInt(100);

String tier, kanji, romaji, name, desc;
if (num < 5) {
    tier = "best"; kanji = "大吉"; romaji = "Daikichi"; name = "最高の運";
    desc = "最高の運勢です。物事はうまくいくでしょう。";
} else if (num < 25) {
    tier = "good"; kanji = "吉"; romaji = "Kichi"; name = "良い運";
    desc = "良いことが起こりそうな、前向きな運勢です。";
} else if (num < 45) {
    tier = "good"; kanji = "中吉"; romaji = "Chūkichi"; name = "なかなか良い運";
    desc = "物事は順調に進みそうですが、少し辛抱が必要かもしれません。";
} // ...small/mid tiers omitted...
} else {
    tier = "worst"; kanji = "大凶"; romaji = "Daikyō"; name = "非常に良くない運";
    desc = "非常に良くない兆しです。断定ではなく、立ち止まって考えるきっかけと捉えましょう。";
}

String html = PAGE_TEMPLATE
        .replace("{{TIER}}", tier)
        .replace("{{KANJI}}", kanji)
        .replace("{{ROMAJI}}", romaji)
        .replace("{{NAME}}", name)
        .replace("{{DESC}}", desc);
Practice & Experiments

Practice & Experiments

Smaller coding-test solutions and one-off exercises — not full projects, but useful snapshots of problem-solving in practice.

Paiza · C166

Coin Change Counter

Breaks a yen amount into the fewest coins possible with a greedy pass over denominations from ¥500 down to ¥1.

C166.java
int[] coins = { 500, 100, 50, 10, 5, 1 };
int count = 0;
for (int coin : coins) {
    count += a / coin;
    a %= coin;
}
System.out.println(count);
Paiza · C183

Board Game Score Simulator

Simulates a sugoroku-style board: a token advances by dice rolls and accumulates each square's score until it runs off the board.

C183.java
int pos = 1;
int total = A[1];
for (int i = 0; i < M; i++) {
    int dice = sc.nextInt();
    pos += dice;
    if (pos > N) break;
    total += A[pos];
}
System.out.println(total);
Paiza · C181

String Length Range Finder

Reads N lines and tracks the running max and min string length, printing the gap between the longest and shortest.

C181.java
int max = 0;
int min = Integer.MAX_VALUE;
for (int i = 0; i < a; i++) {
    String s = sc.nextLine();
    int l = s.length();
    if (l > max) max = l;
    if (l < min) min = l;
}
System.out.println(max - min);
Paiza · C155

Keyword Match Checker

Checks a batch of candidate strings against a target keyword, printing Yes/No for whether each one contains it.

C155.java
String s = sc.nextLine();
int n = Integer.parseInt(sc.nextLine());

for (int i = 0; i < n; i++) {
    String ans = sc.nextLine();
    if (ans.contains(s)) {
        System.out.println("Yes");
    } else {
        System.out.println("No");
    }
}
Paiza · D051

Word Count Validator

Splits a space-separated string into tokens, counts how many equal a target word, and passes/fails against a minimum threshold.

D051.java
String[] ar = str.split(" ");
int count = 0;

for (int i = 0; i < ar.length; i++) {
    if (ar[i].equals("W")) {
        count++;
    }
}
System.out.println(count >= 5 ? "OK" : "NG");
Paiza · D023

Character Counter

Counts how many times a given character appears in a string by scanning it as a char array.

D023.java
char[] ar = s.toCharArray();
int count = 0;

for (int i = 0; i < ar.length; i++) {
    if (ar[i] == 'A') {
        count++;
    }
}
System.out.println(count);
Paiza · C097

FizzBuzz-Style Divisor Classifier

A FizzBuzz-style classifier: loops from 1 to N and prints AB, A, B, or N depending on which of two divisors each number is a multiple of.

C097.java
for (int i = 1; i <= n; i++) {
    if (i % a == 0 && i % b == 0) {
        System.out.println("AB");
    } else if (i % a == 0) {
        System.out.println("A");
    } else if (i % b == 0) {
        System.out.println("B");
    } else {
        System.out.println("N");
    }
}
webapp01 · Test04

Random Greeting Generator

A servlet that renders a random greeting — in Japanese, Burmese, Vietnamese, Sinhala, Hindi, or English — picked fresh on every page load.

Test04Controller.java
Random r = new Random();
int num = r.nextInt(5);

if (num == 0) {
    pw.write("<h1>こんにちは</h1>");
} else if (num == 1) {
    pw.write("<h1>မင်္ဂလာပါ</h1>");
} else if (num == 2) {
    pw.write("<h1>Xin chào</h1>");
} // ...Sinhala, Hindi, and English cases follow the same pattern...
Lesson05 · Myapp02

Kanji Reading Quiz

A multiple-choice quiz testing kanji readings (努力, 労働者, 時間, 季節, 誕生日), tallying a running score as each answer is checked against the correct reading.

Myapp02.java
System.out.println("Q.1 努力");
System.out.println("1.どりょく 2.どうりょく 3.どおりょく");
int ans1 = sci.nextInt();
if (ans1 == 2 || ans1 == 3) {
    System.out.println("WRONG ANSWER");
} else {
    System.out.println("CORRECT");
    score++;
}
// ...remaining questions follow the same check-and-score pattern...
← Back to Main Projects