Java Arena
Step 7 of 7

Planning a whole program

You've now seen every piece of a program with a text user interface. When you write one from scratch, this order keeps each step small:

  1. Write down the commands and what each one prints, best as a short example conversation.
  2. Decide what the program must remember between commands. Those are the instance variables of the logic class.
  3. For each command, decide what the logic must do or answer. Those are its public methods: parameters for what comes in, return values for what goes out, and no printing.
  4. Write the logic class, and try it with a few calls in main, before there's any user interface.
  5. Write the UserInterface class: a constructor that takes the Scanner and the logic object, and start() with the command loop, one branch per command.
  6. Make main create the objects and call start().

Here are the first four for a coat check at a theater. Guests leave their coat and get a ticket with the number of its hook, and the ticket gets them their coat back:

Command What it prints
leave, then a name Ana, your ticket is 1
collect, then a ticket number Here's your coat, Ana, or No coat on hook 7
coats Coats: 2
quit Good night

The coat check remembers whose coat is on which hook. A list of names does that: the hook's number is one more than its index, and a hook that's free again holds null. A new coat goes on the first free hook, or on a new hook at the end. Before writing any user interface, main tries the class out:

Main.java
public class Main {
    public static void main(String[] args) {
        CoatCheck check = new CoatCheck();
        int ana = check.leave("Ana");
        int ben = check.leave("Ben");
        System.out.println(ana + " " + ben + " " + check.coats());
        System.out.println(check.collect(ana));
        System.out.println(check.collect(ana));
        System.out.println(check.leave("Cleo") + " " + check.coats());
    }
}
CoatCheck.java
import java.util.ArrayList;

public class CoatCheck {
    private ArrayList<String> hooks;

    public CoatCheck() {
        this.hooks = new ArrayList<>();
    }

    public int leave(String owner) {
        for (int i = 0; i < this.hooks.size(); i++) {
            if (this.hooks.get(i) == null) {
                this.hooks.set(i, owner);
                return i + 1;
            }
        }
        this.hooks.add(owner);
        return this.hooks.size();
    }

    public String collect(int ticket) {
        if (ticket < 1 || ticket > this.hooks.size()) {
            return null;
        }
        String owner = this.hooks.get(ticket - 1);
        this.hooks.set(ticket - 1, null);
        return owner;
    }

    public int coats() {
        int count = 0;
        for (String owner : this.hooks) {
            if (owner != null) {
                count++;
            }
        }
        return count;
    }
}
Output
1 2 2
Ana
null
1 2
  • leave returns the ticket number, and collect returns the owner's name. The logic answers with values, and the user interface will turn them into sentences.
  • collect returns null when there's no coat on that hook, or no such hook at all. That's the logic's way of saying "no coat". Printing No coat on hook 7 is up to the user interface.
  • After Ana collects her coat, her hook is free: the second collect(ana) finds it empty and returns null. Cleo's coat then goes on hook 1, the first free one.
  • These few lines already show that the logic works. If the whole program then misbehaves, the mistake is most likely in the user interface.

This step ends the MOOC's section 6.2. The next module is about testing: checking automatically that a logic class such as CoatCheck gives the right answers.

Your task

Challenge 1 of 3

Steps 5 and 6 for the coat check. CoatCheck.java is the class above, and Main.java is ready. Write UserInterface.java: its constructor takes a Scanner and a CoatCheck, and start() runs the commands of the table, with the prompt > before each one. Anything else prints Unknown command: and the command. For the input shown, the program prints:

> Ana, your ticket is 1
> Ben, your ticket is 2
> Coats: 2
> Here's your coat, Ana
> No coat on hook 1
> Cleo, your ticket is 1
> No coat on hook 7
> Coats: 2
> Good night

Challenge 2

A savings account program. Write the logic class, Account.java, and the user interface, UserInterface.java. Main.java is ready.

Account has a balance, 0 at the start, and a history of the changes to it, in a list: a deposit adds a positive number to the history, a withdrawal a negative one. Its methods:

  • deposit(int amount): adds the amount to the balance, and to the history.
  • withdraw(int amount): if the balance is too small, changes nothing and returns false. Otherwise takes the amount off the balance, adds -amount to the history, and returns true.
  • getBalance(): returns the balance.
  • history(): returns the history, an ArrayList<Integer>.

UserInterface takes a Scanner and an Account, and start() reads commands, with the prompt > before each one:

  • deposit, then a line with the amount: print Balance: and the new balance.
  • withdraw, then a line with the amount: print Balance: and the new balance, or Not enough money.
  • history: print History: and the list, like History: [50, -20].
  • quit: print Goodbye and return.
  • Anything else: print Unknown command: and the command.

For the input shown, the program prints:

> Balance: 50
> Balance: 30
> Not enough money
> Balance: 45
> History: [50, -20, 15]
> Goodbye

Challenge 3

A library card program, all of it: LibraryCard.java, UserInterface.java and Main.java.

LibraryCard holds the titles of the books borrowed on the card, and a limit to how many books can be borrowed at a time. Its methods:

  • LibraryCard(int limit): a card with no books, for at most limit books at a time.
  • has(String title): returns true when that book is borrowed on the card.
  • isFull(): returns true when limit books are borrowed.
  • borrow(String title): adds the book to the card. The user interface only calls it when the card isn't full and doesn't have the book.
  • giveBack(String title): removes the book and returns true, or returns false if it isn't on the card.
  • books(): returns the titles, an ArrayList<String>, in the order they were borrowed.

UserInterface takes a Scanner and a LibraryCard, and start() reads commands, with the prompt > before each one:

  • borrow, then a line with a title: print You already have and the title when the card has it, otherwise Your card is full when it's full, and otherwise borrow the book and print Borrowed and the title.
  • return, then a line with a title: give the book back and print Returned and the title, or print the title and isn't on your card.
  • books: print Books: and the list of titles.
  • quit: print See you soon and return.
  • Anything else: print Unknown command: and the command.

main creates a card with the limit 3 and starts the user interface. For the input shown, the program prints:

> Borrowed Emma
> Borrowed Dune
> You already have Emma
> Borrowed Ivanhoe
> Your card is full
> Returned Dune
> Dune isn't on your card
> Borrowed Beloved
> Books: [Emma, Ivanhoe, Beloved]
> See you soon