Howdy. 

Christian, Kayl, Levi, Seth, Jiebo, Alex S, Vanessa, Mike C, 
He He, Arif is sick today, Jiahao, Keqin, Yinan, Arthi, Joe,
Andrew T, Sunghyun, Alex Q, Zhiwei, Xing, Kevin, Rerajitha, 
David, Brandon, Andrew R, Danny N, Siddartha, Haoyang, Xinyu,
Rajeev, Chenrui and Matt. 

Homework 07 (Puzzle) is due before the end of the semester. 

Lab 12 (Tomcat Manager) will be done in lab today. 

Homework 08 (Project Stage One).

Homework 09 (Project Stage Two).

Project Final Stage will be by itself. 

Final Exam next week (there will be a study guide/review). 

Here's Stage Two of the project from Spring 2015: 

https://www.cs.indiana.edu/classes/c212-dgerman/spr2015/prjsttwo.html

Here's a sample Final Exam from that same semester: 

http://www.cs.indiana.edu/classes/c212-dgerman/spr2015/sampleFinal.pdf

Here's a solution to the sample final:

...

Next we discuss a DrJava feature:

class One {
  
}

class Two {
  
}

class Three {
  public static void main(String[] args) {
    System.out.println("Howdy.");  
  }
}

If we put all of that in the same file and save it becomes One.java

Then the Run button will immediately call main in One (which does not exist).

You can always remember that the GUI buttons boil down to:

Welcome to DrJava.  Working directory is C:\Users\dgerman\Desktop
> run One
Static Error: This class does not have a static void main method accepting String[].
> run Two
Static Error: This class does not have a static void main method accepting String[].
> run Three
Howdy.


Before we start the project we discuss how getting there is more 
important than the destination. Also how we develop (practice not
until you get it right, practice until you can't get it wrong). 

What's New April 16 Thu Spring 2015

import javax.swing.*; 
import java.awt.event.*; 

class Show implements ActionListener {
  int count = 0, limit = 6; 
  Timer t; 
  Show(Timer t) {
    this.t = t; 
  }
  public void actionPerformed(ActionEvent e) {
    this.count += 1; 
    if (this.count == this.limit) { 
      System.out.println(this.count + ". Show picture and say good bye."); 
      t.stop();
    } else { 
      System.out.println(this.count + ". Show picture.");
    }
  }
}

class Jiawei {
  public static void main(String[] args) {
    Timer t = new Timer(700, null); 
    Show s = new Show(t); 
    t.addActionListener(s); 
    t.start();
  }
}

This was Jiawei's afternoon project then and it's interesting. 

We go back to the project now:


import java.awt.*; 
import java.awt.event.*; 

interface World {
  public void draw(Graphics g);
  public void update(); 
  public boolean hasEnded();
  public void keyPressed(KeyEvent e); 
}


import javax.swing.*; 
import java.awt.event.*; 
import java.awt.*; 

class BigBang extends JComponent implements KeyListener, ActionListener {
  Timer timer; 
  World world; 
  BigBang(int delay, World world) {
    timer = new Timer(delay, this); 
    this.world = world;
  } 
  public void start() {
    timer.start();  
  }
  BigBang(World world) {
    this(1000, world);  
  }
  public void paintComponent(Graphics g) {
    world.draw(g);  
  }
  public void actionPerformed(ActionEvent e) {
    world.update(); 
    if (world.hasEnded())
      timer.stop(); 
    this.repaint(); 
  }
  public void keyPressed(KeyEvent e) { 
    world.keyPressed(e); 
    this.repaint(); 
  } 
  public void keyTyped(KeyEvent e) { } 
  public void keyReleased(KeyEvent e) { } 
}

So this is the engine. 

This is general. 

More than one game can rely on this. 

I compile and close these two files. 

I won't change them ever. 

What will change? The actual code. 

Here's the actual code: 

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

class Tetris implements World {
  Tetromino t; 
  SetOfBlocks blocks; 
  Tetris(Tetromino t, SetOfBlocks s) {
    this.t = t;
    this.blocks = s; 
  }
  public void draw(Graphics g) { // world->image
    // System.out.println("World being drawn."); 
    t.draw(g); 
  } 
  public void update() { 
    // System.out.println("World getting older."); 
  }
  public boolean hasEnded() { return false; } 
  public void keyPressed(KeyEvent e) { // world-key-move
    // System.out.println("Ouch."); 
    if      (e.getKeyCode() == KeyEvent.VK_UP   ) { this.t.move( 0, -1); }
    else if (e.getKeyCode() == KeyEvent.VK_DOWN ) { this.t.move( 0,  1); }
    else if (e.getKeyCode() == KeyEvent.VK_LEFT ) { this.t.move(-1,  0); }
    else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { this.t.move( 1,  0); } 
    else if (e.getKeyChar() == 'q') {      // sQuare
      int dx = this.t.dx, dy = this.t.dy; 
      this.t = Tetromino.sQuare()   ; 
      this.t.move(dx, dy); 
    } else if (e.getKeyChar() == 'n') {    // liNe
      int dx = this.t.dx, dy = this.t.dy; 
      this.t = Tetromino.liNe()     ; 
      this.t.move(dx, dy); 
    } else if (e.getKeyChar() == 'l') {    // L
      int dx = this.t.dx, dy = this.t.dy; 
      this.t = Tetromino.l()        ; 
      this.t.move(dx, dy); 
    } else if (e.getKeyChar() == 'm') {    // Mirrored l
      int dx = this.t.dx, dy = this.t.dy; 
      this.t = Tetromino.MirroredL(); 
      this.t.move(dx, dy); 
    } else if (e.getKeyChar() == 't') {    // T
      int dx = this.t.dx, dy = this.t.dy; 
      this.t = Tetromino.t()        ; 
      this.t.move(dx, dy); 
    } else if (e.getKeyChar() == 's') {    // S
      int dx = this.t.dx, dy = this.t.dy; 
      this.t = Tetromino.s()        ; 
      this.t.move(dx, dy); 
    } else if (e.getKeyChar() == 'z') {    // Z
      int dx = this.t.dx, dy = this.t.dy; 
      this.t = Tetromino.z()        ; 
      this.t.move(dx, dy); 
    } else if (e.getKeyChar() == 'r') {    // Rotate CW
      this.t.rotateCW();  
    } else this.t.move( 0, 0 ); 
    System.out.println( t ); // debug 
  } 
  public static void main(String[] args) {
    BigBang game = new BigBang(200, new Tetris(Tetromino.sQuare(), new SetOfBlocks())); 
    JFrame frame = new JFrame("Tetris"); 
    frame.getContentPane().add( game ); 
    frame.addKeyListener( game ); 
    frame.setVisible(true); 
    frame.setSize(400, 400); 
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 
    game.start(); 
  }
}

This is stage two. 

It also needs: 

import java.awt.*; 
import java.util.*; 

class SetOfBlocks extends ArrayList<Block> {
  void draw(Graphics g) {
    for (Block b : this) 
      b.draw(g); 
  }
  void move(int dx, int dy) {
    for (Block b : this) 
      b.move(dx, dy); 
  }
  void rotateCW(Point center) { // clockwise 
    for (Block b : this)
      b.rotateCW(center); 
  }
}

import java.awt.*; 

class Block {
  final static int SIZE = 20; // pixels 
  int x, y;
  Color color; 
  Block(int x, int y, Color c) {
    this.x = x;
    this.y = y;
    this.color = c; 
  }
  void draw(Graphics g) {
    int xp = this.x * SIZE + SIZE/2, yp = this.y * SIZE + SIZE/2;
    g.setColor(this.color);     
    g.fillRect(xp, yp, SIZE, SIZE); 
    g.setColor(Color.BLACK); 
    g.drawRect(xp, yp, SIZE, SIZE); 
  }
  void move(int dx, int dy) {
    this.x += dx; 
    this.y += dy; 
  }  
  public String toString() {
    return "[" + this.x + ", " + this.y + "]"; 
  }
  void rotateCW(Point c) { // clockwise
    int newX, newY;
    newX = c.x + c.y - this.y;
    newY = c.y + this.x - c.x; 
    this.x = newX; 
    this.y = newY; 
    /********
     Why is this wrong: 
       this.x = c.x + c.y - this.y; 
       this.y = c.y + this.x - c.x; 
     How can you be sure? 
     ********/
  }
  public static void main(String[] args) { // this is testing the rotation 
    Point center = new Point(8, 3); 
    Block block = new Block(8, 2, Color.RED); 
    System.out.println( block ); 
    block.rotateCW(center); 
    System.out.println(block); // should produce (9, 3) 
  }
}

class Point { // represents position of a square (block) 
  int x, y;
  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }
  void move(int dx, int dy) {
    this.x += dx; 
    this.y += dy; 
  }
  
  public String toString() {
    return "(" + this.x + ", " + this.y + ")";  
  }
}

import java.awt.*; 

class Tetromino {
  // please note the centers of rotation CW
  static Tetromino sQuare()    { 
    return new Tetromino(new Point(0, -1), 
                         makeBlocks(new int[] {0, -1, 0, -2, 1, -1, 1, -2}, 
                         Color.GREEN   )); 
  } 
  static Tetromino liNe()      { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 3, -1}, 
                         Color.BLUE    )); 
  } 
  static Tetromino l()         { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 2, -2}, 
                         Color.MAGENTA )); 
  } 
  static Tetromino MirroredL() { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 0, -2}, 
                         Color.CYAN    )); 
  } 
  static Tetromino t()         { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 2, -1, 1, -2}, 
                         Color.ORANGE  )); 
  } 
  static Tetromino s()         { 
    return new Tetromino(new Point(1, -1), 
                         makeBlocks(new int[] {0, -1, 1, -1, 1, -2, 2, -2}, 
                         Color.RED     )); 
  } 
  static Tetromino z()         { 
    return new Tetromino(new Point(1, -2), 
                         makeBlocks(new int[] {0, -2, 1, -2, 1, -1, 2, -1}, 
                         Color.PINK    )); 
  } 
  
  static SetOfBlocks makeBlocks(int[] c, Color color) {
    SetOfBlocks a = new SetOfBlocks(); 
    a.add(new Block( c[0],  c[1], color)); 
    a.add(new Block( c[2],  c[3], color)); 
    a.add(new Block( c[4],  c[5], color)); 
    a.add(new Block( c[6],  c[7], color)); 
    return a;
  }
  Point center;
  SetOfBlocks blocks;
  Tetromino(Point center, SetOfBlocks blocks) {
    this.center = center; 
    this.blocks = blocks; 
  }
  void draw(Graphics g) {
    this.blocks.draw(g); 
  }
  int dx, dy;
  void move(int dx, int dy) {
    this.dx += dx;
    this.dy += dy; 
    this.center.move(dx, dy); 
    this.blocks.move(dx, dy); 
  }
  public String toString() {
    return this.center + " " + this.blocks ;  
  }
  void rotateCW() {
    this.blocks.rotateCW(this.center);  
  }
}

Compile and run these classes. 

We talked about language during the break: 

https://www.ego4u.com/en/chill-out/curiosities/ghoti