Anteckningar från föreläsning 17 och 18 (måndag för- och eftermiddag)

Detta är den programkod vi skrev -- anteckningarna är gjorda bara för att vara ett stöd för minnet för dem som var där, och därför inte nödvändigtvis fullständiga eller ens sammanhängande. Betydligt mer hjälp finns att hämta i kompendiet.

OH-bilder finns här.

Abstrakta klasser

Vi började med att prata om abstrakta klasser, och använde inlämningsuppgift 6 som exempel

abstract class RaceTurtle extends Turtle {

    // ...

    public abstract void raceStep();
}

class SeriousRacer extends RaceTurtle {

    public void racestep() {
        // tar ett seriöst steg
    }
}

Mer om static

Vi fortsatte sedan med en kort repetition av static, och löste följande tre problem:

class Turtle {

    private double x, y;
    private int dir;
    private boolean draws;
    private GrapicsWindow w;

    private static List allTurtles = new ArrayList();
    private static int longestStep;
    private static int nbrOfTurtles;

    public Turtle  (GrapicsWindow w, double x, double y) {
        this.w = w;
        this.x = x;
        this.y = y;
        allTurtles.add(this);
        nbrOfTurtles++;
    }

    public static int getNbrOfTurtles() {
        return nbrOfTurtles;
    }

    public void forward(int steps) {
        // som tidigare
        if (steps > longestStep) {
            longestStep = steps;
        }
    }

    public void penDown() {
        draws = true;
    }

    public static int getLongestStep() {
        penDown();
        return longestStep;
    }
}

För att räkna hur många paddor som har skapats kan vi skriva:

class TurtleCensus {

    public static void main(String[] args) {
        new TurtleCensus().run();
    }

    GrapicsWindow w;

    void run() {
        w = new GrapicsWindow(500, 500);
        for (int k = 1; k <= 10; k++) {
            new Turtle(w, 10, 10);
        }
        census();
    }

    void census() {
        System.out.println("Antal paddor: " +
                           Turtle.getNbrOfTurtles());

    }
}

Vi kan även packa ihop olika funktioner och konstanter i ett 'paket' (som Math):

class OurMath {

    public static double sqrt(double x) {
        return 1 + x/2;
    }

    public static final double PI = ...;
}

Huvudprogrammet

Vårt huvudprogram är en static-metod:

class MainProgram {

    private static int meaningOfLife = 42;

    public static void main(String[] args) {
        greetings();
    }

    static void greetings() {
        System.out.println("hello, world");
        System.out.println(meaningOfLife);
    }
}

class MainProgram {

    private static int meaningOfLife = 42;

    public static void main(String[] args) {
        for (String arg : args) {
            System.out.println(arg);
        }
    }
}

Vi kan testa programmet genom att köra:

$ java MainProgram one two three
one
two
three

Arv för att återanvända programskelett

Vi kan betrakta våra program som objekt med en run()-metod, och kan då anropa ett FunGame-objekt genom att skriva:

class Main {

    public static void main(String[] args) {
        FunGame game = new FunGame();
        game.run();
    }
}

Vi skrev först en allmän spelklass:

abstract class GameTemplate {

    protected DotWindow w;

    public void run() {
        setup();
        mainLoop();
    }

    public abstract void setup();

    public void mainLoop() {
        while (true) {
            GameEvent e = w.getNextEvent();
            switch (e.getKind()) {
            case GameEvent.KEY_PRESSED:
                keyPressed(e.getKey(), e.getKeyCode());
                break;
            case GameEvent.MOUSE_CLICKED:
                mouseClicked(e.getX(), e.getY());
                break;
            case GameEvent.TICK:
                tick();
                break;
            }
        }
    }

    public void keyPressed(char key, int keyCode) {
        System.out.println("Du har uppenbarligen inte överskuggat keyPressed");
    }

    public void mouseClicked(int x, int y) {
        System.out.println("Du har uppenbarligen inte överskuggat mouseClicked");
    }

    public void tick() {
        System.out.println("Du har uppenbarligen inte överskuggat tick");
    }
}

Denna klass kan vi utvidga till ett väldigt enkelt spel:

class FunGame extends GameTemplate {

    public static void main(String[] args) {
        new FunGame().run();
    }

    Random rng = new Random();

    public void setup() {
        w = new DotWindow(50, 50, 10);
        w.checkKeys(true, false, false);
        w.checkMouse(true, false, false, false, false);
        w.timeStep(100);
    }

    public void mouseClicked(int x, int y) {
        w.setDot(x, y, Color.BLUE);
    }

    public void tick() {
        w.setDot(rng.nextInt(w.getWidth()), rng.nextInt(w.getHeight()), Color.GREEN);
    }
}

och detta spel kan alltså köras genom att vi skriver:

class Main {

    public static void main(String[] args) {
        FunGame game = new FunGame();
        game.run();
    }
}

Sortering och sökning

Vi diskuterade sedan olika sätt att sortera en vektor med heltal, och skrev följande program:

class MainAgain {

    public static void main(String[] args) {
        new MainAgain().run();
    }

    void run() {
        int[] values = {3,5,2,1,6,9};
        Sorting.sort(values, values.length);
        Sorting.print(values, values.length);
    }
}

class Sorting {

    public static void sort(int[] v, int size) {
        for (int k = 0; k < size; k++) {
            int minIndex = indexOfSmallest(v, k, size-1);
            swap(v, k, minIndex);
        }
    }

    private static int indexOfSmallest(int[] v, int first, int last) {
        int smallest = first;
        for (int k = first + 1; k <= last; k++) {
            if (v[k] < v[smallest]) {
                smallest = k;
            }
        }
        return smallest;
    }

    private static void swap(int[] v, int a, int b) {
        int tmp = v[a];
        v[a] = v[b];
        v[b] = tmp;
    }

    public static void print(int[] v, int size) {
        for (int k = 0; k < size; k++) {
            System.out.printf("%4d: %6d\n", k, v[k]);
        }
    }

    public static int binarySearch(int value, int[] v, int size) {
        int min = 0;
        int max = size - 1;
        while (min <= max) {
            int mid = (min + max) / 2;
            if (v[mid] < value) {
                min = mid + 1;
            } else if (v[mid] > value) {
                max = mid - 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
}