From 5f22f20973db3ab5173030b101c4707c2bce758d Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 10 Sep 2019 12:22:46 -0400 Subject: [PATCH 01/52] swap ch15 and ch16 --- ch15/.classpath | 1 - {ch16 => ch15}/Cell.java | 0 ch15/Drawing.java | 57 +++++++++-------------------- {ch16 => ch15}/Grid.java | 0 {ch16 => ch15}/Main.java | 0 {ch16 => ch15}/bakersdozen.cells | 0 {ch15 => ch16}/Actor.java | 0 ch16/Drawing.java | 57 ++++++++++++++++++++--------- {ch15 => ch16}/Mole.java | 0 {ch15 => ch16}/MoleHill.java | 0 {ch15 => ch16}/MovingPolygon.java | 0 {ch15 => ch16}/RegularPolygon.java | 0 {ch15 => ch16}/RotatingPolygon.java | 0 {ch15 => ch16}/Sim1.java | 0 {ch15 => ch16}/Sim2.java | 0 {ch15 => ch16}/Sim3.java | 0 {ch15 => ch16}/WhackAMole.java | 0 17 files changed, 57 insertions(+), 58 deletions(-) rename {ch16 => ch15}/Cell.java (100%) rename {ch16 => ch15}/Grid.java (100%) rename {ch16 => ch15}/Main.java (100%) rename {ch16 => ch15}/bakersdozen.cells (100%) rename {ch15 => ch16}/Actor.java (100%) rename {ch15 => ch16}/Mole.java (100%) rename {ch15 => ch16}/MoleHill.java (100%) rename {ch15 => ch16}/MovingPolygon.java (100%) rename {ch15 => ch16}/RegularPolygon.java (100%) rename {ch15 => ch16}/RotatingPolygon.java (100%) rename {ch15 => ch16}/Sim1.java (100%) rename {ch15 => ch16}/Sim2.java (100%) rename {ch15 => ch16}/Sim3.java (100%) rename {ch15 => ch16}/WhackAMole.java (100%) diff --git a/ch15/.classpath b/ch15/.classpath index 83091d5..3f3893a 100644 --- a/ch15/.classpath +++ b/ch15/.classpath @@ -1,7 +1,6 @@ - diff --git a/ch16/Cell.java b/ch15/Cell.java similarity index 100% rename from ch16/Cell.java rename to ch15/Cell.java diff --git a/ch15/Drawing.java b/ch15/Drawing.java index bb154c4..69d6884 100644 --- a/ch15/Drawing.java +++ b/ch15/Drawing.java @@ -1,64 +1,43 @@ import java.awt.Canvas; -import java.awt.Color; import java.awt.Graphics; -import java.util.ArrayList; -import java.util.List; /** - * Draws a collection of actors. + * Drawing of a grid. */ public class Drawing extends Canvas { - private List actors; + private Grid grid; /** - * Constructs a drawing of given size. + * Constructs a drawing for the grid. * - * @param width the width in pixels - * @param height the height in pixels + * @param grid the initialized grid */ - public Drawing(int width, int height) { - setSize(width, height); - setBackground(Color.WHITE); - actors = new ArrayList(); + public Drawing(Grid grid) { + this.grid = grid; + setSize(grid.width(), grid.height()); } /** - * Adds a new actor to the drawing. + * Draws the grid, cell by cell. * - * @param actor the actor to add - */ - public void add(Actor actor) { - actors.add(actor); - } - - /** - * Gets current actors as an array. - * - * @return array of actor objects - */ - public Object[] getActors() { - return actors.toArray(); - } - - /** - * Calls the act method of each actor. + * @param g graphics context */ - public void nextact() { - for (Actor actor : actors) { - actor.act(); - } + @Override + public void paint(Graphics g) { + grid.draw(g); } /** - * Draws all the actors on the canvas. + * Overriding this method helps the simulation run more smoothly. Normally + * the Canvas is cleared before painting, but there is no need to clear it + * since paint draws the entire grid. * * @param g graphics context */ - public void paint(Graphics g) { - for (Actor actor : actors) { - actor.draw(g); - } + @Override + public void update(Graphics g) { + grid.draw(g); } } diff --git a/ch16/Grid.java b/ch15/Grid.java similarity index 100% rename from ch16/Grid.java rename to ch15/Grid.java diff --git a/ch16/Main.java b/ch15/Main.java similarity index 100% rename from ch16/Main.java rename to ch15/Main.java diff --git a/ch16/bakersdozen.cells b/ch15/bakersdozen.cells similarity index 100% rename from ch16/bakersdozen.cells rename to ch15/bakersdozen.cells diff --git a/ch15/Actor.java b/ch16/Actor.java similarity index 100% rename from ch15/Actor.java rename to ch16/Actor.java diff --git a/ch16/Drawing.java b/ch16/Drawing.java index 69d6884..bb154c4 100644 --- a/ch16/Drawing.java +++ b/ch16/Drawing.java @@ -1,43 +1,64 @@ import java.awt.Canvas; +import java.awt.Color; import java.awt.Graphics; +import java.util.ArrayList; +import java.util.List; /** - * Drawing of a grid. + * Draws a collection of actors. */ public class Drawing extends Canvas { - private Grid grid; + private List actors; /** - * Constructs a drawing for the grid. + * Constructs a drawing of given size. * - * @param grid the initialized grid + * @param width the width in pixels + * @param height the height in pixels */ - public Drawing(Grid grid) { - this.grid = grid; - setSize(grid.width(), grid.height()); + public Drawing(int width, int height) { + setSize(width, height); + setBackground(Color.WHITE); + actors = new ArrayList(); } /** - * Draws the grid, cell by cell. + * Adds a new actor to the drawing. * - * @param g graphics context + * @param actor the actor to add */ - @Override - public void paint(Graphics g) { - grid.draw(g); + public void add(Actor actor) { + actors.add(actor); + } + + /** + * Gets current actors as an array. + * + * @return array of actor objects + */ + public Object[] getActors() { + return actors.toArray(); + } + + /** + * Calls the act method of each actor. + */ + public void nextact() { + for (Actor actor : actors) { + actor.act(); + } } /** - * Overriding this method helps the simulation run more smoothly. Normally - * the Canvas is cleared before painting, but there is no need to clear it - * since paint draws the entire grid. + * Draws all the actors on the canvas. * * @param g graphics context */ - @Override - public void update(Graphics g) { - grid.draw(g); + public void paint(Graphics g) { + for (Actor actor : actors) { + actor.draw(g); + } } } diff --git a/ch15/Mole.java b/ch16/Mole.java similarity index 100% rename from ch15/Mole.java rename to ch16/Mole.java diff --git a/ch15/MoleHill.java b/ch16/MoleHill.java similarity index 100% rename from ch15/MoleHill.java rename to ch16/MoleHill.java diff --git a/ch15/MovingPolygon.java b/ch16/MovingPolygon.java similarity index 100% rename from ch15/MovingPolygon.java rename to ch16/MovingPolygon.java diff --git a/ch15/RegularPolygon.java b/ch16/RegularPolygon.java similarity index 100% rename from ch15/RegularPolygon.java rename to ch16/RegularPolygon.java diff --git a/ch15/RotatingPolygon.java b/ch16/RotatingPolygon.java similarity index 100% rename from ch15/RotatingPolygon.java rename to ch16/RotatingPolygon.java diff --git a/ch15/Sim1.java b/ch16/Sim1.java similarity index 100% rename from ch15/Sim1.java rename to ch16/Sim1.java diff --git a/ch15/Sim2.java b/ch16/Sim2.java similarity index 100% rename from ch15/Sim2.java rename to ch16/Sim2.java diff --git a/ch15/Sim3.java b/ch16/Sim3.java similarity index 100% rename from ch15/Sim3.java rename to ch16/Sim3.java diff --git a/ch15/WhackAMole.java b/ch16/WhackAMole.java similarity index 100% rename from ch15/WhackAMole.java rename to ch16/WhackAMole.java From 4d835c8a032054f26e098f50c7cdb3456f098db7 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 10 Sep 2019 15:57:31 -0400 Subject: [PATCH 02/52] separate Conway from Grid --- ch15/Cell.java | 4 +- ch15/Conway.java | 153 ++++++++++++++++++++++++++++++++++++++++++++++ ch15/Grid.java | 122 +++++++++--------------------------- ch15/Langton.java | 48 +++++++++++++++ ch15/Main.java | 2 +- 5 files changed, 232 insertions(+), 97 deletions(-) create mode 100644 ch15/Conway.java create mode 100644 ch15/Langton.java diff --git a/ch15/Cell.java b/ch15/Cell.java index c3100fd..d20d107 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -55,14 +55,14 @@ public void setColor(Color color) { } /** - * @return true if the cell is on + * @return true if the cell is off */ public boolean isOff() { return this.color == OFF; } /** - * @return true if the cell is off + * @return true if the cell is on */ public boolean isOn() { return this.color == ON; diff --git a/ch15/Conway.java b/ch15/Conway.java new file mode 100644 index 0000000..2d84866 --- /dev/null +++ b/ch15/Conway.java @@ -0,0 +1,153 @@ +import java.awt.Toolkit; +import javax.swing.JFrame; + +/** + * Conway's Game of Life. + */ +public class Conway { + + /** + * Counts the number of live neighbors (without going out of bounds). + * + * @param grid the grid + * @param r row index + * @param c column index + * @return number of live neighbors + */ + public static int countAlive(Grid grid, int r, int c) { + int count = 0; + int cols = grid.getCols(); + int rows = grid.getRows(); + + // previous row + if (r > 0) { + if (c > 0 && grid.isOn(r - 1, c - 1)) { + count++; + } + if (grid.isOn(r - 1, c)) { + count++; + } + if (c < cols - 1 && grid.isOn(r - 1, c + 1)) { + count++; + } + } + + // current row + if (c > 0 && grid.isOn(r, c - 1)) { + count++; + } + if (c < cols - 1 && grid.isOn(r, c + 1)) { + count++; + } + + // next row + if (r < rows - 1) { + if (c > 0 && grid.isOn(r + 1, c - 1)) { + count++; + } + if (grid.isOn(r + 1, c)) { + count++; + } + if (c < cols - 1 && grid.isOn(r + 1, c + 1)) { + count++; + } + } + + return count; + } + + /** + * Apply the rules of Conway's Game of Life. + * + * @param cell the cell to update + * @param count number of live neighbors + */ + public static void updateCell(Cell cell, int count) { + if (cell.isOn()) { + if (count < 2) { + // Any live cell with fewer than two live neighbors dies, + // as if by underpopulation. + cell.turnOff(); + } else if (count > 3) { + // Any live cell with more than three live neighbors dies, + // as if by overpopulation. + cell.turnOff(); + } else { + // Any live cell with two or three live neighbors lives on + // to the next generation. + cell.turnOn(); + } + } else { + if (count == 3) { + // Any dead cell with exactly three live neighbors + // becomes a live cell, as if by reproduction. + cell.turnOn(); + } + } + } + + /** + * Simulates one round of Conway's Game of Life. + * + * @param grid the grid + */ + public static void update(Grid grid) { + int cols = grid.getCols(); + int rows = grid.getRows(); + + // count neighbors before changing anything + int[][] counts = new int[rows][cols]; + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + counts[r][c] = countAlive(grid, r, c); + } + } + + // update each cell based on neighbor counts + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + updateCell(grid.getCell(r, c), counts[r][c]); + } + } + } + + /** + * Sets up the grid, creates the drawing, and plays the game. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + + Grid grid = new Grid(30, 25, 20); + grid.flip(1, 2); + grid.flip(2, 2); + grid.flip(3, 2); + Drawing drawing = new Drawing(grid); + + // set up the window frame + JFrame frame = new JFrame("Conway's Game of Life"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.add(drawing); + frame.pack(); + frame.setVisible(true); + + // main simulation loop + Toolkit toolkit = frame.getToolkit(); + while (true) { + + // update the drawing + update(grid); + drawing.repaint(); + + // delay the simulation + try { + Thread.sleep(500); + toolkit.sync(); + } catch (InterruptedException e) { + // do nothing + } + } + } + +} diff --git a/ch15/Grid.java b/ch15/Grid.java index 2c14d32..18b757b 100644 --- a/ch15/Grid.java +++ b/ch15/Grid.java @@ -1,7 +1,7 @@ import java.awt.Graphics; /** - * 2D array of cells that represent Conway's Game of Life. + * 2D array of cells representing a game board. */ public class Grid { @@ -13,7 +13,7 @@ public class Grid { private Cell[][] array; /** - * Constructs a drawing of given size. + * Constructs a grid of given size. * * @param rows number of rows * @param cols number of columns @@ -49,7 +49,7 @@ public void draw(Graphics g) { } /** - * Toggles the cell color. + * Toggles the cell on/off. * * @param r row index * @param c column index @@ -64,115 +64,49 @@ public void flip(int r, int c) { } /** - * @return total height of the grid + * @param r row index + * @param c column index + * @return true if the cell is on */ - public int height() { - return rows * size; + public boolean isOn(int r, int c) { + return array[r][c].isOn(); } /** - * @return total width of the grid + * @param r row index + * @param c column index + * @return the cell */ - public int width() { - return cols * size; + public Cell getCell(int r, int c) { + return array[r][c]; } /** - * Counts the number of live neighbors (without going out of bounds). - * - * @param r row index - * @param c column index - * @return number of live neighbors + * @return number of rows */ - public int countAlive(int r, int c) { - int count = 0; - - // previous row - if (r > 0) { - if (c > 0 && array[r - 1][c - 1].isOn()) { - count++; - } - if (array[r - 1][c].isOn()) { - count++; - } - if (c < cols - 1 && array[r - 1][c + 1].isOn()) { - count++; - } - } - - // current row - if (c > 0 && array[r][c - 1].isOn()) { - count++; - } - if (c < cols - 1 && array[r][c + 1].isOn()) { - count++; - } - - // next row - if (r < rows - 1) { - if (c > 0 && array[r + 1][c - 1].isOn()) { - count++; - } - if (array[r + 1][c].isOn()) { - count++; - } - if (c < cols - 1 && array[r + 1][c + 1].isOn()) { - count++; - } - } - - return count; + public int getRows() { + return rows; } /** - * Apply the rules of Conway's Game of Life. - * - * @param cell the cell to update - * @param count number of live neighbors + * @return number of columns */ - public void updateCell(Cell cell, int count) { - if (cell.isOn()) { - if (count < 2) { - // Any live cell with fewer than two live neighbors dies, - // as if by underpopulation. - cell.turnOff(); - } else if (count > 3) { - // Any live cell with more than three live neighbors dies, - // as if by overpopulation. - cell.turnOff(); - } else { - // Any live cell with two or three live neighbors lives on - // to the next generation. - cell.turnOn(); - } - } else { - if (count == 3) { - // Any dead cell with exactly three live neighbors - // becomes a live cell, as if by reproduction. - cell.turnOn(); - } - } + public int getCols() { + return cols; } /** - * Simulates one round of Conway's Game of Life. + * @return total height of the grid */ - public void update() { - - // count neighbors before changing anything - int[][] counts = new int[rows][cols]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < cols; c++) { - counts[r][c] = countAlive(r, c); - } - } + public int height() { + return rows * size; + } - // update each cell based on neighbor counts - for (int r = 0; r < rows; r++) { - for (int c = 0; c < cols; c++) { - updateCell(array[r][c], counts[r][c]); - } - } + /** + * @return total width of the grid + */ + public int width() { + return cols * size; } } diff --git a/ch15/Langton.java b/ch15/Langton.java new file mode 100644 index 0000000..84b2380 --- /dev/null +++ b/ch15/Langton.java @@ -0,0 +1,48 @@ +import java.awt.Toolkit; +import javax.swing.JFrame; + +/** + * Langton's Ant. + */ +public class Langton { + + private int xpos; + private int ypos; + private int head; // 0=North, 1=East, 2=South, 3=West + + /** + * Sets up the grid, creates the drawing, and plays the game. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + + Grid grid = new Grid(30, 25, 20); + Drawing drawing = new Drawing(grid); + + // set up the window frame + JFrame frame = new JFrame("Langton's Ant"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.add(drawing); + frame.pack(); + frame.setVisible(true); + + // main simulation loop + Toolkit toolkit = frame.getToolkit(); + while (true) { + + // update the drawing + drawing.repaint(); + + // delay the simulation + try { + Thread.sleep(500); + toolkit.sync(); + } catch (InterruptedException e) { + // do nothing + } + } + } + +} diff --git a/ch15/Main.java b/ch15/Main.java index ddad24f..f90aaf0 100644 --- a/ch15/Main.java +++ b/ch15/Main.java @@ -115,7 +115,7 @@ public static void main(String[] args) { while (true) { // update the drawing - grid.update(); + // grid.update(); drawing.repaint(); // delay the simulation From 5ed14dece44e3e661e65cc6603f3436085d1b8ac Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 11 Sep 2019 17:11:42 -0400 Subject: [PATCH 03/52] added Langton's Ant; refactored --- Checkstyle.xml | 4 +- ch15/Automaton.java | 23 ++++ ch15/Conway.java | 167 ++++++++++++++-------------- ch15/Drawing.java | 43 ------- ch15/{Grid.java => GridCanvas.java} | 109 ++++++++++-------- ch15/Langton.java | 78 +++++++------ ch15/Main.java | 131 ---------------------- ch15/Simulation.java | 47 ++++++++ 8 files changed, 265 insertions(+), 337 deletions(-) create mode 100644 ch15/Automaton.java delete mode 100644 ch15/Drawing.java rename ch15/{Grid.java => GridCanvas.java} (59%) delete mode 100644 ch15/Main.java create mode 100644 ch15/Simulation.java diff --git a/Checkstyle.xml b/Checkstyle.xml index acdee7a..0b55302 100644 --- a/Checkstyle.xml +++ b/Checkstyle.xml @@ -23,7 +23,9 @@ Checkstyle configuration for Think Java, 2nd Edition. - + + + diff --git a/ch15/Automaton.java b/ch15/Automaton.java new file mode 100644 index 0000000..d15077f --- /dev/null +++ b/ch15/Automaton.java @@ -0,0 +1,23 @@ +/** + * A cellular automaton consists of a grid of cells and has the ability to + * update itself over time. + */ +public abstract class Automaton { + + public static final int SIZE = 20; + + protected GridCanvas grid; + + /** + * @return the grid + */ + public GridCanvas getGrid() { + return grid; + } + + /** + * Updates the automaton. + */ + public abstract void update(); + +} diff --git a/ch15/Conway.java b/ch15/Conway.java index 2d84866..ad59890 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -1,68 +1,109 @@ -import java.awt.Toolkit; -import javax.swing.JFrame; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; /** * Conway's Game of Life. */ -public class Conway { +public class Conway extends Automaton { /** - * Counts the number of live neighbors (without going out of bounds). + * Creates a grid with a Blinker and a Glider. + */ + public Conway() { + grid = new GridCanvas(30, 25, SIZE); + grid.flip(1, 2); + grid.flip(2, 2); + grid.flip(3, 2); + grid.flip(6, 1); + grid.flip(7, 2); + grid.flip(7, 3); + grid.flip(8, 1); + grid.flip(8, 2); + } + + /** + * Creates a grid based on a plain text file. + * http://www.conwaylife.com/wiki/Plaintext * - * @param grid the grid - * @param r row index - * @param c column index - * @return number of live neighbors + * @param path the path to the file */ - public static int countAlive(Grid grid, int r, int c) { - int count = 0; - int cols = grid.getCols(); - int rows = grid.getRows(); + public Conway(String path) { + + // open the file at the given path + Scanner scan = null; + try { + File file = new File(path); + scan = new Scanner(file); + } catch (FileNotFoundException e) { + e.printStackTrace(); + System.exit(1); + } - // previous row - if (r > 0) { - if (c > 0 && grid.isOn(r - 1, c - 1)) { - count++; - } - if (grid.isOn(r - 1, c)) { - count++; - } - if (c < cols - 1 && grid.isOn(r - 1, c + 1)) { - count++; + // read file contents into memory + List data = new ArrayList(); + while (scan.hasNextLine()) { + String line = scan.nextLine(); + // ignore blank lines and comments + if (!line.isEmpty() && !line.startsWith("!")) { + data.add(line); } } - // current row - if (c > 0 && grid.isOn(r, c - 1)) { - count++; + // validate the file contents + int rows = data.size(); + if (rows == 0) { + throw new IllegalArgumentException("empty file"); } - if (c < cols - 1 && grid.isOn(r, c + 1)) { - count++; + int cols = data.get(0).length(); + for (String line : data) { + if (line.length() != cols) { + throw new IllegalArgumentException("invalid file"); + } } - // next row - if (r < rows - 1) { - if (c > 0 && grid.isOn(r + 1, c - 1)) { - count++; - } - if (grid.isOn(r + 1, c)) { - count++; - } - if (c < cols - 1 && grid.isOn(r + 1, c + 1)) { - count++; + // create the resulting grid + grid = new GridCanvas(rows, cols, SIZE); + for (int r = 0; r < rows; r++) { + String line = data.get(r); + for (int c = 0; c < cols; c++) { + char x = line.charAt(c); + if (x == 'O') { + grid.flip(r, c); + } } } + } + /** + * Counts the number of live neighbors around a cell. + * + * @param r row index + * @param c column index + * @return number of live neighbors + */ + private int countAlive(int r, int c) { + int count = 0; + count += grid.test(r - 1, c - 1); + count += grid.test(r - 1, c); + count += grid.test(r - 1, c + 1); + count += grid.test(r, c - 1); + count += grid.test(r, c + 1); + count += grid.test(r + 1, c - 1); + count += grid.test(r + 1, c); + count += grid.test(r + 1, c + 1); return count; } /** - * Apply the rules of Conway's Game of Life. + * Apply the update rules of Conway's Game of Life. * * @param cell the cell to update * @param count number of live neighbors */ - public static void updateCell(Cell cell, int count) { + private static void updateCell(Cell cell, int count) { if (cell.isOn()) { if (count < 2) { // Any live cell with fewer than two live neighbors dies, @@ -88,18 +129,16 @@ public static void updateCell(Cell cell, int count) { /** * Simulates one round of Conway's Game of Life. - * - * @param grid the grid */ - public static void update(Grid grid) { - int cols = grid.getCols(); + public void update() { int rows = grid.getRows(); + int cols = grid.getCols(); // count neighbors before changing anything int[][] counts = new int[rows][cols]; for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { - counts[r][c] = countAlive(grid, r, c); + counts[r][c] = countAlive(r, c); } } @@ -109,45 +148,9 @@ public static void update(Grid grid) { updateCell(grid.getCell(r, c), counts[r][c]); } } - } - /** - * Sets up the grid, creates the drawing, and plays the game. - * - * @param args command-line arguments - */ - public static void main(String[] args) { - - Grid grid = new Grid(30, 25, 20); - grid.flip(1, 2); - grid.flip(2, 2); - grid.flip(3, 2); - Drawing drawing = new Drawing(grid); - - // set up the window frame - JFrame frame = new JFrame("Conway's Game of Life"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); - frame.add(drawing); - frame.pack(); - frame.setVisible(true); - - // main simulation loop - Toolkit toolkit = frame.getToolkit(); - while (true) { - - // update the drawing - update(grid); - drawing.repaint(); - - // delay the simulation - try { - Thread.sleep(500); - toolkit.sync(); - } catch (InterruptedException e) { - // do nothing - } - } + // update the display + grid.repaint(); } } diff --git a/ch15/Drawing.java b/ch15/Drawing.java deleted file mode 100644 index 69d6884..0000000 --- a/ch15/Drawing.java +++ /dev/null @@ -1,43 +0,0 @@ -import java.awt.Canvas; -import java.awt.Graphics; - -/** - * Drawing of a grid. - */ -public class Drawing extends Canvas { - - private Grid grid; - - /** - * Constructs a drawing for the grid. - * - * @param grid the initialized grid - */ - public Drawing(Grid grid) { - this.grid = grid; - setSize(grid.width(), grid.height()); - } - - /** - * Draws the grid, cell by cell. - * - * @param g graphics context - */ - @Override - public void paint(Graphics g) { - grid.draw(g); - } - - /** - * Overriding this method helps the simulation run more smoothly. Normally - * the Canvas is cleared before painting, but there is no need to clear it - * since paint draws the entire grid. - * - * @param g graphics context - */ - @Override - public void update(Graphics g) { - grid.draw(g); - } - -} diff --git a/ch15/Grid.java b/ch15/GridCanvas.java similarity index 59% rename from ch15/Grid.java rename to ch15/GridCanvas.java index 18b757b..aa1efa4 100644 --- a/ch15/Grid.java +++ b/ch15/GridCanvas.java @@ -1,13 +1,10 @@ +import java.awt.Canvas; import java.awt.Graphics; /** * 2D array of cells representing a game board. */ -public class Grid { - - private final int rows; - private final int cols; - private final int size; +public class GridCanvas extends Canvas { /** Cells stored in row-major order. */ private Cell[][] array; @@ -19,12 +16,7 @@ public class Grid { * @param cols number of columns * @param size pixels per cell */ - public Grid(int rows, int cols, int size) { - - // store the configuration - this.rows = rows; - this.cols = cols; - this.size = size; + public GridCanvas(int rows, int cols, int size) { // build 2D array of cells this.array = new Cell[rows][cols]; @@ -33,19 +25,32 @@ public Grid(int rows, int cols, int size) { this.array[r][c] = new Cell(c * size, r * size, size); } } + + // set up the Canvas drawing + setSize(cols * size, rows * size); } /** - * Paints the grid on the screen. - * - * @param g graphics context + * @return number of rows */ - public void draw(Graphics g) { - for (Cell[] row : array) { - for (Cell cell : row) { - cell.draw(g); - } - } + public int getRows() { + return array.length; + } + + /** + * @return number of columns + */ + public int getCols() { + return array[0].length; + } + + /** + * @param r row index + * @param c column index + * @return the cell + */ + public Cell getCell(int r, int c) { + return array[r][c]; } /** @@ -64,49 +69,57 @@ public void flip(int r, int c) { } /** + * Returns 1 if the cell at (r, c) exists and is on. Returns 0 if the cell + * doesn't exist or is off. + * * @param r row index * @param c column index - * @return true if the cell is on - */ - public boolean isOn(int r, int c) { - return array[r][c].isOn(); - } - - /** - * @param r row index - * @param c column index - * @return the cell - */ - public Cell getCell(int r, int c) { - return array[r][c]; - } - - /** - * @return number of rows + * @return 1 or 0 */ - public int getRows() { - return rows; + public int test(int r, int c) { + try { + if (array[r][c].isOn()) { + return 1; + } + } catch (IndexOutOfBoundsException e) { + // cell doesn't exist + } + return 0; } /** - * @return number of columns + * Draws the grid, cell by cell. + * + * @param g graphics context */ - public int getCols() { - return cols; + public void draw(Graphics g) { + for (Cell[] row : array) { + for (Cell cell : row) { + cell.draw(g); + } + } } /** - * @return total height of the grid + * Paints the grid on the screen. + * + * @param g graphics context */ - public int height() { - return rows * size; + @Override + public void paint(Graphics g) { + draw(g); } /** - * @return total width of the grid + * Overriding this method helps the simulation run more smoothly. Normally + * the Canvas is cleared before painting, but there is no need to clear it + * since the paint method draws the entire grid. + * + * @param g graphics context */ - public int width() { - return cols * size; + @Override + public void update(Graphics g) { + draw(g); } } diff --git a/ch15/Langton.java b/ch15/Langton.java index 84b2380..1ebdff1 100644 --- a/ch15/Langton.java +++ b/ch15/Langton.java @@ -1,48 +1,62 @@ -import java.awt.Toolkit; -import javax.swing.JFrame; - /** * Langton's Ant. */ -public class Langton { +public class Langton extends Automaton { private int xpos; private int ypos; private int head; // 0=North, 1=East, 2=South, 3=West /** - * Sets up the grid, creates the drawing, and plays the game. - * - * @param args command-line arguments + * Creates an 11x11 grid with the ant in the center. */ - public static void main(String[] args) { - - Grid grid = new Grid(30, 25, 20); - Drawing drawing = new Drawing(grid); - - // set up the window frame - JFrame frame = new JFrame("Langton's Ant"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); - frame.add(drawing); - frame.pack(); - frame.setVisible(true); - - // main simulation loop - Toolkit toolkit = frame.getToolkit(); - while (true) { - - // update the drawing - drawing.repaint(); + public Langton() { + grid = new GridCanvas(11, 11, SIZE); + xpos = 5; + ypos = 5; + head = 0; + } - // delay the simulation - try { - Thread.sleep(500); - toolkit.sync(); - } catch (InterruptedException e) { - // do nothing + /** + * Simulates one round of Langton's Ant. + */ + public void update() { + + Cell cell = grid.getCell(xpos, ypos); + if (cell.isOn()) { + // at a black square; flip color and turn left + cell.turnOff(); + head -= 1; + if (head < 0) { + head = 3; + } + } else { + // at a white square; flip color and turn right + cell.turnOn(); + head += 1; + if (head > 3) { + head = 0; } } + + // move forward one unit + switch (head) { + case 0: + ypos -= 1; + break; + case 1: + xpos += 1; + break; + case 2: + ypos += 1; + break; + case 3: + xpos -= 1; + break; + } + + // update the display + grid.repaint(); } } diff --git a/ch15/Main.java b/ch15/Main.java deleted file mode 100644 index f90aaf0..0000000 --- a/ch15/Main.java +++ /dev/null @@ -1,131 +0,0 @@ -import java.awt.Toolkit; -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; -import javax.swing.JFrame; - -/** - * Example simulation of Conway's Game of Life. - */ -public class Main { - - public static final int SIZE = 20; - - /** - * Returns an example of a Blinker and a Glider. - * - * @return hard-coded grid - */ - public static Grid example() { - Grid grid = new Grid(30, 25, SIZE); - grid.flip(1, 2); - grid.flip(2, 2); - grid.flip(3, 2); - grid.flip(6, 1); - grid.flip(7, 2); - grid.flip(7, 3); - grid.flip(8, 1); - grid.flip(8, 2); - return grid; - } - - /** - * Creates a grid based on a plain text file. - * http://www.conwaylife.com/wiki/Plaintext - * - * @param path the path to the file - * @return grid based on file contents - */ - public static Grid readFile(String path) { - - // open the file at the given path - Scanner scan = null; - try { - File file = new File(path); - scan = new Scanner(file); - } catch (FileNotFoundException e) { - e.printStackTrace(); - System.exit(1); - } - - // read file contents into memory - List data = new ArrayList(); - while (scan.hasNextLine()) { - String line = scan.nextLine(); - // ignore blank lines and comments - if (!line.isEmpty() && !line.startsWith("!")) { - data.add(line); - } - } - - // validate the file contents - int rows = data.size(); - if (rows == 0) { - throw new IllegalArgumentException("empty file"); - } - int cols = data.get(0).length(); - for (String line : data) { - if (line.length() != cols) { - throw new IllegalArgumentException("invalid file"); - } - } - - // create the resulting grid - Grid grid = new Grid(rows, cols, SIZE); - for (int r = 0; r < rows; r++) { - String line = data.get(r); - for (int c = 0; c < cols; c++) { - char x = line.charAt(c); - if (x == 'O') { - grid.flip(r, c); - } - } - } - return grid; - } - - /** - * Sets up the grid, creates the drawing, and plays the game. - * - * @param args command-line arguments - */ - public static void main(String[] args) { - - // create the grid drawing - Grid grid; - if (args.length != 1) { - grid = example(); - } else { - grid = readFile(args[0]); - } - Drawing drawing = new Drawing(grid); - - // set up the window frame - JFrame frame = new JFrame("Drawing"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); - frame.add(drawing); - frame.pack(); - frame.setVisible(true); - - // main simulation loop - Toolkit toolkit = frame.getToolkit(); - while (true) { - - // update the drawing - // grid.update(); - drawing.repaint(); - - // delay the simulation - try { - Thread.sleep(500); - toolkit.sync(); - } catch (InterruptedException e) { - // do nothing - } - } - } - -} diff --git a/ch15/Simulation.java b/ch15/Simulation.java new file mode 100644 index 0000000..136d5dd --- /dev/null +++ b/ch15/Simulation.java @@ -0,0 +1,47 @@ +import java.awt.Toolkit; +import javax.swing.JFrame; + +/** + * Application that simulates a zero-player game. + */ +public class Simulation { + + /** + * Sets up the grid, creates the frame, and plays the game. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + + // String title = "Langton's Ant"; + // Automaton auto = new Langton(); + + String title = "Conway's Game of Life"; + Automaton auto = new Conway("bakersdozen.cells"); + + // set up the window frame + JFrame frame = new JFrame(title); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.add(auto.getGrid()); + frame.pack(); + frame.setVisible(true); + + // main simulation loop + Toolkit toolkit = frame.getToolkit(); + while (true) { + + // update the drawing + toolkit.sync(); + auto.update(); + + // delay the simulation + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // do nothing + } + } + } + +} From 70b0af8f5cd367c038bc11d25e81b1d95db73399 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 11 Sep 2019 21:46:43 -0400 Subject: [PATCH 04/52] cleaned up the code --- ch15/Automaton.java | 4 ++-- ch15/Cell.java | 20 +++----------------- ch15/Conway.java | 4 ++-- ch15/GridCanvas.java | 6 +++--- ch15/Simulation.java | 14 +++++++------- 5 files changed, 17 insertions(+), 31 deletions(-) diff --git a/ch15/Automaton.java b/ch15/Automaton.java index d15077f..3451192 100644 --- a/ch15/Automaton.java +++ b/ch15/Automaton.java @@ -1,6 +1,6 @@ /** - * A cellular automaton consists of a grid of cells and has the ability to - * update itself over time. + * A cellular automaton consists of a grid of cells and follows a set of rules + * that update the grid over time. */ public abstract class Automaton { diff --git a/ch15/Cell.java b/ch15/Cell.java index d20d107..1f4bee9 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -29,7 +29,7 @@ public Cell(int x, int y, int size) { } /** - * Paints the cell on the screen. + * Draws the cell on the screen. * * @param g graphics context */ @@ -41,28 +41,14 @@ public void draw(Graphics g) { } /** - * @return the cell's color - */ - public Color getColor() { - return this.color; - } - - /** - * @param color the new color - */ - public void setColor(Color color) { - this.color = color; - } - - /** - * @return true if the cell is off + * @return true if the cell is OFF */ public boolean isOff() { return this.color == OFF; } /** - * @return true if the cell is on + * @return true if the cell is ON */ public boolean isOn() { return this.color == ON; diff --git a/ch15/Conway.java b/ch15/Conway.java index ad59890..ef5e69f 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -131,8 +131,8 @@ private static void updateCell(Cell cell, int count) { * Simulates one round of Conway's Game of Life. */ public void update() { - int rows = grid.getRows(); - int cols = grid.getCols(); + int rows = grid.numRows(); + int cols = grid.numCols(); // count neighbors before changing anything int[][] counts = new int[rows][cols]; diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index aa1efa4..db75117 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -26,21 +26,21 @@ public GridCanvas(int rows, int cols, int size) { } } - // set up the Canvas drawing + // set up the canvas drawing setSize(cols * size, rows * size); } /** * @return number of rows */ - public int getRows() { + public int numRows() { return array.length; } /** * @return number of columns */ - public int getCols() { + public int numCols() { return array[0].length; } diff --git a/ch15/Simulation.java b/ch15/Simulation.java index 136d5dd..7e2849e 100644 --- a/ch15/Simulation.java +++ b/ch15/Simulation.java @@ -2,7 +2,7 @@ import javax.swing.JFrame; /** - * Application that simulates a zero-player game. + * Application that simulates a cellular automaton. */ public class Simulation { @@ -13,17 +13,17 @@ public class Simulation { */ public static void main(String[] args) { - // String title = "Langton's Ant"; - // Automaton auto = new Langton(); - String title = "Conway's Game of Life"; - Automaton auto = new Conway("bakersdozen.cells"); + Automaton game = new Conway("bakersdozen.cells"); + + // String title = "Langton's Ant"; + // Automaton game = new Langton(); // set up the window frame JFrame frame = new JFrame(title); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); - frame.add(auto.getGrid()); + frame.add(game.getGrid()); frame.pack(); frame.setVisible(true); @@ -33,7 +33,7 @@ public static void main(String[] args) { // update the drawing toolkit.sync(); - auto.update(); + game.update(); // delay the simulation try { From b395aa448371fc0d6e3b337f74ebe49c58167749 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Thu, 12 Sep 2019 16:00:10 -0400 Subject: [PATCH 05/52] added more specialization --- ch15/GridCanvas.java | 2 -- ch16/BlinkingPolygon.java | 31 +++++++++++++++++++++++++++++++ ch16/Drawing.java | 6 ++++-- ch16/Mole.java | 19 +++++++++++++++++-- ch16/MovingPolygon.java | 2 +- ch16/RegularPolygon.java | 11 ++--------- ch16/Sim1.java | 2 +- ch16/Sim2.java | 15 +++++++++------ ch16/Sim3.java | 13 ++++++++----- ch16/WhackAMole.java | 5 ++--- 10 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 ch16/BlinkingPolygon.java diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index db75117..005160c 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -105,7 +105,6 @@ public void draw(Graphics g) { * * @param g graphics context */ - @Override public void paint(Graphics g) { draw(g); } @@ -117,7 +116,6 @@ public void paint(Graphics g) { * * @param g graphics context */ - @Override public void update(Graphics g) { draw(g); } diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java new file mode 100644 index 0000000..308cd4f --- /dev/null +++ b/ch16/BlinkingPolygon.java @@ -0,0 +1,31 @@ +import java.awt.Color; + +/** + * A polygon that changes colors on/off. + */ +public class BlinkingPolygon extends RegularPolygon { + + private Color onColor; + + /** + * Constructs a blinking polygon. + * + * @param nsides the number of sides + * @param length length of each side + * @param color initial fill color + */ + public BlinkingPolygon(int nsides, int length, Color color) { + super(nsides, length, color); + onColor = color; + } + + @Override + public void act() { + if (color != onColor) { + color = onColor; + } else { + color = Color.WHITE; + } + } + +} diff --git a/ch16/Drawing.java b/ch16/Drawing.java index bb154c4..c9770ad 100644 --- a/ch16/Drawing.java +++ b/ch16/Drawing.java @@ -42,12 +42,13 @@ public Object[] getActors() { } /** - * Calls the act method of each actor. + * Calls the act method of each actor and updates the drawing. */ - public void nextact() { + public void next() { for (Actor actor : actors) { actor.act(); } + repaint(); } /** @@ -55,6 +56,7 @@ public void nextact() { * * @param g graphics context */ + @Override public void paint(Graphics g) { for (Actor actor : actors) { actor.draw(g); diff --git a/ch16/Mole.java b/ch16/Mole.java index 5f5f71b..0fd8724 100644 --- a/ch16/Mole.java +++ b/ch16/Mole.java @@ -3,10 +3,12 @@ /** * A polygon that represents a small burrowing mammal. */ -public class Mole extends RegularPolygon { +public class Mole extends BlinkingPolygon { public static final Color BROWN = new Color(153, 102, 0); + private boolean alive; + /** * Creates a mole at the given location. * @@ -16,13 +18,26 @@ public class Mole extends RegularPolygon { public Mole(int x, int y) { super(10, 20, BROWN); translate(x, y); + alive = true; + } + + @Override + public void act() { + // blink on/off at random times + if (alive && Math.random() < 0.5) { + super.act(); + } } /** * Updates the state of the mole when clicked. */ public void whack() { - setColor(Color.LIGHT_GRAY); + // ignore whack when invisible + if (color == BROWN) { + color = Color.LIGHT_GRAY; + alive = false; + } } } diff --git a/ch16/MovingPolygon.java b/ch16/MovingPolygon.java index 28d94fa..76bdc34 100644 --- a/ch16/MovingPolygon.java +++ b/ch16/MovingPolygon.java @@ -1,5 +1,5 @@ /** - * A polygon that moves around the screen. + * A polygon that bounces off the walls. */ public class MovingPolygon extends RegularPolygon { diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index 1116336..0a830cf 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -12,7 +12,7 @@ public class RegularPolygon extends Polygon implements Actor { "Triangle", "Square", "Pentagon", "Hexagon", "Heptagon", "Octagon", "Nonagon", "Decagon"}; - private Color color; + protected Color color; /** * Constructs a regular polygon, given the number of sides. @@ -40,7 +40,7 @@ public RegularPolygon(int nsides, int length) { * * @param nsides the number of sides * @param length length of each side - * @param color the fill color + * @param color initial fill color */ public RegularPolygon(int nsides, int length, Color color) { @@ -91,13 +91,6 @@ public void draw(Graphics g) { g.fillPolygon(this); } - /** - * @param color the new color - */ - public void setColor(Color color) { - this.color = color; - } - @Override public String toString() { StringBuilder str = new StringBuilder(); diff --git a/ch16/Sim1.java b/ch16/Sim1.java index 877ca77..ef8db8d 100644 --- a/ch16/Sim1.java +++ b/ch16/Sim1.java @@ -30,7 +30,7 @@ public static void main(String[] args) { drawing.add(p5); // set up the window frame - JFrame frame = new JFrame("Drawing"); + JFrame frame = new JFrame("Drawing (no animation)"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.add(drawing); diff --git a/ch16/Sim2.java b/ch16/Sim2.java index 53365cc..63e5ea3 100644 --- a/ch16/Sim2.java +++ b/ch16/Sim2.java @@ -1,8 +1,9 @@ +import java.awt.Color; import java.awt.Toolkit; import javax.swing.JFrame; /** - * Example simulation of moving objects. + * Example simulation of animated objects. */ public class Sim2 { @@ -14,20 +15,23 @@ public class Sim2 { public static void main(String[] args) { // create some regular polygons + BlinkingPolygon bp = new BlinkingPolygon(3, 10, Color.BLUE); MovingPolygon mp = new MovingPolygon(8, 30); RotatingPolygon rp = new RotatingPolygon(5, 50); // move them out of the corner + bp.translate(50, 50); mp.translate(100, 100); rp.translate(200, 200); // create drawing, add polygons Drawing drawing = new Drawing(800, 600); + drawing.add(bp); drawing.add(mp); drawing.add(rp); // set up the window frame - JFrame frame = new JFrame("Drawing"); + JFrame frame = new JFrame("Drawing with Thread.sleep"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.add(drawing); @@ -39,13 +43,12 @@ public static void main(String[] args) { while (true) { // update the drawing - drawing.nextact(); - drawing.repaint(); + toolkit.sync(); + drawing.next(); // delay the simulation try { - Thread.sleep(1000 / 60); - toolkit.sync(); + Thread.sleep(50); } catch (InterruptedException e) { // do nothing } diff --git a/ch16/Sim3.java b/ch16/Sim3.java index 4ac9bc6..facc19b 100644 --- a/ch16/Sim3.java +++ b/ch16/Sim3.java @@ -1,3 +1,4 @@ +import java.awt.Color; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -5,7 +6,7 @@ import javax.swing.Timer; /** - * Smoother version using a timer. + * Smoother version of Sim2 using a timer. */ public class Sim3 implements ActionListener { @@ -17,20 +18,23 @@ public class Sim3 implements ActionListener { */ public Sim3() { // create some regular polygons + BlinkingPolygon bp = new BlinkingPolygon(3, 10, Color.BLUE); MovingPolygon mp = new MovingPolygon(8, 30); RotatingPolygon rp = new RotatingPolygon(5, 50); // move them out of the corner + bp.translate(50, 50); mp.translate(100, 100); rp.translate(200, 200); // create drawing, add polygons drawing = new Drawing(800, 600); + drawing.add(bp); drawing.add(mp); drawing.add(rp); // set up the window frame - JFrame frame = new JFrame("Drawing"); + JFrame frame = new JFrame("Drawing with ActionListener"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.add(drawing); @@ -46,15 +50,14 @@ public Sim3() { */ public static void main(String[] args) { Sim3 sim = new Sim3(); - Timer timer = new Timer(1000 / 60, sim); + Timer timer = new Timer(50, sim); timer.start(); } @Override public void actionPerformed(ActionEvent e) { - drawing.nextact(); - drawing.repaint(); toolkit.sync(); + drawing.next(); } } diff --git a/ch16/WhackAMole.java b/ch16/WhackAMole.java index 8760778..44e1c94 100644 --- a/ch16/WhackAMole.java +++ b/ch16/WhackAMole.java @@ -41,15 +41,14 @@ public WhackAMole() { */ public static void main(String[] args) { WhackAMole sim = new WhackAMole(); - Timer timer = new Timer(1000 / 60, sim); + Timer timer = new Timer(500, sim); timer.start(); } @Override public void actionPerformed(ActionEvent e) { - drawing.nextact(); - drawing.repaint(); toolkit.sync(); + drawing.next(); } } From 445db0e0e29ecd5606245b3f5e441bf6575e42ea Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Thu, 12 Sep 2019 19:03:49 -0400 Subject: [PATCH 06/52] rename act to step --- ch16/Actor.java | 10 +++++----- ch16/BlinkingPolygon.java | 2 +- ch16/Drawing.java | 6 +++--- ch16/Mole.java | 4 ++-- ch16/MovingPolygon.java | 2 +- ch16/RegularPolygon.java | 2 +- ch16/RotatingPolygon.java | 2 +- ch16/Sim2.java | 2 +- ch16/Sim3.java | 2 +- ch16/WhackAMole.java | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ch16/Actor.java b/ch16/Actor.java index 0e9ebb2..5f99153 100644 --- a/ch16/Actor.java +++ b/ch16/Actor.java @@ -5,11 +5,6 @@ */ public interface Actor { - /** - * Updates the state of the simulation element. - */ - void act(); - /** * Draws the simulation element in the context. * @@ -17,4 +12,9 @@ public interface Actor { */ void draw(Graphics g); + /** + * Updates the state of the simulation element. + */ + void step(); + } diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java index 308cd4f..f9c1ff8 100644 --- a/ch16/BlinkingPolygon.java +++ b/ch16/BlinkingPolygon.java @@ -20,7 +20,7 @@ public BlinkingPolygon(int nsides, int length, Color color) { } @Override - public void act() { + public void step() { if (color != onColor) { color = onColor; } else { diff --git a/ch16/Drawing.java b/ch16/Drawing.java index c9770ad..16c5c2d 100644 --- a/ch16/Drawing.java +++ b/ch16/Drawing.java @@ -42,11 +42,11 @@ public Object[] getActors() { } /** - * Calls the act method of each actor and updates the drawing. + * Calls the step method of each actor and updates the drawing. */ - public void next() { + public void step() { for (Actor actor : actors) { - actor.act(); + actor.step(); } repaint(); } diff --git a/ch16/Mole.java b/ch16/Mole.java index 0fd8724..3f41b8f 100644 --- a/ch16/Mole.java +++ b/ch16/Mole.java @@ -22,10 +22,10 @@ public Mole(int x, int y) { } @Override - public void act() { + public void step() { // blink on/off at random times if (alive && Math.random() < 0.5) { - super.act(); + super.step(); } } diff --git a/ch16/MovingPolygon.java b/ch16/MovingPolygon.java index 76bdc34..0f02f74 100644 --- a/ch16/MovingPolygon.java +++ b/ch16/MovingPolygon.java @@ -33,7 +33,7 @@ public void setDy(int dy) { } @Override - public void act() { + public void step() { // edge detection for (int i = 0; i < npoints; i++) { diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index 0a830cf..602f4ea 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -80,7 +80,7 @@ public RegularPolygon(int nsides, int length, Color color) { } @Override - public void act() { + public void step() { // nothing to do } diff --git a/ch16/RotatingPolygon.java b/ch16/RotatingPolygon.java index f7e5046..3243f73 100644 --- a/ch16/RotatingPolygon.java +++ b/ch16/RotatingPolygon.java @@ -50,7 +50,7 @@ public void center() { } @Override - public void act() { + public void step() { // update the rotation angle angle = (angle + 1) % 360; final double RAD = Math.toRadians(angle); diff --git a/ch16/Sim2.java b/ch16/Sim2.java index 63e5ea3..a70368b 100644 --- a/ch16/Sim2.java +++ b/ch16/Sim2.java @@ -44,7 +44,7 @@ public static void main(String[] args) { // update the drawing toolkit.sync(); - drawing.next(); + drawing.step(); // delay the simulation try { diff --git a/ch16/Sim3.java b/ch16/Sim3.java index facc19b..a52658a 100644 --- a/ch16/Sim3.java +++ b/ch16/Sim3.java @@ -57,7 +57,7 @@ public static void main(String[] args) { @Override public void actionPerformed(ActionEvent e) { toolkit.sync(); - drawing.next(); + drawing.step(); } } diff --git a/ch16/WhackAMole.java b/ch16/WhackAMole.java index 44e1c94..dea25c3 100644 --- a/ch16/WhackAMole.java +++ b/ch16/WhackAMole.java @@ -48,7 +48,7 @@ public static void main(String[] args) { @Override public void actionPerformed(ActionEvent e) { toolkit.sync(); - drawing.next(); + drawing.step(); } } From bb437e361c944097ad231981823bcddb7dbc1aba Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Thu, 12 Sep 2019 20:21:00 -0400 Subject: [PATCH 07/52] reviewed ch15 code --- ch15/Cell.java | 4 ++-- ch15/Conway.java | 32 ++++++++++++++--------------- ch15/GridCanvas.java | 2 +- ch15/{Simulation.java => Main.java} | 4 ++-- ch15/bakersdozen.cells | 31 ---------------------------- ch15/pulsar.cells | 17 +++++++++++++++ 6 files changed, 38 insertions(+), 52 deletions(-) rename ch15/{Simulation.java => Main.java} (92%) delete mode 100644 ch15/bakersdozen.cells create mode 100644 ch15/pulsar.cells diff --git a/ch15/Cell.java b/ch15/Cell.java index 1f4bee9..d374a90 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -41,14 +41,14 @@ public void draw(Graphics g) { } /** - * @return true if the cell is OFF + * @return true if the color is OFF */ public boolean isOff() { return this.color == OFF; } /** - * @return true if the cell is ON + * @return true if the color is ON */ public boolean isOn() { return this.color == ON; diff --git a/ch15/Conway.java b/ch15/Conway.java index ef5e69f..ad8325c 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -1,7 +1,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; -import java.util.List; import java.util.Scanner; /** @@ -29,8 +28,9 @@ public Conway() { * http://www.conwaylife.com/wiki/Plaintext * * @param path the path to the file + * @param margin how many cells to add */ - public Conway(String path) { + public Conway(String path, int margin) { // open the file at the given path Scanner scan = null; @@ -43,35 +43,35 @@ public Conway(String path) { } // read file contents into memory - List data = new ArrayList(); + ArrayList data = new ArrayList(); while (scan.hasNextLine()) { String line = scan.nextLine(); - // ignore blank lines and comments - if (!line.isEmpty() && !line.startsWith("!")) { + // only add non-comment lines + if (!line.startsWith("!")) { data.add(line); } } - // validate the file contents + // determine number of rows and columns in the pattern int rows = data.size(); - if (rows == 0) { - throw new IllegalArgumentException("empty file"); - } - int cols = data.get(0).length(); + int cols = 0; for (String line : data) { - if (line.length() != cols) { - throw new IllegalArgumentException("invalid file"); + if (cols < line.length()) { + cols = line.length(); } } + if (rows == 0 || cols == 0) { + throw new IllegalArgumentException("no cells found"); + } - // create the resulting grid - grid = new GridCanvas(rows, cols, SIZE); + // create the resulting grid with margin of extra cells + grid = new GridCanvas(rows + 2 * margin, cols + 2 * margin, SIZE); for (int r = 0; r < rows; r++) { String line = data.get(r); - for (int c = 0; c < cols; c++) { + for (int c = 0; c < line.length(); c++) { char x = line.charAt(c); if (x == 'O') { - grid.flip(r, c); + grid.flip(r + margin, c + margin); } } } diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index 005160c..03f1135 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -2,7 +2,7 @@ import java.awt.Graphics; /** - * 2D array of cells representing a game board. + * 2D array of cells representing a rectangular grid. */ public class GridCanvas extends Canvas { diff --git a/ch15/Simulation.java b/ch15/Main.java similarity index 92% rename from ch15/Simulation.java rename to ch15/Main.java index 7e2849e..694f219 100644 --- a/ch15/Simulation.java +++ b/ch15/Main.java @@ -4,7 +4,7 @@ /** * Application that simulates a cellular automaton. */ -public class Simulation { +public class Main { /** * Sets up the grid, creates the frame, and plays the game. @@ -14,7 +14,7 @@ public class Simulation { public static void main(String[] args) { String title = "Conway's Game of Life"; - Automaton game = new Conway("bakersdozen.cells"); + Automaton game = new Conway("pulsar.cells", 2); // String title = "Langton's Ant"; // Automaton game = new Langton(); diff --git a/ch15/bakersdozen.cells b/ch15/bakersdozen.cells deleted file mode 100644 index 7785a85..0000000 --- a/ch15/bakersdozen.cells +++ /dev/null @@ -1,31 +0,0 @@ -! bakersdozenreactions.cells -! http://conwaylife.com/wiki/Baker%27s_dozen -! http://conwaylife.com/patterns/bakersdozenreactions.cells -.........................O......... -........................OO.OO...... -........................OOOOO...... -........O.OO.OO.O.......OO......... -........OO.O.O.OO........O......... -................................... -........OOO...OOO......O.O......... -........O..O.O..O.......O.......... -..........OO.OO.............O...... -.....O.............O.......O.O..OO. -OO..O.O...........O.O..OO..O..O.OO. -OO.O..O..OO...OO..O..O.OO...OO..... -....OO...OO...OO...OO.............. -................................... -...............................O... -...............................O... -....OO...OO.....OO...OO.......OO.O. -OO.O..O..OO.....OO..O..O.OO......OO -OO..O.O.............O.O..OO...O.... -.....O...............O........OO... -.............................OO.... -........OOO.......O..........OOO... -........OOO.......O................ -......OO..OOO...O.OO............... -......OO.......OO...O.............. -......OOO..........O.O............. -........O.........O..O............. -........O..........OO.............. \ No newline at end of file diff --git a/ch15/pulsar.cells b/ch15/pulsar.cells new file mode 100644 index 0000000..19eda57 --- /dev/null +++ b/ch15/pulsar.cells @@ -0,0 +1,17 @@ +!Name: Pulsar +!Author: John Conway +!Despite its size, this is the fourth most common oscillator (and by far the most common of period greater than 2). +!www.conwaylife.com/wiki/index.php?title=Pulsar +..OOO...OOO + +O....O.O....O +O....O.O....O +O....O.O....O +..OOO...OOO + +..OOO...OOO +O....O.O....O +O....O.O....O +O....O.O....O + +..OOO...OOO From d11dd8ecde5e82acb4d03f5e6a59f28ec11ae094 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Thu, 12 Sep 2019 22:39:41 -0400 Subject: [PATCH 08/52] removed explicit this --- ch15/Cell.java | 14 +++++++------- ch15/GridCanvas.java | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ch15/Cell.java b/ch15/Cell.java index d374a90..b367966 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -34,38 +34,38 @@ public Cell(int x, int y, int size) { * @param g graphics context */ public void draw(Graphics g) { - g.setColor(this.color); - g.fillRect(this.x + 1, this.y + 1, this.size - 1, this.size - 1); + g.setColor(color); + g.fillRect(x + 1, y + 1, size - 1, size - 1); g.setColor(Color.LIGHT_GRAY); - g.drawRect(this.x, this.y, this.size, this.size); + g.drawRect(x, y, size, size); } /** * @return true if the color is OFF */ public boolean isOff() { - return this.color == OFF; + return color == OFF; } /** * @return true if the color is ON */ public boolean isOn() { - return this.color == ON; + return color == ON; } /** * Sets the cell's color to OFF. */ public void turnOff() { - this.color = OFF; + color = OFF; } /** * Sets the cell's color to ON. */ public void turnOn() { - this.color = ON; + color = ON; } } diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index 03f1135..ece68af 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -19,10 +19,10 @@ public class GridCanvas extends Canvas { public GridCanvas(int rows, int cols, int size) { // build 2D array of cells - this.array = new Cell[rows][cols]; + array = new Cell[rows][cols]; for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { - this.array[r][c] = new Cell(c * size, r * size, size); + array[r][c] = new Cell(c * size, r * size, size); } } From b10cd8ee34c5ab38ecbf6cee1de77805fc7ac96e Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Thu, 12 Sep 2019 22:41:01 -0400 Subject: [PATCH 09/52] radius instead of side length --- ch16/BlinkingPolygon.java | 24 ++++++++++++++++-------- ch16/Drawing.java | 20 ++++++++++---------- ch16/Mole.java | 2 +- ch16/MovingPolygon.java | 10 +++++----- ch16/RegularPolygon.java | 27 +++++++++++---------------- ch16/RotatingPolygon.java | 14 +++++++------- ch16/Sim1.java | 6 +++--- ch16/Sim2.java | 6 +++--- ch16/Sim3.java | 6 +++--- ch16/WhackAMole.java | 9 ++++++--- 10 files changed, 65 insertions(+), 59 deletions(-) diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java index f9c1ff8..06c9b7d 100644 --- a/ch16/BlinkingPolygon.java +++ b/ch16/BlinkingPolygon.java @@ -1,30 +1,38 @@ import java.awt.Color; /** - * A polygon that changes colors on/off. + * A polygon that periodically changes colors on/off. */ public class BlinkingPolygon extends RegularPolygon { private Color onColor; + private int count; /** * Constructs a blinking polygon. * * @param nsides the number of sides - * @param length length of each side + * @param radius from center to vertex * @param color initial fill color */ - public BlinkingPolygon(int nsides, int length, Color color) { - super(nsides, length, color); + public BlinkingPolygon(int nsides, int radius, Color color) { + super(nsides, radius, color); onColor = color; + count = 0; } @Override public void step() { - if (color != onColor) { - color = onColor; - } else { - color = Color.WHITE; + // count to ten first + count++; + if (count >= 10) { + count = 0; + // toggle the color + if (color != onColor) { + color = onColor; + } else { + color = Color.WHITE; + } } } diff --git a/ch16/Drawing.java b/ch16/Drawing.java index 16c5c2d..445d11e 100644 --- a/ch16/Drawing.java +++ b/ch16/Drawing.java @@ -41,16 +41,6 @@ public Object[] getActors() { return actors.toArray(); } - /** - * Calls the step method of each actor and updates the drawing. - */ - public void step() { - for (Actor actor : actors) { - actor.step(); - } - repaint(); - } - /** * Draws all the actors on the canvas. * @@ -63,4 +53,14 @@ public void paint(Graphics g) { } } + /** + * Calls the step method of each actor and updates the drawing. + */ + public void step() { + for (Actor actor : actors) { + actor.step(); + } + repaint(); + } + } diff --git a/ch16/Mole.java b/ch16/Mole.java index 3f41b8f..aaa397e 100644 --- a/ch16/Mole.java +++ b/ch16/Mole.java @@ -16,7 +16,7 @@ public class Mole extends BlinkingPolygon { * @param y the Y coordinate */ public Mole(int x, int y) { - super(10, 20, BROWN); + super(10, 30, BROWN); translate(x, y); alive = true; } diff --git a/ch16/MovingPolygon.java b/ch16/MovingPolygon.java index 0f02f74..7c6c2f5 100644 --- a/ch16/MovingPolygon.java +++ b/ch16/MovingPolygon.java @@ -10,12 +10,12 @@ public class MovingPolygon extends RegularPolygon { * Constructs a moving polygon. * * @param nsides the number of sides - * @param length length of each side + * @param radius from center to vertex */ - public MovingPolygon(int nsides, int length) { - super(nsides, length); - this.dx = 10; - this.dy = 5; + public MovingPolygon(int nsides, int radius) { + super(nsides, radius); + dx = 10; + dy = 5; } /** diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index 602f4ea..4e42533 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -24,32 +24,31 @@ public RegularPolygon(int nsides) { } /** - * Constructs a regular polygon, given the number of sides and length of - * each side. + * Constructs a regular polygon, given the number of sides and the radius. * * @param nsides the number of sides - * @param length length of each side + * @param radius from center to vertex */ - public RegularPolygon(int nsides, int length) { - this(nsides, length, Color.BLACK); + public RegularPolygon(int nsides, int radius) { + this(nsides, radius, Color.BLACK); } /** - * Constructs a regular polygon, given the number of sides, the length of - * each side, and fill color. + * Constructs a regular polygon, given the number of sides, the radius, and + * fill color. * * @param nsides the number of sides - * @param length length of each side + * @param radius from center to vertex * @param color initial fill color */ - public RegularPolygon(int nsides, int length, Color color) { + public RegularPolygon(int nsides, int radius, Color color) { // validate and store arguments if (nsides < 3) { throw new IllegalArgumentException("invalid nsides"); } - if (length < 1) { - throw new IllegalArgumentException("invalid length"); + if (radius < 1) { + throw new IllegalArgumentException("invalid radius"); } if (color == null) { throw new NullPointerException("invalid color"); @@ -61,9 +60,6 @@ public RegularPolygon(int nsides, int length, Color color) { this.ypoints = new int[nsides]; this.color = color; - // radius of the polygon (distance from center to vertex) - double radius = 0.5 * length / Math.sin(Math.PI / nsides); - // the angle (in radians) at each vertex double angle = 2.0 * Math.PI / nsides; @@ -81,12 +77,11 @@ public RegularPolygon(int nsides, int length, Color color) { @Override public void step() { - // nothing to do + // do nothing } @Override public void draw(Graphics g) { - // System.out.println(this); g.setColor(color); g.fillPolygon(this); } diff --git a/ch16/RotatingPolygon.java b/ch16/RotatingPolygon.java index 3243f73..f1a84ed 100644 --- a/ch16/RotatingPolygon.java +++ b/ch16/RotatingPolygon.java @@ -14,13 +14,13 @@ public class RotatingPolygon extends RegularPolygon { private int[] y0; // original ypoints /** - * Constructs a moving polygon. + * Constructs a rotating polygon. * * @param nsides the number of sides - * @param length length of each side + * @param radius from center to vertex */ - public RotatingPolygon(int nsides, int length) { - super(nsides, length); + public RotatingPolygon(int nsides, int radius) { + super(nsides, radius); center(); } @@ -38,11 +38,11 @@ public void center() { for (int y : ypoints) { ysum += y; } - this.xmid = (int) Math.round(xsum / npoints); - this.ymid = (int) Math.round(ysum / npoints); + xmid = (int) Math.round(xsum / npoints); + ymid = (int) Math.round(ysum / npoints); // reset the rotation direction - this.angle = 359; + angle = 359; // save the original x and y points x0 = Arrays.copyOf(xpoints, npoints); diff --git a/ch16/Sim1.java b/ch16/Sim1.java index ef8db8d..bcd3aa7 100644 --- a/ch16/Sim1.java +++ b/ch16/Sim1.java @@ -14,9 +14,9 @@ public class Sim1 { public static void main(String[] args) { // create some regular polygons - RegularPolygon p3 = new RegularPolygon(3, 100, Color.GREEN); - RegularPolygon p4 = new RegularPolygon(4, 100, Color.ORANGE); - RegularPolygon p5 = new RegularPolygon(360, 1, Color.MAGENTA); + RegularPolygon p3 = new RegularPolygon(3, 50, Color.GREEN); + RegularPolygon p4 = new RegularPolygon(5, 50, Color.ORANGE); + RegularPolygon p5 = new RegularPolygon(360, 50, Color.MAGENTA); // move them out of the corner p3.translate(100, 100); diff --git a/ch16/Sim2.java b/ch16/Sim2.java index a70368b..0a9d921 100644 --- a/ch16/Sim2.java +++ b/ch16/Sim2.java @@ -15,9 +15,9 @@ public class Sim2 { public static void main(String[] args) { // create some regular polygons - BlinkingPolygon bp = new BlinkingPolygon(3, 10, Color.BLUE); + BlinkingPolygon bp = new BlinkingPolygon(3, 20, Color.BLUE); MovingPolygon mp = new MovingPolygon(8, 30); - RotatingPolygon rp = new RotatingPolygon(5, 50); + RotatingPolygon rp = new RotatingPolygon(5, 40); // move them out of the corner bp.translate(50, 50); @@ -48,7 +48,7 @@ public static void main(String[] args) { // delay the simulation try { - Thread.sleep(50); + Thread.sleep(1000 / 30); } catch (InterruptedException e) { // do nothing } diff --git a/ch16/Sim3.java b/ch16/Sim3.java index a52658a..4752785 100644 --- a/ch16/Sim3.java +++ b/ch16/Sim3.java @@ -18,9 +18,9 @@ public class Sim3 implements ActionListener { */ public Sim3() { // create some regular polygons - BlinkingPolygon bp = new BlinkingPolygon(3, 10, Color.BLUE); + BlinkingPolygon bp = new BlinkingPolygon(3, 20, Color.BLUE); MovingPolygon mp = new MovingPolygon(8, 30); - RotatingPolygon rp = new RotatingPolygon(5, 50); + RotatingPolygon rp = new RotatingPolygon(5, 40); // move them out of the corner bp.translate(50, 50); @@ -50,7 +50,7 @@ public Sim3() { */ public static void main(String[] args) { Sim3 sim = new Sim3(); - Timer timer = new Timer(50, sim); + Timer timer = new Timer(1000 / 30, sim); timer.start(); } diff --git a/ch16/WhackAMole.java b/ch16/WhackAMole.java index dea25c3..a4c7fbc 100644 --- a/ch16/WhackAMole.java +++ b/ch16/WhackAMole.java @@ -21,11 +21,14 @@ public WhackAMole() { // create drawing, add polygons drawing = new MoleHill(800, 600); drawing.add(new Mole(150, 200)); - drawing.add(new Mole(350, 250)); + drawing.add(new Mole(350, 200)); drawing.add(new Mole(550, 200)); + drawing.add(new Mole(150, 400)); + drawing.add(new Mole(350, 400)); + drawing.add(new Mole(550, 400)); // set up the window frame - JFrame frame = new JFrame("Drawing"); + JFrame frame = new JFrame("Whack-A-Mole"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.add(drawing); @@ -41,7 +44,7 @@ public WhackAMole() { */ public static void main(String[] args) { WhackAMole sim = new WhackAMole(); - Timer timer = new Timer(500, sim); + Timer timer = new Timer(1000 / 30, sim); timer.start(); } From 561ca418d7bdba9afab07c19a85de9d347ee2174 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Fri, 13 Sep 2019 14:08:30 -0400 Subject: [PATCH 10/52] Refactoring Main and Main2 --- ch15/Langton.java | 10 +++++----- ch15/Main.java | 25 +++++++++++++++---------- ch15/Main2.java | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 ch15/Main2.java diff --git a/ch15/Langton.java b/ch15/Langton.java index 1ebdff1..932a969 100644 --- a/ch15/Langton.java +++ b/ch15/Langton.java @@ -8,12 +8,12 @@ public class Langton extends Automaton { private int head; // 0=North, 1=East, 2=South, 3=West /** - * Creates an 11x11 grid with the ant in the center. + * Creates a grid with the ant in the center. */ - public Langton() { - grid = new GridCanvas(11, 11, SIZE); - xpos = 5; - ypos = 5; + public Langton(int nrows, int ncols) { + grid = new GridCanvas(nrows, ncols, 10); + xpos = nrows / 2; + ypos = ncols / 2; head = 0; } diff --git a/ch15/Main.java b/ch15/Main.java index 694f219..5e4140b 100644 --- a/ch15/Main.java +++ b/ch15/Main.java @@ -7,19 +7,25 @@ public class Main { /** - * Sets up the grid, creates the frame, and plays the game. + * Creates an automaton and runs it. * * @param args command-line arguments */ public static void main(String[] args) { - String title = "Conway's Game of Life"; Automaton game = new Conway("pulsar.cells", 2); + runSimulation(title, game, 500); + } - // String title = "Langton's Ant"; - // Automaton game = new Langton(); - - // set up the window frame + /** + * Creates a JFrame and runs the simulation. + * + * @param title + * @param game + * @param delay + */ + public static void runSimulation(String title, Automaton game, int delay) { + // set up the window frame JFrame frame = new JFrame(title); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); @@ -32,16 +38,15 @@ public static void main(String[] args) { while (true) { // update the drawing - toolkit.sync(); game.update(); + toolkit.sync(); // delay the simulation try { - Thread.sleep(500); + Thread.sleep(delay); } catch (InterruptedException e) { // do nothing } } - } - + } } diff --git a/ch15/Main2.java b/ch15/Main2.java new file mode 100644 index 0000000..1f0c939 --- /dev/null +++ b/ch15/Main2.java @@ -0,0 +1,17 @@ +/** + * Application that runs a cellular automaton. + */ +public class Main2 { + + /** + * Creates an automaton and runs it. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + String title = "Langton's Ant"; + Automaton game = new Langton(61, 61); + Main.runSimulation(title, game, 1); + } + +} From 3032b6fad5f548f05ee208886b6c9b7736297028 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Fri, 13 Sep 2019 14:16:58 -0400 Subject: [PATCH 11/52] Move flip to Cell --- ch15/Cell.java | 8 ++++++++ ch15/GridCanvas.java | 7 +------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ch15/Cell.java b/ch15/Cell.java index b367966..efa29a3 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -68,4 +68,12 @@ public void turnOn() { color = ON; } + public void flip() { + if (isOn()) { + turnOff(); + } else { + turnOn(); + } + } + } diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index ece68af..f85e321 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -61,11 +61,7 @@ public Cell getCell(int r, int c) { */ public void flip(int r, int c) { Cell cell = array[r][c]; - if (cell.isOff()) { - cell.turnOn(); - } else { - cell.turnOff(); - } + cell.flip(); } /** @@ -119,5 +115,4 @@ public void paint(Graphics g) { public void update(Graphics g) { draw(g); } - } From 096ebddffc6a7129dc774d3626eae2a5e8399e81 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Fri, 13 Sep 2019 14:30:13 -0400 Subject: [PATCH 12/52] Simplify Langton.update --- ch15/Conway.java | 19 ++++++++++--------- ch15/GridCanvas.java | 17 ++++------------- ch15/Langton.java | 12 ++++-------- ch15/Main.java | 3 ++- 4 files changed, 20 insertions(+), 31 deletions(-) diff --git a/ch15/Conway.java b/ch15/Conway.java index ad8325c..83a232a 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -13,14 +13,14 @@ public class Conway extends Automaton { */ public Conway() { grid = new GridCanvas(30, 25, SIZE); - grid.flip(1, 2); - grid.flip(2, 2); - grid.flip(3, 2); - grid.flip(6, 1); - grid.flip(7, 2); - grid.flip(7, 3); - grid.flip(8, 1); - grid.flip(8, 2); + grid.getCell(1, 2).turnOn(); + grid.getCell(2, 2).turnOn(); + grid.getCell(3, 2).turnOn(); + grid.getCell(6, 1).turnOn(); + grid.getCell(7, 2).turnOn(); + grid.getCell(7, 3).turnOn(); + grid.getCell(8, 1).turnOn(); + grid.getCell(8, 2).turnOn(); } /** @@ -71,7 +71,8 @@ public Conway(String path, int margin) { for (int c = 0; c < line.length(); c++) { char x = line.charAt(c); if (x == 'O') { - grid.flip(r + margin, c + margin); + Cell cell = grid.getCell(r + margin, c + margin); + cell.turnOn(); } } } diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index f85e321..671701f 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -21,12 +21,14 @@ public GridCanvas(int rows, int cols, int size) { // build 2D array of cells array = new Cell[rows][cols]; for (int r = 0; r < rows; r++) { + int y = r * size; for (int c = 0; c < cols; c++) { - array[r][c] = new Cell(c * size, r * size, size); + int x = c * size; + array[r][c] = new Cell(x, y, size); } } - // set up the canvas drawing + // set the canvas size setSize(cols * size, rows * size); } @@ -53,17 +55,6 @@ public Cell getCell(int r, int c) { return array[r][c]; } - /** - * Toggles the cell on/off. - * - * @param r row index - * @param c column index - */ - public void flip(int r, int c) { - Cell cell = array[r][c]; - cell.flip(); - } - /** * Returns 1 if the cell at (r, c) exists and is on. Returns 0 if the cell * doesn't exist or is off. diff --git a/ch15/Langton.java b/ch15/Langton.java index 932a969..2ca448e 100644 --- a/ch15/Langton.java +++ b/ch15/Langton.java @@ -26,17 +26,11 @@ public void update() { if (cell.isOn()) { // at a black square; flip color and turn left cell.turnOff(); - head -= 1; - if (head < 0) { - head = 3; - } + head = (head + 3) % 4; } else { // at a white square; flip color and turn right cell.turnOn(); - head += 1; - if (head > 3) { - head = 0; - } + head = (head + 1) % 4; } // move forward one unit @@ -57,6 +51,8 @@ public void update() { // update the display grid.repaint(); + + // TODO: draw a triangle to show the ant } } diff --git a/ch15/Main.java b/ch15/Main.java index 5e4140b..178765f 100644 --- a/ch15/Main.java +++ b/ch15/Main.java @@ -13,7 +13,8 @@ public class Main { */ public static void main(String[] args) { String title = "Conway's Game of Life"; - Automaton game = new Conway("pulsar.cells", 2); + Automaton game = new Conway(); + // Automaton game = new Conway("pulsar.cells", 2); runSimulation(title, game, 500); } From 192f1e7d6ddf626679a3673784a08709d5c83702 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Fri, 13 Sep 2019 14:43:55 -0400 Subject: [PATCH 13/52] Suggestions in Conway --- ch15/Conway.java | 28 +++++++++++----------------- ch15/Main.java | 6 +++--- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/ch15/Conway.java b/ch15/Conway.java index 83a232a..80a984c 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -87,14 +87,13 @@ public Conway(String path, int margin) { */ private int countAlive(int r, int c) { int count = 0; - count += grid.test(r - 1, c - 1); - count += grid.test(r - 1, c); - count += grid.test(r - 1, c + 1); - count += grid.test(r, c - 1); - count += grid.test(r, c + 1); - count += grid.test(r + 1, c - 1); - count += grid.test(r + 1, c); - count += grid.test(r + 1, c + 1); + for (int i=-1; i<=1; i++) { + for (int j=-1; j<=1; j++) { + if (i!=0 || j!=0) { + count += grid.test(r+i, c+j); + } + } + } return count; } @@ -106,18 +105,12 @@ private int countAlive(int r, int c) { */ private static void updateCell(Cell cell, int count) { if (cell.isOn()) { - if (count < 2) { + if (count < 2 || count > 3) { // Any live cell with fewer than two live neighbors dies, // as if by underpopulation. - cell.turnOff(); - } else if (count > 3) { - // Any live cell with more than three live neighbors dies, + // Any live cell with more than three live neighbors dies, // as if by overpopulation. cell.turnOff(); - } else { - // Any live cell with two or three live neighbors lives on - // to the next generation. - cell.turnOn(); } } else { if (count == 3) { @@ -146,7 +139,8 @@ public void update() { // update each cell based on neighbor counts for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { - updateCell(grid.getCell(r, c), counts[r][c]); + final Cell cell = grid.getCell(r, c); + updateCell(cell, counts[r][c]); } } diff --git a/ch15/Main.java b/ch15/Main.java index 178765f..cf2e85b 100644 --- a/ch15/Main.java +++ b/ch15/Main.java @@ -13,8 +13,8 @@ public class Main { */ public static void main(String[] args) { String title = "Conway's Game of Life"; - Automaton game = new Conway(); - // Automaton game = new Conway("pulsar.cells", 2); + //Automaton game = new Conway(); + Automaton game = new Conway("pulsar.cells", 2); runSimulation(title, game, 500); } @@ -40,7 +40,7 @@ public static void runSimulation(String title, Automaton game, int delay) { // update the drawing game.update(); - toolkit.sync(); + //toolkit.sync(); // delay the simulation try { From fb040b1bbabb609d9442c499e14190d8f3dbaa9f Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Sat, 14 Sep 2019 14:40:40 -0400 Subject: [PATCH 14/52] removed Main; refactored ch15 --- ch15/Automaton.java | 38 ++++++++++++++++++++++++++----- ch15/Cell.java | 8 ------- ch15/Conway.java | 52 +++++++++++++++++++++++++------------------ ch15/GridCanvas.java | 17 +++++++++++--- ch15/Langton.java | 27 +++++++++++++++------- ch15/Main.java | 53 -------------------------------------------- ch15/Main2.java | 17 -------------- 7 files changed, 95 insertions(+), 117 deletions(-) delete mode 100644 ch15/Main.java delete mode 100644 ch15/Main2.java diff --git a/ch15/Automaton.java b/ch15/Automaton.java index 3451192..ae67edd 100644 --- a/ch15/Automaton.java +++ b/ch15/Automaton.java @@ -1,3 +1,5 @@ +import javax.swing.JFrame; + /** * A cellular automaton consists of a grid of cells and follows a set of rules * that update the grid over time. @@ -9,15 +11,39 @@ public abstract class Automaton { protected GridCanvas grid; /** - * @return the grid + * Applies rules to update the grid. */ - public GridCanvas getGrid() { - return grid; - } + public abstract void update(); /** - * Updates the automaton. + * Creates a JFrame and runs the automaton. + * + * @param title the frame title + * @param rate frames per second */ - public abstract void update(); + public void run(String title, int rate) { + // set up the window frame + JFrame frame = new JFrame(title); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.add(this.grid); + frame.pack(); + frame.setVisible(true); + + // main simulation loop + while (true) { + + // update the drawing + this.update(); + grid.repaint(); + + // delay the simulation + try { + Thread.sleep(1000 / rate); + } catch (InterruptedException e) { + // do nothing + } + } + } } diff --git a/ch15/Cell.java b/ch15/Cell.java index efa29a3..b367966 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -68,12 +68,4 @@ public void turnOn() { color = ON; } - public void flip() { - if (isOn()) { - turnOff(); - } else { - turnOn(); - } - } - } diff --git a/ch15/Conway.java b/ch15/Conway.java index 80a984c..2c49571 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -13,14 +13,14 @@ public class Conway extends Automaton { */ public Conway() { grid = new GridCanvas(30, 25, SIZE); - grid.getCell(1, 2).turnOn(); - grid.getCell(2, 2).turnOn(); - grid.getCell(3, 2).turnOn(); - grid.getCell(6, 1).turnOn(); - grid.getCell(7, 2).turnOn(); - grid.getCell(7, 3).turnOn(); - grid.getCell(8, 1).turnOn(); - grid.getCell(8, 2).turnOn(); + grid.init(1, 2); + grid.init(2, 2); + grid.init(3, 2); + grid.init(6, 1); + grid.init(7, 2); + grid.init(7, 3); + grid.init(8, 1); + grid.init(8, 2); } /** @@ -71,8 +71,7 @@ public Conway(String path, int margin) { for (int c = 0; c < line.length(); c++) { char x = line.charAt(c); if (x == 'O') { - Cell cell = grid.getCell(r + margin, c + margin); - cell.turnOn(); + grid.init(r + margin, c + margin); } } } @@ -87,13 +86,14 @@ public Conway(String path, int margin) { */ private int countAlive(int r, int c) { int count = 0; - for (int i=-1; i<=1; i++) { - for (int j=-1; j<=1; j++) { - if (i!=0 || j!=0) { - count += grid.test(r+i, c+j); - } - } - } + count += grid.test(r - 1, c - 1); + count += grid.test(r - 1, c); + count += grid.test(r - 1, c + 1); + count += grid.test(r, c - 1); + count += grid.test(r, c + 1); + count += grid.test(r + 1, c - 1); + count += grid.test(r + 1, c); + count += grid.test(r + 1, c + 1); return count; } @@ -108,7 +108,7 @@ private static void updateCell(Cell cell, int count) { if (count < 2 || count > 3) { // Any live cell with fewer than two live neighbors dies, // as if by underpopulation. - // Any live cell with more than three live neighbors dies, + // Any live cell with more than three live neighbors dies, // as if by overpopulation. cell.turnOff(); } @@ -139,13 +139,21 @@ public void update() { // update each cell based on neighbor counts for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { - final Cell cell = grid.getCell(r, c); - updateCell(cell, counts[r][c]); + Cell cell = grid.cellAt(r, c); + updateCell(cell, counts[r][c]); } } + } - // update the display - grid.repaint(); + /** + * Creates and runs the simulation. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + String title = "Conway's Game of Life"; + Conway game = new Conway("pulsar.cells", 2); + game.run(title, 2); } } diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index 671701f..858e68f 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -21,9 +21,9 @@ public GridCanvas(int rows, int cols, int size) { // build 2D array of cells array = new Cell[rows][cols]; for (int r = 0; r < rows; r++) { - int y = r * size; + int y = r * size; for (int c = 0; c < cols; c++) { - int x = c * size; + int x = c * size; array[r][c] = new Cell(x, y, size); } } @@ -51,10 +51,20 @@ public int numCols() { * @param c column index * @return the cell */ - public Cell getCell(int r, int c) { + public Cell cellAt(int r, int c) { return array[r][c]; } + /** + * Convenience method that turns on the cell at (r, c). + * + * @param r row index + * @param c column index + */ + public void init(int r, int c) { + array[r][c].turnOn(); + } + /** * Returns 1 if the cell at (r, c) exists and is on. Returns 0 if the cell * doesn't exist or is off. @@ -106,4 +116,5 @@ public void paint(Graphics g) { public void update(Graphics g) { draw(g); } + } diff --git a/ch15/Langton.java b/ch15/Langton.java index 2ca448e..7bf0a23 100644 --- a/ch15/Langton.java +++ b/ch15/Langton.java @@ -9,11 +9,14 @@ public class Langton extends Automaton { /** * Creates a grid with the ant in the center. + * + * @param rows number of rows + * @param cols number of columns */ - public Langton(int nrows, int ncols) { - grid = new GridCanvas(nrows, ncols, 10); - xpos = nrows / 2; - ypos = ncols / 2; + public Langton(int rows, int cols) { + grid = new GridCanvas(rows, cols, 10); + xpos = rows / 2; + ypos = cols / 2; head = 0; } @@ -22,7 +25,7 @@ public Langton(int nrows, int ncols) { */ public void update() { - Cell cell = grid.getCell(xpos, ypos); + Cell cell = grid.cellAt(xpos, ypos); if (cell.isOn()) { // at a black square; flip color and turn left cell.turnOff(); @@ -49,10 +52,18 @@ public void update() { break; } - // update the display - grid.repaint(); - // TODO: draw a triangle to show the ant } + /** + * Creates and runs the simulation. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + String title = "Langton's Ant"; + Langton game = new Langton(61, 61); + game.run(title, 750); + } + } diff --git a/ch15/Main.java b/ch15/Main.java deleted file mode 100644 index cf2e85b..0000000 --- a/ch15/Main.java +++ /dev/null @@ -1,53 +0,0 @@ -import java.awt.Toolkit; -import javax.swing.JFrame; - -/** - * Application that simulates a cellular automaton. - */ -public class Main { - - /** - * Creates an automaton and runs it. - * - * @param args command-line arguments - */ - public static void main(String[] args) { - String title = "Conway's Game of Life"; - //Automaton game = new Conway(); - Automaton game = new Conway("pulsar.cells", 2); - runSimulation(title, game, 500); - } - - /** - * Creates a JFrame and runs the simulation. - * - * @param title - * @param game - * @param delay - */ - public static void runSimulation(String title, Automaton game, int delay) { - // set up the window frame - JFrame frame = new JFrame(title); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); - frame.add(game.getGrid()); - frame.pack(); - frame.setVisible(true); - - // main simulation loop - Toolkit toolkit = frame.getToolkit(); - while (true) { - - // update the drawing - game.update(); - //toolkit.sync(); - - // delay the simulation - try { - Thread.sleep(delay); - } catch (InterruptedException e) { - // do nothing - } - } - } -} diff --git a/ch15/Main2.java b/ch15/Main2.java deleted file mode 100644 index 1f0c939..0000000 --- a/ch15/Main2.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Application that runs a cellular automaton. - */ -public class Main2 { - - /** - * Creates an automaton and runs it. - * - * @param args command-line arguments - */ - public static void main(String[] args) { - String title = "Langton's Ant"; - Automaton game = new Langton(61, 61); - Main.runSimulation(title, game, 1); - } - -} From dbcdbc82f3ba056d3271e668aa28b24e09822365 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Sat, 14 Sep 2019 15:12:30 -0400 Subject: [PATCH 15/52] Suggesting changes --- ch16/BlinkingPolygon.java | 26 ++++++++++++++------------ ch16/MovingPolygon.java | 1 - ch16/RegularPolygon.java | 13 ++++++------- ch16/Sim1.java | 1 - ch16/Sim2.java | 1 - ch16/Sim3.java | 13 ++++++------- ch16/WhackAMole.java | 17 +++++++++-------- 7 files changed, 35 insertions(+), 37 deletions(-) diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java index 06c9b7d..cc19f48 100644 --- a/ch16/BlinkingPolygon.java +++ b/ch16/BlinkingPolygon.java @@ -1,11 +1,12 @@ import java.awt.Color; +import java.awt.Graphics; /** * A polygon that periodically changes colors on/off. */ public class BlinkingPolygon extends RegularPolygon { - private Color onColor; + private boolean drawFlag; private int count; /** @@ -17,23 +18,24 @@ public class BlinkingPolygon extends RegularPolygon { */ public BlinkingPolygon(int nsides, int radius, Color color) { super(nsides, radius, color); - onColor = color; + drawFlag = true; count = 0; } - + @Override public void step() { - // count to ten first + // every 10 steps toggle drawFlag count++; - if (count >= 10) { + if (count == 10) { count = 0; - // toggle the color - if (color != onColor) { - color = onColor; - } else { - color = Color.WHITE; - } + drawFlag = !drawFlag; } } - + + @Override + public void draw(Graphics g) { + if (drawFlag) { + super.draw(g); + } + } } diff --git a/ch16/MovingPolygon.java b/ch16/MovingPolygon.java index 7c6c2f5..87a1235 100644 --- a/ch16/MovingPolygon.java +++ b/ch16/MovingPolygon.java @@ -52,5 +52,4 @@ public void step() { // move one step translate(dx, dy); } - } diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index 4e42533..7c42da5 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -20,7 +20,7 @@ public class RegularPolygon extends Polygon implements Actor { * @param nsides the number of sides */ public RegularPolygon(int nsides) { - this(nsides, 100); + this(nsides, 6); } /** @@ -47,7 +47,7 @@ public RegularPolygon(int nsides, int radius, Color color) { if (nsides < 3) { throw new IllegalArgumentException("invalid nsides"); } - if (radius < 1) { + if (radius <= 0) { throw new IllegalArgumentException("invalid radius"); } if (color == null) { @@ -68,10 +68,10 @@ public RegularPolygon(int nsides, int radius, Color color) { // compute x and y coordinates, centered around the origin for (int i = 0; i < nsides; i++) { - xpoints[i] = (int) Math.round( - radius * Math.cos(i * angle + rotate)); - ypoints[i] = (int) Math.round( - radius * Math.sin(i * angle + rotate)); + double x = radius * Math.cos(i * angle + rotate); + xpoints[i] = (int) Math.round(x); + double y = radius * Math.sin(i * angle + rotate); + ypoints[i] = (int) Math.round(y); } } @@ -110,5 +110,4 @@ public String toString() { str.append(']'); return str.toString(); } - } diff --git a/ch16/Sim1.java b/ch16/Sim1.java index bcd3aa7..76ffe79 100644 --- a/ch16/Sim1.java +++ b/ch16/Sim1.java @@ -37,5 +37,4 @@ public static void main(String[] args) { frame.pack(); frame.setVisible(true); } - } diff --git a/ch16/Sim2.java b/ch16/Sim2.java index 0a9d921..8aa2e81 100644 --- a/ch16/Sim2.java +++ b/ch16/Sim2.java @@ -54,5 +54,4 @@ public static void main(String[] args) { } } } - } diff --git a/ch16/Sim3.java b/ch16/Sim3.java index 4752785..4c4ce85 100644 --- a/ch16/Sim3.java +++ b/ch16/Sim3.java @@ -43,6 +43,12 @@ public Sim3() { toolkit = frame.getToolkit(); } + @Override + public void actionPerformed(ActionEvent e) { + toolkit.sync(); + drawing.step(); + } + /** * Create and start the timer. * @@ -53,11 +59,4 @@ public static void main(String[] args) { Timer timer = new Timer(1000 / 30, sim); timer.start(); } - - @Override - public void actionPerformed(ActionEvent e) { - toolkit.sync(); - drawing.step(); - } - } diff --git a/ch16/WhackAMole.java b/ch16/WhackAMole.java index a4c7fbc..c2205cb 100644 --- a/ch16/WhackAMole.java +++ b/ch16/WhackAMole.java @@ -5,7 +5,7 @@ import javax.swing.Timer; /** - * Simulates the arcade game of Whack-A-Mole. + * Simulates the arcade game Whack-A-Mole. * https://en.wikipedia.org/wiki/Whac-A-Mole */ public class WhackAMole implements ActionListener { @@ -37,6 +37,12 @@ public WhackAMole() { toolkit = frame.getToolkit(); } + @Override + public void actionPerformed(ActionEvent e) { + toolkit.sync(); + drawing.step(); + } + /** * Create and start the timer. * @@ -44,14 +50,9 @@ public WhackAMole() { */ public static void main(String[] args) { WhackAMole sim = new WhackAMole(); + + // TODO: Can we explain the 1000 / 30 or write it so it's obvious? Timer timer = new Timer(1000 / 30, sim); timer.start(); } - - @Override - public void actionPerformed(ActionEvent e) { - toolkit.sync(); - drawing.step(); - } - } From c3eb035f496f4b29355dae30a4cc2bd9c50367ca Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Sat, 14 Sep 2019 15:41:18 -0400 Subject: [PATCH 16/52] draw before step; whitespace --- ch16/BlinkingPolygon.java | 19 ++++++++++--------- ch16/MovingPolygon.java | 1 + ch16/RegularPolygon.java | 17 +++++++++-------- ch16/Sim1.java | 1 + ch16/Sim2.java | 1 + ch16/Sim3.java | 3 ++- ch16/WhackAMole.java | 5 ++--- 7 files changed, 26 insertions(+), 21 deletions(-) diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java index cc19f48..fc81ea4 100644 --- a/ch16/BlinkingPolygon.java +++ b/ch16/BlinkingPolygon.java @@ -21,21 +21,22 @@ public BlinkingPolygon(int nsides, int radius, Color color) { drawFlag = true; count = 0; } - + + @Override + public void draw(Graphics g) { + if (drawFlag) { + super.draw(g); + } + } + @Override public void step() { - // every 10 steps toggle drawFlag + // toggle drawFlag every 10 steps count++; if (count == 10) { count = 0; drawFlag = !drawFlag; } } - - @Override - public void draw(Graphics g) { - if (drawFlag) { - super.draw(g); - } - } + } diff --git a/ch16/MovingPolygon.java b/ch16/MovingPolygon.java index 87a1235..7c6c2f5 100644 --- a/ch16/MovingPolygon.java +++ b/ch16/MovingPolygon.java @@ -52,4 +52,5 @@ public void step() { // move one step translate(dx, dy); } + } diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index 7c42da5..ac667f3 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -20,7 +20,7 @@ public class RegularPolygon extends Polygon implements Actor { * @param nsides the number of sides */ public RegularPolygon(int nsides) { - this(nsides, 6); + this(nsides, 50); } /** @@ -69,23 +69,23 @@ public RegularPolygon(int nsides, int radius, Color color) { // compute x and y coordinates, centered around the origin for (int i = 0; i < nsides; i++) { double x = radius * Math.cos(i * angle + rotate); - xpoints[i] = (int) Math.round(x); + xpoints[i] = (int) Math.round(x); double y = radius * Math.sin(i * angle + rotate); - ypoints[i] = (int) Math.round(y); + ypoints[i] = (int) Math.round(y); } } - @Override - public void step() { - // do nothing - } - @Override public void draw(Graphics g) { g.setColor(color); g.fillPolygon(this); } + @Override + public void step() { + // do nothing + } + @Override public String toString() { StringBuilder str = new StringBuilder(); @@ -110,4 +110,5 @@ public String toString() { str.append(']'); return str.toString(); } + } diff --git a/ch16/Sim1.java b/ch16/Sim1.java index 76ffe79..bcd3aa7 100644 --- a/ch16/Sim1.java +++ b/ch16/Sim1.java @@ -37,4 +37,5 @@ public static void main(String[] args) { frame.pack(); frame.setVisible(true); } + } diff --git a/ch16/Sim2.java b/ch16/Sim2.java index 8aa2e81..0a9d921 100644 --- a/ch16/Sim2.java +++ b/ch16/Sim2.java @@ -54,4 +54,5 @@ public static void main(String[] args) { } } } + } diff --git a/ch16/Sim3.java b/ch16/Sim3.java index 4c4ce85..f725b21 100644 --- a/ch16/Sim3.java +++ b/ch16/Sim3.java @@ -48,7 +48,7 @@ public void actionPerformed(ActionEvent e) { toolkit.sync(); drawing.step(); } - + /** * Create and start the timer. * @@ -59,4 +59,5 @@ public static void main(String[] args) { Timer timer = new Timer(1000 / 30, sim); timer.start(); } + } diff --git a/ch16/WhackAMole.java b/ch16/WhackAMole.java index c2205cb..641d6e3 100644 --- a/ch16/WhackAMole.java +++ b/ch16/WhackAMole.java @@ -42,7 +42,7 @@ public void actionPerformed(ActionEvent e) { toolkit.sync(); drawing.step(); } - + /** * Create and start the timer. * @@ -50,9 +50,8 @@ public void actionPerformed(ActionEvent e) { */ public static void main(String[] args) { WhackAMole sim = new WhackAMole(); - - // TODO: Can we explain the 1000 / 30 or write it so it's obvious? Timer timer = new Timer(1000 / 30, sim); timer.start(); } + } From 543b43a83e82eb9ba433ecdb560efc5bbe01dc47 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Sat, 14 Sep 2019 16:11:02 -0400 Subject: [PATCH 17/52] fixed invisible whack --- ch16/BlinkingPolygon.java | 10 +++++----- ch16/Mole.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java index fc81ea4..2a259cf 100644 --- a/ch16/BlinkingPolygon.java +++ b/ch16/BlinkingPolygon.java @@ -6,7 +6,7 @@ */ public class BlinkingPolygon extends RegularPolygon { - private boolean drawFlag; + protected boolean visible; private int count; /** @@ -18,24 +18,24 @@ public class BlinkingPolygon extends RegularPolygon { */ public BlinkingPolygon(int nsides, int radius, Color color) { super(nsides, radius, color); - drawFlag = true; + visible = true; count = 0; } @Override public void draw(Graphics g) { - if (drawFlag) { + if (visible) { super.draw(g); } } @Override public void step() { - // toggle drawFlag every 10 steps + // toggle visibility every 10 steps count++; if (count == 10) { count = 0; - drawFlag = !drawFlag; + visible = !visible; } } diff --git a/ch16/Mole.java b/ch16/Mole.java index aaa397e..75d48e0 100644 --- a/ch16/Mole.java +++ b/ch16/Mole.java @@ -34,7 +34,7 @@ public void step() { */ public void whack() { // ignore whack when invisible - if (color == BROWN) { + if (visible) { color = Color.LIGHT_GRAY; alive = false; } From c32030b7887adc1001ebfb16468e73bdede6e08b Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 18 Sep 2019 01:27:43 -0400 Subject: [PATCH 18/52] minor changes based on narrative --- ch15/Cell.java | 2 +- ch15/GridCanvas.java | 2 +- ch15/Langton.java | 35 +++++++++++++++-------------------- ch15/empty.cells | 11 +++++++++++ 4 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 ch15/empty.cells diff --git a/ch15/Cell.java b/ch15/Cell.java index b367966..456958d 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -34,7 +34,7 @@ public Cell(int x, int y, int size) { * @param g graphics context */ public void draw(Graphics g) { - g.setColor(color); + g.setColor(this.color); g.fillRect(x + 1, y + 1, size - 1, size - 1); g.setColor(Color.LIGHT_GRAY); g.drawRect(x, y, size, size); diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index 858e68f..70c6718 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -78,7 +78,7 @@ public int test(int r, int c) { if (array[r][c].isOn()) { return 1; } - } catch (IndexOutOfBoundsException e) { + } catch (ArrayIndexOutOfBoundsException e) { // cell doesn't exist } return 0; diff --git a/ch15/Langton.java b/ch15/Langton.java index 7bf0a23..dff37ae 100644 --- a/ch15/Langton.java +++ b/ch15/Langton.java @@ -26,30 +26,25 @@ public Langton(int rows, int cols) { public void update() { Cell cell = grid.cellAt(xpos, ypos); - if (cell.isOn()) { - // at a black square; flip color and turn left - cell.turnOff(); - head = (head + 3) % 4; - } else { - // at a white square; flip color and turn right - cell.turnOn(); + if (cell.isOff()) { + // at a white square; turn right and flip color head = (head + 1) % 4; + cell.turnOn(); + } else { + // at a black square; turn left and flip color + head = (head + 3) % 4; + cell.turnOff(); } // move forward one unit - switch (head) { - case 0: - ypos -= 1; - break; - case 1: - xpos += 1; - break; - case 2: - ypos += 1; - break; - case 3: - xpos -= 1; - break; + if (head == 0) { + ypos -= 1; + } else if (head == 1) { + xpos += 1; + } else if (head == 2) { + ypos += 1; + } else { + xpos -= 1; } // TODO: draw a triangle to show the ant diff --git a/ch15/empty.cells b/ch15/empty.cells new file mode 100644 index 0000000..add6d90 --- /dev/null +++ b/ch15/empty.cells @@ -0,0 +1,11 @@ +!An empty 10x10 grid +.......... +.......... +.......... +.......... +.......... +.......... +.......... +.......... +.......... +.......... From da0053babfca11f4f0b74152947b1caf00c367a6 Mon Sep 17 00:00:00 2001 From: Allen Downey Date: Wed, 25 Sep 2019 10:07:44 -0400 Subject: [PATCH 19/52] Changing cell implementation --- ch15/Cell.java | 27 +++++++++++++-------------- ch15/Conway.java | 20 ++++++++++---------- ch15/GridCanvas.java | 4 ++-- ch15/Langton.java | 2 +- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/ch15/Cell.java b/ch15/Cell.java index 456958d..5566af1 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -6,13 +6,12 @@ */ public class Cell { - public static final Color OFF = Color.WHITE; - public static final Color ON = Color.BLACK; + public static final Color colors[] = {Color.WHITE, Color.BLACK}; private final int x; private final int y; private final int size; - private Color color; + private int state; /** * Constructs a new cell, initially turned off. @@ -25,7 +24,7 @@ public Cell(int x, int y, int size) { this.x = x; this.y = y; this.size = size; - this.color = OFF; + this.state = 0; } /** @@ -34,38 +33,38 @@ public Cell(int x, int y, int size) { * @param g graphics context */ public void draw(Graphics g) { - g.setColor(this.color); + Color color = colors[this.state]; + g.setColor(color); g.fillRect(x + 1, y + 1, size - 1, size - 1); g.setColor(Color.LIGHT_GRAY); g.drawRect(x, y, size, size); } /** - * @return true if the color is OFF + * @return true if the cell is OFF */ public boolean isOff() { - return color == OFF; + return state == 0; } /** - * @return true if the color is ON + * @return true if the cell is ON */ public boolean isOn() { - return color == ON; + return state == 1; } /** - * Sets the cell's color to OFF. + * Sets the cell's state to OFF. */ public void turnOff() { - color = OFF; + state = 0; } /** - * Sets the cell's color to ON. + * Sets the cell's state to ON. */ public void turnOn() { - color = ON; + state = 1; } - } diff --git a/ch15/Conway.java b/ch15/Conway.java index 2c49571..34935b5 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -13,14 +13,14 @@ public class Conway extends Automaton { */ public Conway() { grid = new GridCanvas(30, 25, SIZE); - grid.init(1, 2); - grid.init(2, 2); - grid.init(3, 2); - grid.init(6, 1); - grid.init(7, 2); - grid.init(7, 3); - grid.init(8, 1); - grid.init(8, 2); + grid.turnCellOn(1, 2); + grid.turnCellOn(2, 2); + grid.turnCellOn(3, 2); + grid.turnCellOn(6, 1); + grid.turnCellOn(7, 2); + grid.turnCellOn(7, 3); + grid.turnCellOn(8, 1); + grid.turnCellOn(8, 2); } /** @@ -71,7 +71,7 @@ public Conway(String path, int margin) { for (int c = 0; c < line.length(); c++) { char x = line.charAt(c); if (x == 'O') { - grid.init(r + margin, c + margin); + grid.getCell(r + margin, c + margin).turnOn(); } } } @@ -139,7 +139,7 @@ public void update() { // update each cell based on neighbor counts for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { - Cell cell = grid.cellAt(r, c); + Cell cell = grid.getCell(r, c); updateCell(cell, counts[r][c]); } } diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index 70c6718..a3da137 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -51,7 +51,7 @@ public int numCols() { * @param c column index * @return the cell */ - public Cell cellAt(int r, int c) { + public Cell getCell(int r, int c) { return array[r][c]; } @@ -61,7 +61,7 @@ public Cell cellAt(int r, int c) { * @param r row index * @param c column index */ - public void init(int r, int c) { + public void turnCellOn(int r, int c) { array[r][c].turnOn(); } diff --git a/ch15/Langton.java b/ch15/Langton.java index dff37ae..b744fbf 100644 --- a/ch15/Langton.java +++ b/ch15/Langton.java @@ -25,7 +25,7 @@ public Langton(int rows, int cols) { */ public void update() { - Cell cell = grid.cellAt(xpos, ypos); + Cell cell = grid.getCell(xpos, ypos); if (cell.isOff()) { // at a white square; turn right and flip color head = (head + 1) % 4; From aa248dcbfca524943ae20ec4774c680482660cc0 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 1 Oct 2019 23:43:35 -0400 Subject: [PATCH 20/52] added ColorPolygon --- ch16/ColorPolygon.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 ch16/ColorPolygon.java diff --git a/ch16/ColorPolygon.java b/ch16/ColorPolygon.java new file mode 100644 index 0000000..9cdb8a3 --- /dev/null +++ b/ch16/ColorPolygon.java @@ -0,0 +1,30 @@ +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Polygon; + +/** + * Specialization of Polygon that has a color and the ability to draw itself. + */ +public class ColorPolygon extends Polygon { + + public Color color; + + /** + * Creates an empty polygon. + */ + public ColorPolygon() { + super(); + color = Color.GRAY; + } + + /** + * Draws the polygon on the screen. + * + * @param g graphics context + */ + public void draw(Graphics g) { + g.setColor(color); + g.fillPolygon(this); + } + +} From 14073905f8af2a31f8aa87b90cb65be89497c197 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Fri, 4 Oct 2019 02:07:29 -0400 Subject: [PATCH 21/52] draft of ch16 --- ch16/ColorPolygon.java | 9 +- ch16/Drawing.bak | 65 +++++++++ ch16/Drawing.java | 15 +- ch16/RegularPolygon.java | 21 +-- ch16/Sim1.java | 21 ++- ch16/Sim2.java | 1 - ch16/Sim3.java | 1 - ch16/Sprite.java | 86 ++++++++++++ ch16/VideoGame.java | 48 +++++++ ch16/face-smile.png | Bin 0 -> 9094 bytes ch16/face-smile.svg | 286 +++++++++++++++++++++++++++++++++++++++ ch16/face-smile.txt | 10 ++ 12 files changed, 522 insertions(+), 41 deletions(-) create mode 100644 ch16/Drawing.bak create mode 100644 ch16/Sprite.java create mode 100644 ch16/VideoGame.java create mode 100644 ch16/face-smile.png create mode 100644 ch16/face-smile.svg create mode 100644 ch16/face-smile.txt diff --git a/ch16/ColorPolygon.java b/ch16/ColorPolygon.java index 9cdb8a3..99561bd 100644 --- a/ch16/ColorPolygon.java +++ b/ch16/ColorPolygon.java @@ -5,9 +5,9 @@ /** * Specialization of Polygon that has a color and the ability to draw itself. */ -public class ColorPolygon extends Polygon { +public class ColorPolygon extends Polygon implements Actor { - public Color color; + protected Color color; /** * Creates an empty polygon. @@ -27,4 +27,9 @@ public void draw(Graphics g) { g.fillPolygon(this); } + @Override + public void step() { + // do nothing + } + } diff --git a/ch16/Drawing.bak b/ch16/Drawing.bak new file mode 100644 index 0000000..1acbc52 --- /dev/null +++ b/ch16/Drawing.bak @@ -0,0 +1,65 @@ +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Graphics; +import java.util.ArrayList; + +/** + * Draws a collection of actors. + */ +public class Drawing extends Canvas { + + private ArrayList list; + + /** + * Constructs a drawing of given size. + * + * @param width the width in pixels + * @param height the height in pixels + */ + public Drawing(int width, int height) { + setSize(width, height); + setBackground(Color.WHITE); + list = new ArrayList(); + } + + /** + * Adds a new actor to the drawing. + * + * @param cp the object to add + */ + public void add(ColorPolygon cp) { + list.add(cp); + } + + /** + * Gets current actors as an array. + * + * @return array of actor objects + */ + public Object[] getActors() { + return list.toArray(); + } + + /** + * Draws all the actors on the canvas. + * + * @param g graphics context + */ + @Override + public void paint(Graphics g) { + for (ColorPolygon cp : list) { + cp.draw(g); + } + } + + /** + * Calls the step method of each actor and updates the drawing. + */ + public void step() { + for (ColorPolygon cp : list) { + cp.step(); + } + repaint(); + } + +} diff --git a/ch16/Drawing.java b/ch16/Drawing.java index 445d11e..6d3792f 100644 --- a/ch16/Drawing.java +++ b/ch16/Drawing.java @@ -2,14 +2,13 @@ import java.awt.Color; import java.awt.Graphics; import java.util.ArrayList; -import java.util.List; /** * Draws a collection of actors. */ public class Drawing extends Canvas { - private List actors; + private ArrayList list; /** * Constructs a drawing of given size. @@ -20,16 +19,16 @@ public class Drawing extends Canvas { public Drawing(int width, int height) { setSize(width, height); setBackground(Color.WHITE); - actors = new ArrayList(); + list = new ArrayList(); } /** * Adds a new actor to the drawing. * - * @param actor the actor to add + * @param actor the object to add */ public void add(Actor actor) { - actors.add(actor); + list.add(actor); } /** @@ -38,7 +37,7 @@ public void add(Actor actor) { * @return array of actor objects */ public Object[] getActors() { - return actors.toArray(); + return list.toArray(); } /** @@ -48,7 +47,7 @@ public Object[] getActors() { */ @Override public void paint(Graphics g) { - for (Actor actor : actors) { + for (Actor actor : list) { actor.draw(g); } } @@ -57,7 +56,7 @@ public void paint(Graphics g) { * Calls the step method of each actor and updates the drawing. */ public void step() { - for (Actor actor : actors) { + for (Actor actor : list) { actor.step(); } repaint(); diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index ac667f3..11a26f9 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -1,19 +1,15 @@ import java.awt.Color; -import java.awt.Graphics; -import java.awt.Polygon; /** * A polygon that is equiangular (all angles are equal in measure) and * equilateral (all sides have the same length). It also has a color. */ -public class RegularPolygon extends Polygon implements Actor { +public class RegularPolygon extends ColorPolygon { public static final String[] NAMES = {null, null, null, "Triangle", "Square", "Pentagon", "Hexagon", "Heptagon", "Octagon", "Nonagon", "Decagon"}; - protected Color color; - /** * Constructs a regular polygon, given the number of sides. * @@ -43,7 +39,7 @@ public RegularPolygon(int nsides, int radius) { */ public RegularPolygon(int nsides, int radius, Color color) { - // validate and store arguments + // validate the arguments if (nsides < 3) { throw new IllegalArgumentException("invalid nsides"); } @@ -60,7 +56,7 @@ public RegularPolygon(int nsides, int radius, Color color) { this.ypoints = new int[nsides]; this.color = color; - // the angle (in radians) at each vertex + // the angle (in radians) for each vertex double angle = 2.0 * Math.PI / nsides; // rotation that makes the polygon right-side up @@ -75,17 +71,6 @@ public RegularPolygon(int nsides, int radius, Color color) { } } - @Override - public void draw(Graphics g) { - g.setColor(color); - g.fillPolygon(this); - } - - @Override - public void step() { - // do nothing - } - @Override public String toString() { StringBuilder str = new StringBuilder(); diff --git a/ch16/Sim1.java b/ch16/Sim1.java index bcd3aa7..2f747d2 100644 --- a/ch16/Sim1.java +++ b/ch16/Sim1.java @@ -2,7 +2,7 @@ import javax.swing.JFrame; /** - * Example simulation of stationary objects. + * Initial drawing of stationary objects. */ public class Sim1 { @@ -14,25 +14,24 @@ public class Sim1 { public static void main(String[] args) { // create some regular polygons - RegularPolygon p3 = new RegularPolygon(3, 50, Color.GREEN); - RegularPolygon p4 = new RegularPolygon(5, 50, Color.ORANGE); - RegularPolygon p5 = new RegularPolygon(360, 50, Color.MAGENTA); + ColorPolygon p1 = new RegularPolygon(3, 50, Color.GREEN); + ColorPolygon p2 = new RegularPolygon(6, 50, Color.ORANGE); + ColorPolygon p3 = new RegularPolygon(360, 50, Color.BLUE); // move them out of the corner - p3.translate(100, 100); - p4.translate(250, 250); - p5.translate(400, 400); + p1.translate(100, 80); + p2.translate(250, 120); + p3.translate(400, 160); // create drawing, add polygons - Drawing drawing = new Drawing(800, 600); + Drawing drawing = new Drawing(500, 250); + drawing.add(p1); + drawing.add(p2); drawing.add(p3); - drawing.add(p4); - drawing.add(p5); // set up the window frame JFrame frame = new JFrame("Drawing (no animation)"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); frame.add(drawing); frame.pack(); frame.setVisible(true); diff --git a/ch16/Sim2.java b/ch16/Sim2.java index 0a9d921..c1284c2 100644 --- a/ch16/Sim2.java +++ b/ch16/Sim2.java @@ -33,7 +33,6 @@ public static void main(String[] args) { // set up the window frame JFrame frame = new JFrame("Drawing with Thread.sleep"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); frame.add(drawing); frame.pack(); frame.setVisible(true); diff --git a/ch16/Sim3.java b/ch16/Sim3.java index f725b21..2bb42d0 100644 --- a/ch16/Sim3.java +++ b/ch16/Sim3.java @@ -36,7 +36,6 @@ public Sim3() { // set up the window frame JFrame frame = new JFrame("Drawing with ActionListener"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); frame.add(drawing); frame.pack(); frame.setVisible(true); diff --git a/ch16/Sprite.java b/ch16/Sprite.java new file mode 100644 index 0000000..5835750 --- /dev/null +++ b/ch16/Sprite.java @@ -0,0 +1,86 @@ +import java.awt.Graphics; +import java.awt.Image; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; + +/** + * A small character that can move around the screen. + */ +public class Sprite implements Actor, KeyListener { + + private Image image; + + private int xpos; + private int ypos; + private int dx; + private int dy; + + /** + * Reads a sprite from a png file. + * + * @param path location of image file + * @param xpos initial X coordinate + * @param ypos initial Y coordinate + */ + public Sprite(String path, int xpos, int ypos) { + try { + this.image = ImageIO.read(new File(path)); + this.xpos = xpos; + this.ypos = ypos; + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void draw(Graphics g) { + g.drawImage(image, xpos, ypos, null); + } + + @Override + public void step() { + xpos += dx; + ypos += dy; + } + + @Override + public void keyTyped(KeyEvent e) { + // do nothing + } + + @Override + public void keyPressed(KeyEvent e) { + switch (e.getKeyCode()) { + case KeyEvent.VK_UP: + dy = -5; + break; + case KeyEvent.VK_DOWN: + dy = +5; + break; + case KeyEvent.VK_LEFT: + dx = -5; + break; + case KeyEvent.VK_RIGHT: + dx = +5; + break; + } + } + + @Override + public void keyReleased(KeyEvent e) { + switch (e.getKeyCode()) { + case KeyEvent.VK_UP: + case KeyEvent.VK_DOWN: + dy = 0; + break; + case KeyEvent.VK_LEFT: + case KeyEvent.VK_RIGHT: + dx = 0; + break; + } + } + +} diff --git a/ch16/VideoGame.java b/ch16/VideoGame.java new file mode 100644 index 0000000..08df88e --- /dev/null +++ b/ch16/VideoGame.java @@ -0,0 +1,48 @@ +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JFrame; +import javax.swing.Timer; + +/** + * Example game with a sprite that moves around the screen. + */ +public class VideoGame implements ActionListener { + + private Drawing drawing; + private Toolkit toolkit; + + /** + * Set up the drawing and window frame. + */ + public VideoGame() { + Sprite sprite = new Sprite("face-smile.png", 25, 150); + drawing = new Drawing(800, 600); + drawing.add(sprite); + drawing.addKeyListener(sprite); + JFrame frame = new JFrame("Video Game"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(drawing); + frame.pack(); + frame.setVisible(true); + toolkit = frame.getToolkit(); + } + + @Override + public void actionPerformed(ActionEvent e) { + drawing.step(); + toolkit.sync(); + } + + /** + * Create and start the timer. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + VideoGame game = new VideoGame(); + Timer timer = new Timer(25, game); + timer.start(); + } + +} diff --git a/ch16/face-smile.png b/ch16/face-smile.png new file mode 100644 index 0000000000000000000000000000000000000000..417024e3e7376c9b8832c50050b855fe54781e86 GIT binary patch literal 9094 zcmZ9S2Q-{d`0rO=oz;WrEP@S5w1j2#2&;r3%Bm4%SBc&`(ZcE_x)3dTmk`A2z4st` z7u}WL|K4-%z3+MFop)xw^E{vDIdk4K?>Q3=S5qVAkQumz<&hl@ZwUCz1t_Vj9fUB#k zptZe?lNkbKA&7LeO51z>;9f-gPo!<_Y-<5L{VVsc|Bt!<+&Hn`2gnNlU}|e^#wv%jLs;7js`xMC+|#lBqk}nGApW7TYFpb` z0E8irAp#H)0f?A3L`>odL;~`Z^ReR2y;$|1SPS{V(aZwykJ9NL6N$30H?y@yAsn6m z12ngAMp)Yli9m!Oi~dgx0{=25@L$FROx*?k?-a3SwA$a>ee)j#66Nk_ZS~F>0E0pP zUszT-3v+9;|3UoU*)jVM*~P*PX=jJDclysY>c0TZ|BFw^!@?0M^jHug)V11j0RXT9 zl;vc!-O_h6Jl&XIHyrrdSng+-Z)6rEJy9Ng)}o<8T>Vys_zl$lHJ_X0QlVeiL#Re{ z4*1I-aVDCG&jc}VaZj?`yh?P715Er!9%5>s#MRUfQWxT$y>eQdPD;_+zJ8q4ayFn= z8DG%3adjz0V$;9V)0g^Jbic`dKeb&$oKJD>3sXX_qjogr|1|E(<(nt*=!;79gQx52 zDrESa5;ZHCxG*wkB6%f0wCo4sd=KbJD#qQ@%Ga^Gw9d3`a&18OcG-W<)l(+dI=Pp6 z%NzR}AeoRlatV|OeX1PUk9`^`993A}nvL8>@a?hnN^{0u=_=3>{p6wCGNsl!StKIj z2lIX{^pNF{ALe7n>kNWv^ug)7zkSnutXU)lI<%J{don!Q5-N9Xawed!QKC>}Z1lm* zE0E#~$6seyuQW+4fiK*Uum9W%Z%bwA4S-FRkB_nFb8Aq~=|^yRx_n+1{V0jMZ~nH1 zbYBIqg5c;od2cb= z%vcC_5+?zWuxjblcm489ng{niCP|0Voqrsd1}6RjJWh@|dd5h>s>({DfQvx0MQZ-7 z$3|o4EB*AGYTDLYm^q>&+wsMTG5QRhw@Oh;9`-FgK~Yv~mAYsQl+ zLIk}_uSz$Ixx-yc7{vyvEDK&{vLH=_e=UDo=z_5!uN83wr6#H<{XjPYgJn)VZ>yWiSTC#m8>^(AAA?8-pFSZ-@O zL|c?Xq^x<{F;A!s0!<6&lUC~!L3u|08n7c!(d%^zOjvGkjA5Jly_DRkA zUHf-C!-lkjW4BNd5qtLU1YafP{bjif;NMEae#y1tt-gCFmeC%dsjqKDnmfkDKS27S z%%|Pw5Vg5of!%NyowFUhB*oS@G~(3SGl!RiNM_5cAxLqXwkso|LLurYWPylA6yyao zq%NhN*1Qoz7cvV3vI6(p-ol5nz%hQ9;{0as6zFLSp{6PAD@6Obcx1U$$hsk85c&*{ zu0@*3=*D%ss3W_o1ONAJ!tfvwn~!NK-bxAazR6bPUk+Tca9xcFNozdML^iMO@6zkA zL%_KKfM<6?F2o}22`**UL1ktW@exLHvY!~QUAlymuay{dMbRn3%l|dEcHPZo=b9x? zHN#=J0a0^FxSjHCVitjQw8Sh=$MF*uLiudK(1EUow2(b^DxB{7ba~4S8}37rC$3y0 ziNfDs6OQ7=t`+-L*ZARc8470mQ?SqLQ&~UTYn>dWQ<2$XJrU)Iu+n_{7IyPn-gfaD zEpMp>T?XAk-6f&T>YFY5KL6+SmG6o`E0k=Jzbc7a73asez!s}NKg;*1;ikSm7bIi} z+9<=;O$b5Pf;qm3zJ)aQ9>v?buC-m_cF)UIfy(KGyeP21csk@KEm7c1d5uFk?kMSy zf^{qSNP|hI`|_lYG{TON|0aqz_VfH}VIzqWO8AGF%CuyuD_L9+Pb=1%bN)8|pfG;@ zqnqTU!LqUWMLheLeFQiRG_EEzD$=U87Fh=2cTFk=q2ELEzDLU#Q{^}da^=@(Cx{-{ zA4}lWFRc*wEj~Z0pMOd#@gzi=OIm}7P3uSotEOtb%w&Cz2KYU^EzD731T(gcEhJPO z@#4#pJWz&SF4>v*5fc*~JL4B$(*0Eb(~JIhELjUBYWw_co!le#aBKGMwcf7S8Bh=dT_i zZKnqVR=Gh@AuUekmtG0Az-;PY{_Z9AN-hX=|NY7|o1Q$A@cvdiBgd(IzQME8#!~#S zJJ0O=JEk2!=vya*eVB&j4sY%CsD=x_niuRKq$y(Zh@B)zc)@uw%6mWhwb${)9j3lJ zR7fiR&gV~BkSso*8DN;@Yh??iaoe#K4sE&p%#UEYyW~LTZ%g{|HW;_-n7dGhQ57u4 zwJ2KRZmii?!DfNG`O$$Dr;Bz!^T=5->RCb)11z_W0y@QmIx3Hzk1br&H#}Muq#nj2 z7AkCh|KN*H`p=IGYr(VO$8#Y=b0NSvrJ2qW_xDtbmjf`Iy@M-hsSXUw&9ka-CTI4j zlUA4VH*KBLhPP0B62HWWhf;?r(k9bHe>0qWi@sM$mFrOE@pHbQ!5+T^bCSbB%-uyi zZwV_Ya!ELJG)WVXzvsOG6o^qKzna_nGW!%G*3o8`gZ?pTf6Jh< zmifJD_lkUYVVJ-}i-A-H-}#5{!WFe->a3HI%`xMZ+qo!msTHFC^3`^)c?VqfI0mDz zdqD+=irNsipR4u&3-0}2J2KB4k}7ImzpFS5wVE}6x4lZUc^ z>YoNnd;?#lEi#<=+}sfQ+#1K^^Y3BN)KI=P=Kaw^Ucy{?{a5OokKvU_sVmEqWGB5a zp~Ly1L!tsi#R=M`<*FFD=*qH;NDvKU0>u*e(6<1@vK_CP-oIDJ=Ty7q5;ifH>8VJ} zs@vTwzukV>vEX!SJmEj#+fzZZJHu#fXNi2-9XmO5ZOPx?)Y$Vy<%4U&(~7u;?cM5I z(sZ%a;s-_Ll6WS?(*|DC739MAJ}9!!CBElqmA6Ak&5H^1FNav*=Jnd8JTCx=KSDN) zSk5wqTCTYhxfp;?ojmt~3z{>RgOmPRul1-@k*^g$O!pBxV8Z?pek^o6pix(%|Fn^I z=ZpVbn{Xq=8+{}31m&7SKkSq-npDyNnTL=5ysSDcW$sv*th8O2ZcXz?iIg{eFz^{& zF{t}MK6YF&Uis_!#&`T!+SduADcVlYzen!P4<8@#K@%e%gt7fB1VkGiP^yl~=}W>Z zU8|FFrR}Lcu89VFXSFy@In9v$)=jJp3~wG_)ZC%3Zu4Wq?e4z>0A$0}qt`Wau^qQd zgV35RqLCCINUZ?%@v01Q9CC^mcZ}x-#>Ra6SAWmCD$C+CWFIB=ZR>k`7xk@}8(C6l z;0%iYnedH&ug1y5i#Ha!cjaT@ZWKIZt_|Ia$lbuA;+g!cQe6+?GEiY$b z6gYq7dwJZXBac>H^E8xeYsQImk6i>v7~y3(Y;EpsMjRjW1##zMvoAgJ+d4c3#1>^V z(CiVgyQxgl6jX~l1plOn(-UC~5vo8yY`V-xWQeB^-|Tr?^{1y#R`sR4_`#oKJfIp( zpiyw!OZ&Vq(_>_{aW|q^kKPj3U;o)i=2e*goReY?u8F;}9`o?Z`?~I}>Q64}dbF_) zeN|zR06g_ie4RP+-DIA3W*Y-pV(;r$U+3kj2tSfnR?~m-qI^TI-Xu&%MO`WH$X<{hYx7tIQU}90H^NT~!*y=J%$BRiNE6xjl!^kC(&RIygky!VewX zE>AC8kLL&ijzX1j*f=rH{0@{Sq@1$v4r^su(bCmX2I55f%R#eDwAGHIx>A@|q8_>A z7zOcN*7$Q8h`Er=uYhH&I2U58M=8H%cp<_>o=MNZDWR*7YaFif&`iFTiXY|pr6rOtF zf*{5@R|ehwR6o4h#UG6Nn~?8+@KB;D`Y5f{BV(mdhghW=n_Hy|%0*b3IXX=oK+SG#V(IBG^klcxakxJIhXeR_YH3B9?bY)-69} zA?=rFP6p?zOUQ)uj!0y_J56YHE}AQs*o+frQJF4RDCw&S&c0?9uJ! zcyHlOd_Wb=tf+#=Uh*OgXGFO$8g^VJ=-~-s@Q%uQjUHFgJnt4xtJ*ZvS>Mk)mLV2+ zXLm6eg!}5_FHSnj>8<-?m80T7Kqifp<$6l!`c~r%zDi z`FQ8p$tpiGI2`SkNEXgUy<<+n1Ls%F*F^9M7jcvmd22(_CZElCD&oAep!8hg2;iol znbYuvQ^Q4*kf}kDYVXjZt@FnouWcM9nS~=(H^vklktGidx6^Q8u3oj#Lbg_K-1V`c zK)Nr+Jm~RH=LS7oOUhbjr7lSd)RGxXhqx`2WD0+X#RiX>T|4EOt75=LC5p3MS=e2c zkcUY$MaX;Aoi3vMk-)3K;d#x(H1=K#Qoz^15krJT@vyNvI4{xTB72Ln+wuHb{p@jW zYx=a-R~fR$O?qMv{p6Z)x|MS%kWuh94yydOtS$4Na~MJG%^#@B1&MtbEjzER&uZP& zl=kOcFFE6R2ggZDcq#?3OHS5dY@?dmCR{05B4t7uS*lXh%yKjDPw09B5t3dPw=SvV z-`l(#34gkfmu3aL2bg*b?6tx<^ot>>!wYtRjEucJbeQUa$+=)JA@x#gI2qrns!;&3bf zWG-tf3{({5ZrF^F?|V48snAN!!xaVCv7g8Fb4;gG$XTSsY1p!9nWf&@-I-EjXTT95 zS}t~8`|={M3^zgIS4kuF-Qj-HkPD=fr`$8xxO67G`UT#5*j5AI;YoqstEJ0okIvzo z$qZZK!|hro$P?Gu1q+9M^~U?{_DXvE_WAGW_^iM4%L!C`{yE`!OrhR(NWUy;qh$Kw zhHzRT6A>(^H0~K)_DH&ziCNkk_Wk0u8zC9#)THhKFLAf zrqFL>(n12I(I_@tOq~<-uyFSw);(ykwwVw4TZ)tls5FXlKazJ2YYjWbded)>%pvM zTOu)DR}IeJB(#4+zv9)e8tX`QGfRewS8-P%R*mZNi*OCn;!2E0J8TSA#1eBX(`96) zn155L5Ui4)_n3g?-Z8g4Np_as?SM!BF11X1z0IU^yI^@kt30=@uUf*lvR9toep31D zkIjHF?>G-^+ID8P?yzfO5$FBxYh$(RZlw>Bsf2uhJa`*~n#KEgw@pL0j$Xroy}DGs zM;nq`fR+WjeuoosBrj>Szb@Ny56&lEcl_IyG5BiH_@$yNr~^eeXKPnERh#>fz-P91 z$C`4zA1IQ`rV5Md`N@aV5%nB(B}*i%U{%vV!bP*o95+FxJZjV_>B*Vqs?=yEC5qDl z$fu5~u_$TYbK{mfgZ*9F*2WKmm|TMZwNGE{F;kJpD3s^okBrRT)iuVwJ6=eP(vp;P zz2Ay4^U<-*Oxi%2QLJl%iaNJniXd+-7(nAy;d=2_hfBK~PTlIp>z%KzC}mCP@k0>x zdnMD$8HPk`k4QRLnLyg;RBc@#5iu?v0+_~{&z|W_Ge2AYXE$^&`FkZP8l=SAqHRJi zyy{LnP_|@{G?+iOfHm)4{l&RRANYyr@{+vrX1)+hB8d4$;3Vcvd9G1#lZ(Jnj#CG1 z#dE~zV>=8;ZdvY~?+@mJg8^dv!30J;`jSQ6TOwUT9Z7l0AJbNSW-I5Q1&=!7UT(h? zWP!B@t$AEEZbnPMnc$CGvcQQz{8DE8-TC`FV4+^7UAQ{sQPnf}6eIw9-4 zEMFUnuJ}42PJt0oHn`m0C;5h;mK9gJeyeMbMN-4JnXw+2R zDHOXGp#*MBJC^yACd4+1cbFgZq++F-5H04JZ5H1IdY=a>^0Q9LhPdtJdx}pTl7V%6 z_H4XkqIC*Gub2I()T=}j<=go^uFhUP(4B_L%i~awL%S8~EO5?8Gh{zvpS1DDF5^}}fCABh!2uN6)Tx6}rqe&sa{{&1lm)2u9o0cCzs_hsn!T@*&H&X7-hvz5V1 zSeN-TgL@-TUlpAj8xkWs%z4H#)lST~PcW4cd1ie1C--;T6xT}y>XaABZY(uk1r-&V zUgtSi;7IC@*23)9PPrjx7ep}J(H0yj<7|O?XDbv8{w5Gy;t%Il;XV71H#MD_RVpIy znIzB7r9AByp!5b#Pph4n9LZ0vVa#laIR_$eDyS%s{onGV3#!%Y0*NF^$7l4BAkH(hG zd9_-U2Jn*uMHw_mWzOLVA~w3_)a>JP8>dUQahx7OrH6e;6oiF06}PHPo`EgXceBuT zy7mEejL&-4?OLeEriQ3z6_?)FU2uTg@Cvi!os~=fPepOd3CHA12e+#Q)&&|R{+Adm z9nksZTbp*QKY`jTS*41UcqVSfsDpBTfr{1NPj8=S5+=2usQXh|Zj_PQPM=xfR!_4@ ziO?poh!A7BEe-r31V5u!s6W8jSQt3p(u>^+s@r#fJqi_w0i4iGSum+R zCPu7VWq%1N+iQ7#RL59Rnq1B7a4YRAP#f~t4X5kKQ_u92YQmp5F<62WW^}$+MygtB ztcq~PMh^s)P0owDiVd^l1W)Kv-qt6$cuk#u`9{q_5|soyq&B@_zW&hvij&GPPt$8Z zwfyg0#7P~DtO#m`CAZYr3Zb~&jz3#J9w3nqR?28Jn{-mOc_YgyL5Yd+&#e2-5NPpB zQNNEp*?|kK%8?Rr_$OX;bhawVT=QnHV80uwmOuAEZB~JF9qtF*--k`lHqz}{4L*OW zO>nsCQfF(fGS5pb#{=zrUKdw)93A1l&!veaQXcY7;80F9M*2oTLLyZuZ%nIhjWl*_(Ck zLhkN8JV5G`u4m#0g_FBpeZoHEFSP{(Vi94j#}CewtJ+ZXk0(4@m^|~y+x@P?{VH8u zM&qeA^S(>!b38`B-lJbwhvxV@1Gdgs=WqD_nZFLVk64-vx58Adodt#{fR7< zfqdJ91l_=Nx?kCVVJ+skPutCOMh-46AHF`VdH_473in=J^w@X|CtL06{}DM+52GB` zucJy)|7=mhsY&>B1KQD@RZphKw_xX!+Wq;KjQL;EcP@G#YMnLofhHJ&@_}4lbGRt&j;OjB8{;Dur7&<|;;`}H7mm<9&YkGTk&&A+q-K_1X z?2c!O{OrGhU`>bX9t>?XyupIkkyZ{&aUJ z=ISbt&MqiM7__!=`C`i0BVzg>`vjPNOPWM&;#wSmbYR-kfB5{wHMl?Bv_pH=a_KJMWh9pFQE%4Q$G7vtrnIu ze{=tv3P|~Bm~Rn4=^*KtZ3-?42_UowIOnm~M`}kbv_4C9mFl0^RmXRz|K>A(vSqm; z+IDTWrPuuflYQ;QO5$q!%X00Vgb;_01T63g)-gvfj95*N{?<*tNKB)iMKdp_@>5X_ zkA{KB=ZNBI>L6l@TyQ0}rb|RwwCg*&*}mv`p-~4Ek&kfDU~&H8Uqw2_Aec%ATeoX(b7o0^Ag^gm7RCl$yg;#=c=;20snHYsm1((eoS$ z7$S`4VIbzibY7!=-MEq|a@6K}G&Q<=@B3U_+8{BL6Vk}tpvZl{^N5M#4w(l%iAhXb z2cA+YEM&4}1&(JX8CYS{B7K-u%a0it;z$4hOX%NOfRG-lzQ!Y>_Z$cf5LtL!tnw!W zC=O&j`}2|F>1^Vk{hc^Z1M)8~_MeD18PBd%!@77rRw91SRLYQ8$uvMC-+@g_)?o@} zSktWdIPBHV6?TxGae`m?In~;Av2PPaG>IR4i`>MeX%OJhB@ou#csxmQ28aIov=uiW zIDp3~*&l)?1vCCKK`98Bk;=90!3C9dJp}0zhy$eJB&M>AYRx+ij;G7`lNd(@EXAPi zuct14En~-dlg|_3R{@!!XSYhF9ZAb2oJm)h*KH*D=6!|yF}SgB|MuaTf_weuphvuS zs8y9fJ&cJ7+1F+|sH1YN!Grhsf{b!fv@08-*ztyiOxZn`suzk_!s#R%#UaIGr(R_e i|KBNvYiXf7VyZWthU2}Mg8QQy0A+bKxiVRkfd2)&wJUD` literal 0 HcmV?d00001 diff --git a/ch16/face-smile.svg b/ch16/face-smile.svg new file mode 100644 index 0000000..362f67e --- /dev/null +++ b/ch16/face-smile.svg @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + tango face smile + 2010-03-08T08:40:05 + Smiley icon from Tango Project: http://tango.freedesktop.org/Tango_Desktop_Project \n<br><br> \nTango Project icons are Public Domain. + https://openclipart.org/detail/30217/tango-face-smile-by-warszawianka + + + warszawianka + + + + + emote + happy + icon + smile + smiley + + + + + + + + + + + diff --git a/ch16/face-smile.txt b/ch16/face-smile.txt new file mode 100644 index 0000000..ea6f5b1 --- /dev/null +++ b/ch16/face-smile.txt @@ -0,0 +1,10 @@ +Source: +https://publicdomainvectors.org/en/free-clipart/Smiley-face-icon-vector-image/15374.html + +Description: +Vector illustration of a smiley face icon. Color drawing of a yellow smiling emoticon. + +License: +Public domain + +inkscape -z -e face-smile.png -w 100 -h 100 face-smile.svg From 869baded6a726bcc969de9f4b959586c7097d90d Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Fri, 4 Oct 2019 16:23:15 -0400 Subject: [PATCH 22/52] revised ch16 examples --- ch16/BlinkingPolygon.java | 2 +- ch16/ColorPolygon.java | 13 +++++++++++++ ch16/RegularPolygon.java | 4 ++-- ch16/VideoGame.java | 3 ++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java index 2a259cf..118dcf6 100644 --- a/ch16/BlinkingPolygon.java +++ b/ch16/BlinkingPolygon.java @@ -7,7 +7,7 @@ public class BlinkingPolygon extends RegularPolygon { protected boolean visible; - private int count; + protected int count; /** * Constructs a blinking polygon. diff --git a/ch16/ColorPolygon.java b/ch16/ColorPolygon.java index 99561bd..6db23a9 100644 --- a/ch16/ColorPolygon.java +++ b/ch16/ColorPolygon.java @@ -32,4 +32,17 @@ public void step() { // do nothing } + /** + * Test code that creates a ColorPolygon. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + ColorPolygon p = new ColorPolygon(); + p.addPoint(57, 110); + p.addPoint(100, 35); + p.addPoint(143, 110); + p.color = Color.GREEN; + } + } diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index 11a26f9..3ad566a 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -56,13 +56,13 @@ public RegularPolygon(int nsides, int radius, Color color) { this.ypoints = new int[nsides]; this.color = color; - // the angle (in radians) for each vertex + // the amount to rotate for each vertex (in radians) double angle = 2.0 * Math.PI / nsides; // rotation that makes the polygon right-side up double rotate = Math.PI / nsides + Math.PI / 2.0; - // compute x and y coordinates, centered around the origin + // compute x and y coordinates, centered at the origin for (int i = 0; i < nsides; i++) { double x = radius * Math.cos(i * angle + rotate); xpoints[i] = (int) Math.round(x); diff --git a/ch16/VideoGame.java b/ch16/VideoGame.java index 08df88e..3f54c3c 100644 --- a/ch16/VideoGame.java +++ b/ch16/VideoGame.java @@ -16,10 +16,11 @@ public class VideoGame implements ActionListener { * Set up the drawing and window frame. */ public VideoGame() { - Sprite sprite = new Sprite("face-smile.png", 25, 150); + Sprite sprite = new Sprite("face-smile.png", 50, 50); drawing = new Drawing(800, 600); drawing.add(sprite); drawing.addKeyListener(sprite); + drawing.setFocusable(true); JFrame frame = new JFrame("Video Game"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(drawing); From de389a06e50938fb52bb2c3cce41ce3906984905 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Sat, 5 Oct 2019 20:19:13 -0400 Subject: [PATCH 23/52] sync with ch15 revisions --- ch15/Cell.java | 5 ++--- ch15/Conway.java | 45 +++++++++++++++++++++++++++++++------------- ch15/GridCanvas.java | 2 +- ch15/Langton.java | 19 ++++++++++++++----- 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/ch15/Cell.java b/ch15/Cell.java index 5566af1..7eecbe3 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -6,7 +6,7 @@ */ public class Cell { - public static final Color colors[] = {Color.WHITE, Color.BLACK}; + public static final Color[] COLORS = {Color.WHITE, Color.BLACK}; private final int x; private final int y; @@ -33,8 +33,7 @@ public Cell(int x, int y, int size) { * @param g graphics context */ public void draw(Graphics g) { - Color color = colors[this.state]; - g.setColor(color); + g.setColor(COLORS[this.state]); g.fillRect(x + 1, y + 1, size - 1, size - 1); g.setColor(Color.LIGHT_GRAY); g.drawRect(x, y, size, size); diff --git a/ch15/Conway.java b/ch15/Conway.java index 34935b5..572ab78 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -13,14 +13,14 @@ public class Conway extends Automaton { */ public Conway() { grid = new GridCanvas(30, 25, SIZE); - grid.turnCellOn(1, 2); - grid.turnCellOn(2, 2); - grid.turnCellOn(3, 2); - grid.turnCellOn(6, 1); - grid.turnCellOn(7, 2); - grid.turnCellOn(7, 3); - grid.turnCellOn(8, 1); - grid.turnCellOn(8, 2); + grid.turnOn(1, 2); + grid.turnOn(2, 2); + grid.turnOn(3, 2); + grid.turnOn(6, 1); + grid.turnOn(7, 2); + grid.turnOn(7, 3); + grid.turnOn(8, 1); + grid.turnOn(8, 2); } /** @@ -71,7 +71,7 @@ public Conway(String path, int margin) { for (int c = 0; c < line.length(); c++) { char x = line.charAt(c); if (x == 'O') { - grid.getCell(r + margin, c + margin).turnOn(); + grid.turnOn(r + margin, c + margin); } } } @@ -122,21 +122,32 @@ private static void updateCell(Cell cell, int count) { } /** - * Simulates one round of Conway's Game of Life. + * Counts the neighbors before changing anything. + * + * @return number of neighbors for each cell */ - public void update() { + private int[][] countNeighbors() { int rows = grid.numRows(); int cols = grid.numCols(); - // count neighbors before changing anything int[][] counts = new int[rows][cols]; for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { counts[r][c] = countAlive(r, c); } } + return counts; + } + + /** + * Updates each cell based on neighbor counts. + * + * @param counts number of neighbors for each cell + */ + private void updateGrid(int[][] counts) { + int rows = grid.numRows(); + int cols = grid.numCols(); - // update each cell based on neighbor counts for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { Cell cell = grid.getCell(r, c); @@ -145,6 +156,14 @@ public void update() { } } + /** + * Simulates one round of Conway's Game of Life. + */ + public void update() { + int[][] counts = countNeighbors(); + updateGrid(counts); + } + /** * Creates and runs the simulation. * diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index a3da137..c936135 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -61,7 +61,7 @@ public Cell getCell(int r, int c) { * @param r row index * @param c column index */ - public void turnCellOn(int r, int c) { + public void turnOn(int r, int c) { array[r][c].turnOn(); } diff --git a/ch15/Langton.java b/ch15/Langton.java index b744fbf..45869a1 100644 --- a/ch15/Langton.java +++ b/ch15/Langton.java @@ -21,10 +21,9 @@ public Langton(int rows, int cols) { } /** - * Simulates one round of Langton's Ant. + * Flip the color of the current cell. */ - public void update() { - + private void flipCell() { Cell cell = grid.getCell(xpos, ypos); if (cell.isOff()) { // at a white square; turn right and flip color @@ -35,8 +34,12 @@ public void update() { head = (head + 3) % 4; cell.turnOff(); } + } - // move forward one unit + /** + * Move the ant forward one unit. + */ + private void moveAnt() { if (head == 0) { ypos -= 1; } else if (head == 1) { @@ -46,8 +49,14 @@ public void update() { } else { xpos -= 1; } + } - // TODO: draw a triangle to show the ant + /** + * Simulates one round of Langton's Ant. + */ + public void update() { + flipCell(); + moveAnt(); } /** From f267d4d27a714a5d98369400f421d3125702fef1 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Sun, 6 Oct 2019 01:20:30 -0400 Subject: [PATCH 24/52] added mainloop method --- ch15/Automaton.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ch15/Automaton.java b/ch15/Automaton.java index ae67edd..254bf68 100644 --- a/ch15/Automaton.java +++ b/ch15/Automaton.java @@ -29,8 +29,15 @@ public void run(String title, int rate) { frame.add(this.grid); frame.pack(); frame.setVisible(true); + this.mainloop(rate); + } - // main simulation loop + /** + * The simulation loop. + * + * @param rate frames per second + */ + private void mainloop(int rate) { while (true) { // update the drawing From 2a634e3712c7fcdd09a553a07e573605cc681e1f Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 7 Oct 2019 07:06:56 -0400 Subject: [PATCH 25/52] revised ch16 --- ch16/BlinkingPolygon.java | 2 +- ch16/{ColorPolygon.java => DrawablePolygon.java} | 8 ++++---- ch16/Drawing.bak | 14 +++++++------- ch16/RegularPolygon.java | 2 +- ch16/Sim1.java | 6 +++--- ch16/Sprite.java | 5 ++--- 6 files changed, 18 insertions(+), 19 deletions(-) rename ch16/{ColorPolygon.java => DrawablePolygon.java} (82%) diff --git a/ch16/BlinkingPolygon.java b/ch16/BlinkingPolygon.java index 118dcf6..9408309 100644 --- a/ch16/BlinkingPolygon.java +++ b/ch16/BlinkingPolygon.java @@ -34,8 +34,8 @@ public void step() { // toggle visibility every 10 steps count++; if (count == 10) { - count = 0; visible = !visible; + count = 0; } } diff --git a/ch16/ColorPolygon.java b/ch16/DrawablePolygon.java similarity index 82% rename from ch16/ColorPolygon.java rename to ch16/DrawablePolygon.java index 6db23a9..0efc8eb 100644 --- a/ch16/ColorPolygon.java +++ b/ch16/DrawablePolygon.java @@ -5,14 +5,14 @@ /** * Specialization of Polygon that has a color and the ability to draw itself. */ -public class ColorPolygon extends Polygon implements Actor { +public class DrawablePolygon extends Polygon implements Actor { - protected Color color; + public Color color; /** * Creates an empty polygon. */ - public ColorPolygon() { + public DrawablePolygon() { super(); color = Color.GRAY; } @@ -38,7 +38,7 @@ public void step() { * @param args command-line arguments */ public static void main(String[] args) { - ColorPolygon p = new ColorPolygon(); + DrawablePolygon p = new DrawablePolygon(); p.addPoint(57, 110); p.addPoint(100, 35); p.addPoint(143, 110); diff --git a/ch16/Drawing.bak b/ch16/Drawing.bak index 1acbc52..63ba8f9 100644 --- a/ch16/Drawing.bak +++ b/ch16/Drawing.bak @@ -25,10 +25,10 @@ public class Drawing extends Canvas { /** * Adds a new actor to the drawing. * - * @param cp the object to add + * @param dp the object to add */ - public void add(ColorPolygon cp) { - list.add(cp); + public void add(ColorPolygon dp) { + list.add(dp); } /** @@ -47,8 +47,8 @@ public class Drawing extends Canvas { */ @Override public void paint(Graphics g) { - for (ColorPolygon cp : list) { - cp.draw(g); + for (ColorPolygon dp : list) { + dp.draw(g); } } @@ -56,8 +56,8 @@ public class Drawing extends Canvas { * Calls the step method of each actor and updates the drawing. */ public void step() { - for (ColorPolygon cp : list) { - cp.step(); + for (ColorPolygon dp : list) { + dp.step(); } repaint(); } diff --git a/ch16/RegularPolygon.java b/ch16/RegularPolygon.java index 3ad566a..5aef2d3 100644 --- a/ch16/RegularPolygon.java +++ b/ch16/RegularPolygon.java @@ -4,7 +4,7 @@ * A polygon that is equiangular (all angles are equal in measure) and * equilateral (all sides have the same length). It also has a color. */ -public class RegularPolygon extends ColorPolygon { +public class RegularPolygon extends DrawablePolygon { public static final String[] NAMES = {null, null, null, "Triangle", "Square", "Pentagon", "Hexagon", diff --git a/ch16/Sim1.java b/ch16/Sim1.java index 2f747d2..019903e 100644 --- a/ch16/Sim1.java +++ b/ch16/Sim1.java @@ -14,9 +14,9 @@ public class Sim1 { public static void main(String[] args) { // create some regular polygons - ColorPolygon p1 = new RegularPolygon(3, 50, Color.GREEN); - ColorPolygon p2 = new RegularPolygon(6, 50, Color.ORANGE); - ColorPolygon p3 = new RegularPolygon(360, 50, Color.BLUE); + DrawablePolygon p1 = new RegularPolygon(3, 50, Color.GREEN); + DrawablePolygon p2 = new RegularPolygon(6, 50, Color.ORANGE); + DrawablePolygon p3 = new RegularPolygon(360, 50, Color.BLUE); // move them out of the corner p1.translate(100, 80); diff --git a/ch16/Sprite.java b/ch16/Sprite.java index 5835750..515408a 100644 --- a/ch16/Sprite.java +++ b/ch16/Sprite.java @@ -12,7 +12,6 @@ public class Sprite implements Actor, KeyListener { private Image image; - private int xpos; private int ypos; private int dx; @@ -26,10 +25,10 @@ public class Sprite implements Actor, KeyListener { * @param ypos initial Y coordinate */ public Sprite(String path, int xpos, int ypos) { + this.xpos = xpos; + this.ypos = ypos; try { this.image = ImageIO.read(new File(path)); - this.xpos = xpos; - this.ypos = ypos; } catch (IOException e) { e.printStackTrace(); } From 9cdeac14585447489666afa6276f4c8bcbb2e231 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 7 Oct 2019 21:07:19 -0400 Subject: [PATCH 26/52] ch15 feedback from Kevin --- appc/Drawing.java | 1 + appc/Mickey.java | 11 ++++++----- appc/Moire.java | 1 + ch15/Cell.java | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/appc/Drawing.java b/appc/Drawing.java index e82bfca..ef80672 100644 --- a/appc/Drawing.java +++ b/appc/Drawing.java @@ -6,6 +6,7 @@ public class Drawing extends Canvas { public static void main(String[] args) { JFrame frame = new JFrame("My Drawing"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Canvas drawing = new Drawing(); drawing.setSize(400, 400); frame.add(drawing); diff --git a/appc/Mickey.java b/appc/Mickey.java index 6dfa3bc..b303b20 100644 --- a/appc/Mickey.java +++ b/appc/Mickey.java @@ -8,6 +8,7 @@ public class Mickey extends Canvas { public static void main(String[] args) { JFrame frame = new JFrame("Mickey Mouse"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Canvas canvas = new Mickey(); canvas.setSize(400, 400); canvas.setBackground(Color.white); @@ -28,14 +29,14 @@ public void boxOval(Graphics g, Rectangle bb) { public void mickey(Graphics g, Rectangle bb) { boxOval(g, bb); - int dx = bb.width / 2; - int dy = bb.height / 2; - Rectangle half = new Rectangle(bb.x, bb.y, dx, dy); + int hx = bb.width / 2; + int hy = bb.height / 2; + Rectangle half = new Rectangle(bb.x, bb.y, hx, hy); - half.translate(-dx / 2, -dy / 2); + half.translate(-hx / 2, -hy / 2); boxOval(g, half); - half.translate(dx * 2, 0); + half.translate(hx * 2, 0); boxOval(g, half); } diff --git a/appc/Moire.java b/appc/Moire.java index 8e7247f..b736d97 100644 --- a/appc/Moire.java +++ b/appc/Moire.java @@ -7,6 +7,7 @@ public class Moire extends Canvas { public static void main(String[] args) { JFrame frame = new JFrame("Moire Pattern"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Canvas canvas = new Moire(); canvas.setSize(400, 400); canvas.setBackground(Color.white); diff --git a/ch15/Cell.java b/ch15/Cell.java index 7eecbe3..17e9987 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -33,7 +33,7 @@ public Cell(int x, int y, int size) { * @param g graphics context */ public void draw(Graphics g) { - g.setColor(COLORS[this.state]); + g.setColor(COLORS[state]); g.fillRect(x + 1, y + 1, size - 1, size - 1); g.setColor(Color.LIGHT_GRAY); g.drawRect(x, y, size, size); From c9f227aa3658f1c0c41dd16b5fa0bbd7209963be Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 8 Oct 2019 19:34:09 -0400 Subject: [PATCH 27/52] fix typos --- ch06/Strings.java | 2 +- ch09/Objects.java | 6 +++--- ch10/PointRect.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ch06/Strings.java b/ch06/Strings.java index e451db8..09b817f 100644 --- a/ch06/Strings.java +++ b/ch06/Strings.java @@ -1,5 +1,5 @@ /** - * Demonstates uses of Strings. + * Demonstrates uses of Strings. */ public class Strings { diff --git a/ch09/Objects.java b/ch09/Objects.java index 8bc4cc6..6dde3a0 100644 --- a/ch09/Objects.java +++ b/ch09/Objects.java @@ -1,7 +1,7 @@ import java.math.BigInteger; /** - * Demonstates uses of objects and wrappers. + * Demonstrates uses of objects and wrappers. */ public class Objects { @@ -24,8 +24,8 @@ public static void main(String[] args) { // Wrapper classes - Integer x = new Integer(123); - Integer y = new Integer(123); + Integer x = Integer.valueOf(123); + Integer y = Integer.valueOf(123); if (x == y) { // false System.out.println("x and y are the same object"); } diff --git a/ch10/PointRect.java b/ch10/PointRect.java index 66f94db..cb0af07 100644 --- a/ch10/PointRect.java +++ b/ch10/PointRect.java @@ -2,7 +2,7 @@ import java.awt.Rectangle; /** - * Demonstates use of Point and Rectangle classes. + * Demonstrates use of Point and Rectangle classes. */ public class PointRect { From 8e227a045dc741fe0458ff0646b34b909190c6ef Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 15 Jun 2020 13:19:23 -0400 Subject: [PATCH 28/52] update readme --- LICENSE | 2 +- README.md | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/LICENSE b/LICENSE index d3cee1c..c3838e3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Allen Downey and Chris Mayfield +Copyright (c) 2020 Allen Downey and Chris Mayfield Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 84689d7..a9646f6 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # ThinkJavaCode2 Supporting code for Think Java, 2nd edition. -Copyright (c) 2019 Allen Downey and Chris Mayfield. -**This new edition is a work in progress and won't be completed until Fall 2019.** +Copyright (c) 2020 Allen B. Downey and Chris Mayfield. +This edition was published in December 2019 by [O'Reilly Media](https://www.oreilly.com/library/view/think-java-2nd/9781492072492/) (ISBN 9781492072508). This repository contains the code examples from the book and starter code for some exercises. There are several ways you can work with the code: -* You can create a copy of this repository on GitHub by pressing the "Fork" button in the upper right. +* You can create a copy of this repository on GitHub by clicking the "Fork" button. If you don't already have a GitHub account, you'll need to create one. After forking, you'll have your own repository on GitHub that you can use to keep track of code you write. Then you can "clone" the repository, which downloads a copy of the files to your computer. @@ -14,7 +14,7 @@ Then you can "clone" the repository, which downloads a copy of the files to your * Alternatively, you could clone the original repository without forking. If you choose this option, you don't need a GitHub account, but you won't be able to save your changes on GitHub. -* If you don't want to use Git at all, you can download the code in a ZIP archive using the "Download ZIP" button on this page, or this link: http://tinyurl.com/ThinkJavaCode2. +* If you don't want to use Git at all, you can download the code in a ZIP archive using the "Clone or download" button, or this link: https://thinkjava.org/code2zip. To clone a repository, you need Git installed on your computer (see https://help.github.com/). If you use Git from the command line, you can clone the original repository like this: @@ -23,6 +23,7 @@ If you use Git from the command line, you can clone the original repository like After you clone the repository or unzip the ZIP file, you should have a directory named `ThinkJavaCode2` with a subdirectory for each chapter in the book. -All examples in this book were developed and tested using Java SE Development Kit 8. -If you are using a more recent version, the examples in this book should still work. -If you are using an older version, some of them may not. +The examples in this book were developed and tested using OpenJDK 11. +If you are using a more recent version, everything should still work. +If you are using an older version, some of the examples might not. + From 15b6389a1eeeae4e07e75a426efffef5ed36144f Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 15 Jun 2020 13:34:11 -0400 Subject: [PATCH 29/52] moved appe and misc to ThinkJava2 --- appe/.checkstyle | 8 ----- appe/.classpath | 6 ---- appe/.project | 23 -------------- appe/Tables.java | 45 --------------------------- appe/Unreachable.java | 16 ---------- appe/Validate.java | 54 --------------------------------- appe/Vowels.java | 46 ---------------------------- misc/.checkstyle | 8 ----- misc/.classpath | 7 ----- misc/.project | 23 -------------- misc/Point.java | 69 ------------------------------------------ misc/PointTest.java | 45 --------------------------- misc/Pose.java | 34 --------------------- misc/PoseTest.java | 34 --------------------- misc/Triangle.java | 53 -------------------------------- misc/TriangleTest.java | 28 ----------------- 16 files changed, 499 deletions(-) delete mode 100644 appe/.checkstyle delete mode 100644 appe/.classpath delete mode 100644 appe/.project delete mode 100644 appe/Tables.java delete mode 100644 appe/Unreachable.java delete mode 100644 appe/Validate.java delete mode 100644 appe/Vowels.java delete mode 100644 misc/.checkstyle delete mode 100644 misc/.classpath delete mode 100644 misc/.project delete mode 100644 misc/Point.java delete mode 100644 misc/PointTest.java delete mode 100644 misc/Pose.java delete mode 100644 misc/PoseTest.java delete mode 100644 misc/Triangle.java delete mode 100644 misc/TriangleTest.java diff --git a/appe/.checkstyle b/appe/.checkstyle deleted file mode 100644 index 744b9f9..0000000 --- a/appe/.checkstyle +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/appe/.classpath b/appe/.classpath deleted file mode 100644 index 3f3893a..0000000 --- a/appe/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/appe/.project b/appe/.project deleted file mode 100644 index 0932ca3..0000000 --- a/appe/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - appe - - - - - - org.eclipse.jdt.core.javabuilder - - - - - net.sf.eclipsecs.core.CheckstyleBuilder - - - - - - org.eclipse.jdt.core.javanature - net.sf.eclipsecs.core.CheckstyleNature - - diff --git a/appe/Tables.java b/appe/Tables.java deleted file mode 100644 index edade81..0000000 --- a/appe/Tables.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Generating tables. - */ -public class Tables { - - public static void example() { - int i = 1; - while (i < 10) { - double x = i; - System.out.println(x + " " + Math.log(x)); - i = i + 1; - } - } - - public static void example2() { - int i = 1; - while (i < 10) { - double x = i; - System.out.println(x + " " + Math.log(x) / Math.log(2)); - i = i + 1; - } - } - - public static void example3() { - final double LOG2 = Math.log(2); - int i = 1; - while (i < 100) { - double x = i; - System.out.println(x + " " + Math.log(x) / LOG2); - i = i * 2; - } - } - - public static void main(String[] args) { - System.out.println("example"); - example(); - - System.out.println("example2"); - example2(); - - System.out.println("example3"); - example3(); - } - -} diff --git a/appe/Unreachable.java b/appe/Unreachable.java deleted file mode 100644 index 7749dd3..0000000 --- a/appe/Unreachable.java +++ /dev/null @@ -1,16 +0,0 @@ -public class Unreachable { - - public static double absoluteValue(double x) { - if (x < 0) { - return -x; - } else { - return x; - } - } - - public static void main(String[] args) { - System.out.println("absolute value"); - System.out.println(absoluteValue(-2)); - } - -} diff --git a/appe/Validate.java b/appe/Validate.java deleted file mode 100644 index e825705..0000000 --- a/appe/Validate.java +++ /dev/null @@ -1,54 +0,0 @@ -import java.util.Scanner; - -/** - * Do-while, break, and continue. - */ -public class Validate { - - public static double scanDouble() { - Scanner in = new Scanner(System.in); - boolean okay; - do { - System.out.print("Enter a number: "); - if (in.hasNextDouble()) { - okay = true; - } else { - okay = false; - String word = in.next(); - System.err.println(word + " is not a number"); - } - } while (!okay); - double x = in.nextDouble(); - return x; - } - - public static double scanDouble2() { - Scanner in = new Scanner(System.in); - while (true) { - System.out.print("Enter a number: "); - if (in.hasNextDouble()) { - break; - } - String word = in.next(); - System.err.println(word + " is not a number"); - } - double x = in.nextDouble(); - return x; - } - - public static double addNumbers() { - Scanner in = new Scanner(System.in); - int x = -1; - int sum = 0; - while (x != 0) { - x = in.nextInt(); - if (x <= 0) { - continue; - } - System.out.println("Adding " + x); - sum += x; - } - return sum; - } - -} diff --git a/appe/Vowels.java b/appe/Vowels.java deleted file mode 100644 index 4b01b58..0000000 --- a/appe/Vowels.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Example switch statement with cases that fall through. - */ -public class Vowels { - - public static void main(String[] args) { - String s = "Ahoy!"; - for (int i = 0; i < s.length(); i++) { - - // display the next character - char c = s.charAt(i); - System.out.print(c + " is a "); - - // if capital, convert to lowercase - if (c >= 'A' && c <= 'Z') { - c += 'a' - 'A'; - } - - // check if not a lowercase letter - if (c < 'a' || c > 'z') { - System.out.println("symbol"); - continue; - } - - // output the result of the letter - switch (c) { - case 'a': - case 'e': - case 'i': - case 'o': - case 'u': - System.out.println("vowel"); - break; - - case 'y': - System.out.println("not sure"); - break; - - default: - System.out.println("consonant"); - break; - } - } - } - -} diff --git a/misc/.checkstyle b/misc/.checkstyle deleted file mode 100644 index 744b9f9..0000000 --- a/misc/.checkstyle +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/misc/.classpath b/misc/.classpath deleted file mode 100644 index 83091d5..0000000 --- a/misc/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/misc/.project b/misc/.project deleted file mode 100644 index 4ed6818..0000000 --- a/misc/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - misc - - - - - - org.eclipse.jdt.core.javabuilder - - - - - net.sf.eclipsecs.core.CheckstyleBuilder - - - - - - org.eclipse.jdt.core.javanature - net.sf.eclipsecs.core.CheckstyleNature - - diff --git a/misc/Point.java b/misc/Point.java deleted file mode 100644 index 5447d0c..0000000 --- a/misc/Point.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * An immutable point in two-dimensional space. - */ -public class Point { - - public static final double DELTA = 0.001; - - private final double x; - private final double y; - - /** - * Constructs a point at the given location. - * - * @param x the X coordinate - * @param y the Y coordinate - */ - public Point(double x, double y) { - this.x = x; - this.y = y; - } - - /** - * @return the X coordinate - */ - public double getX() { - return x; - } - - /** - * @return the Y coordinate - */ - public double getY() { - return y; - } - - /** - * Computes the distance between two points. - * - * @param pt the other point - * @return Euclidean distance - */ - public double distance(Point pt) { - double dx = this.x - pt.x; - double dy = this.y - pt.y; - return Math.sqrt(dx * dx + dy * dy); - } - - /** - * Determines whether or not two points are equal. - * - * @param obj the other point - * @return true if this equals obj - */ - public boolean equals(Object obj) { - if (obj instanceof Point) { - Point pt = (Point) obj; - return distance(pt) < DELTA; - } - return super.equals(obj); - } - - /** - * @return string representation of the point - */ - public String toString() { - return String.format("(%.1f, %.1f)", this.x, this.y); - } - -} diff --git a/misc/PointTest.java b/misc/PointTest.java deleted file mode 100644 index fd683dc..0000000 --- a/misc/PointTest.java +++ /dev/null @@ -1,45 +0,0 @@ -import static org.junit.Assert.*; -import org.junit.Test; - -/** - * Tests the Point class. - */ -public class PointTest { - - /** - * Tests the distance method. - */ - @Test - public void testDistance() { - Point p1 = new Point(0, 0); - Point p2 = new Point(3, 4); - assertEquals(0.0, p1.distance(p1), Point.DELTA); - assertEquals(5.0, p1.distance(p2), Point.DELTA); - } - - /** - * Tests the equals method. - */ - @Test - public void testEquals() { - Point p1 = new Point(0, 0); - Point p2 = new Point(0, 0); - Point p3 = new Point(3, 4); - Point p4 = new Point(3, 5); - assertTrue(p1.equals(p2)); - assertFalse(p2.equals(p3)); - assertFalse(p3.equals(p4)); - } - - /** - * Tests the toString method. - */ - @Test - public void testToString() { - Point p1 = new Point(0, 0); - Point p2 = new Point(3, 4); - assertEquals("(0.0, 0.0)", p1.toString()); - assertEquals("(3.0, 4.0)", p2.toString()); - } - -} diff --git a/misc/Pose.java b/misc/Pose.java deleted file mode 100644 index 03fdee4..0000000 --- a/misc/Pose.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * A point with an associated heading (in degrees). - */ -public class Pose extends Point { - - private final double heading; - - /** - * Constructs a pose at the given location. - * - * @param x the X coordinate - * @param y the Y coordinate - * @param heading the heading - */ - public Pose(double x, double y, double heading) { - super(x, y); - this.heading = heading; - } - - /** - * @return heading the heading - */ - public double getHeading() { - return heading; - } - - /** - * @return string representation of the pose - */ - public String toString() { - return String.format("%s @%.1f", super.toString(), this.heading); - } - -} diff --git a/misc/PoseTest.java b/misc/PoseTest.java deleted file mode 100644 index 00c1b0f..0000000 --- a/misc/PoseTest.java +++ /dev/null @@ -1,34 +0,0 @@ -import static org.junit.Assert.*; -import org.junit.Test; - -/** - * Tests the Pose class. - */ -public class PoseTest { - - /** - * Tests the equals method. - */ - @Test - public void testEquals() { - Pose p1 = new Pose(1, 3, 0); - Pose p2 = new Pose(1, 3, 45); - Pose p3 = new Pose(5, 7, 45); - Point p4 = new Point(5, 7); - assertTrue(p1.equals(p2)); - assertFalse(p2.equals(p3)); - assertTrue(p3.equals(p4)); - } - - /** - * Tests the toString method. - */ - @Test - public void testToString() { - Pose p1 = new Pose(1, 3, 45); - Pose p2 = new Pose(5, 7, 90); - assertEquals("(1.0, 3.0) @45.0", p1.toString()); - assertEquals("(5.0, 7.0) @90.0", p2.toString()); - } - -} diff --git a/misc/Triangle.java b/misc/Triangle.java deleted file mode 100644 index 1b89467..0000000 --- a/misc/Triangle.java +++ /dev/null @@ -1,53 +0,0 @@ -import java.awt.Polygon; - -/** - * A three-sided polygon. - */ -public class Triangle extends Polygon { - - /** - * Constructs a triangle at the given points. - * - * @param ax 1st x-coordinate - * @param ay 1st y-coordinate - * @param bx 2nd x-coordinate - * @param by 2nd y-coordinate - * @param cx 3rd x-coordinate - * @param cy 3rd y-coordinate - */ - public Triangle(int ax, int ay, int bx, int by, int cx, int cy) { - - // check for invalid triangle - int lhs = (cy - by) * (bx - ax); - int rhs = (by - ay) * (cx - bx); - if (lhs == rhs) { - throw new IllegalArgumentException("points are collinear"); - } - - // store points of polygon - xpoints = new int[] {ax, bx, cx}; - ypoints = new int[] {ay, by, cy}; - npoints = 3; - } - - /** - * @return string representation of the triangle - */ - public String toString() { - StringBuilder str = new StringBuilder(); - str.append("Triangle["); - for (int i = 0; i < npoints; i++) { - if (i > 0) { - str.append(", "); - } - // append the next (x, y) point - str.append('('); - str.append(xpoints[i]); - str.append(", "); - str.append(ypoints[i]); - str.append(')'); - } - str.append(']'); - return str.toString(); - } -} diff --git a/misc/TriangleTest.java b/misc/TriangleTest.java deleted file mode 100644 index ff86076..0000000 --- a/misc/TriangleTest.java +++ /dev/null @@ -1,28 +0,0 @@ -import static org.junit.Assert.*; -import org.junit.Test; - -/** - * Tests the Triangle class. - */ -public class TriangleTest { - - /** - * Tests an invalid triangle. - */ - @Test(expected = IllegalArgumentException.class) - public void testCollinear() { - // straight line along the X-axis - new Triangle(0, 0, 1, 0, 2, 0); - } - - /** - * Tests the toString method. - */ - @Test - public void testToString() { - // 3-4-5 right triangle at origin - Triangle t = new Triangle(0, 0, 0, 3, 4, 0); - assertEquals("Triangle[(0, 0), (0, 3), (4, 0)]", t.toString()); - } - -} From 3e9b0a3f3f7c00ce124d219b16a1819142c8af32 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 15 Jun 2020 14:03:21 -0400 Subject: [PATCH 30/52] ch12 revisions --- ch12/CardTable.java | 7 ++++--- ch12/Search.java | 26 -------------------------- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/ch12/CardTable.java b/ch12/CardTable.java index 727d307..5e85686 100644 --- a/ch12/CardTable.java +++ b/ch12/CardTable.java @@ -15,11 +15,13 @@ public class CardTable extends Canvas { * Creates a CardTable. * cardset is the name of the folder that contains the card images. */ - public CardTable(String cardset) { + public CardTable() { setBackground(new Color(0x088A4B)); // create a 2-D array of card images images = new Image[14][4]; + + String cardset = "cardset-oxymoron"; String suits = "cdhs"; for (int suit = 0; suit <= 3; suit++) { @@ -81,8 +83,7 @@ public static void main(String[] args) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // add the CardTable - String cardset = "cardset-oxymoron"; - Canvas canvas = new CardTable(cardset); + Canvas canvas = new CardTable(); frame.getContentPane().add(canvas); // show the frame diff --git a/ch12/Search.java b/ch12/Search.java index 8bd3129..dd81ed0 100644 --- a/ch12/Search.java +++ b/ch12/Search.java @@ -62,28 +62,6 @@ public static int binarySearch(Card[] cards, Card target) { return -1; } - /** - * Binary search (recursive version). - */ - public static int binarySearch(Card[] cards, Card target, - int low, int high) { - System.out.println(low + ", " + high); - - if (high < low) { - return -1; - } - int mid = (low + high) / 2; // step 1 - int comp = cards[mid].compareTo(target); - - if (comp == 0) { // step 2 - return mid; - } else if (comp < 0) { // step 3 - return binarySearch(cards, target, mid + 1, high); - } else { // step 4 - return binarySearch(cards, target, low, mid - 1); - } - } - /** * Demonstrates how to call the search methods. */ @@ -103,10 +81,6 @@ public static void main(String[] args) { System.out.println("Failed binary search"); System.out.println(binarySearch(cards, fake)); System.out.println(); - - System.out.println("Recursive binary search"); - System.out.println(binarySearch(cards, jack, 0, 51)); - System.out.println(); } } From b98cbcd766b9885f4cd4b68e762ed8104fa1311c Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 15 Jun 2020 14:44:36 -0400 Subject: [PATCH 31/52] ch13 revisions --- Checkstyle.xml | 9 +++------ ch13/Deck.java | 14 ++++++++++++-- ch13/Pile.java | 12 ++++++------ ch13/War.java | 4 ++-- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Checkstyle.xml b/Checkstyle.xml index 0b55302..367b3fe 100644 --- a/Checkstyle.xml +++ b/Checkstyle.xml @@ -62,14 +62,11 @@ Checkstyle configuration for Think Java, 2nd Edition. - - - - + + diff --git a/ch13/Deck.java b/ch13/Deck.java index 0c32929..25b2912 100644 --- a/ch13/Deck.java +++ b/ch13/Deck.java @@ -1,4 +1,3 @@ -import java.util.Arrays; import java.util.Random; /** @@ -6,6 +5,10 @@ */ public class Deck { + // This is a class variable so we don't have to create + // a new Random object every time we call randomInt. + private static Random random = new Random(); + private Card[] cards; /** @@ -49,7 +52,7 @@ public void print() { * Returns a string representation of the deck. */ public String toString() { - return Arrays.toString(this.cards); + return "TODO"; } /** @@ -122,4 +125,11 @@ public Deck mergeSort() { */ public void insertionSort() { } + + /** + * Helper method for insertion sort. + */ + private void insert(Card card, int i) { + } + } diff --git a/ch13/Pile.java b/ch13/Pile.java index 1b6bdab..1df5cdc 100644 --- a/ch13/Pile.java +++ b/ch13/Pile.java @@ -31,17 +31,17 @@ public void addDeck(Deck deck) { } /** - * Removes a card from the top of the pile. + * Returns true if this pile has no cards. */ - public Card popCard() { - return this.cards.remove(0); + public boolean isEmpty() { + return this.cards.isEmpty(); } /** - * Returns the number of cards in the pile. + * Removes a card from the top of the pile. */ - public int size() { - return this.cards.size(); + public Card popCard() { + return this.cards.remove(0); } } diff --git a/ch13/War.java b/ch13/War.java index 7639f1d..d9e9c04 100644 --- a/ch13/War.java +++ b/ch13/War.java @@ -16,7 +16,7 @@ public static void main(String[] args) { p2.addDeck(deck.subdeck(26, 51)); // while both piles are not empty - while (p1.size() > 0 && p2.size() > 0) { + while (!p1.isEmpty() && !p2.isEmpty()) { Card c1 = p1.popCard(); Card c2 = p2.popCard(); @@ -34,7 +34,7 @@ public static void main(String[] args) { } // display the winner - if (p1.size() > 0) { + if (p2.isEmpty()) { System.out.println("Player 1 wins!"); } else { System.out.println("Player 2 wins!"); From 90f4b04e758917894cc20d7a6c68c33a368129ef Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 15 Jun 2020 15:45:03 -0400 Subject: [PATCH 32/52] ch14 revisions --- Checkstyle.xml | 4 --- ch14/CardCollection.java | 60 ++++++++++++++++++++-------------------- ch14/Eights.java | 15 ++++------ ch14/Player.java | 13 ++------- 4 files changed, 39 insertions(+), 53 deletions(-) diff --git a/Checkstyle.xml b/Checkstyle.xml index 367b3fe..75ad255 100644 --- a/Checkstyle.xml +++ b/Checkstyle.xml @@ -43,7 +43,6 @@ Checkstyle configuration for Think Java, 2nd Edition. --> - @@ -62,9 +61,6 @@ Checkstyle configuration for Think Java, 2nd Edition. - diff --git a/ch14/CardCollection.java b/ch14/CardCollection.java index 9e65d39..bf00cde 100644 --- a/ch14/CardCollection.java +++ b/ch14/CardCollection.java @@ -24,6 +24,13 @@ public String getLabel() { return label; } + /** + * Returns a string representation of the card collection. + */ + public String toString() { + return label + ": " + cards.toString(); + } + /** * Adds the given card to the collection. */ @@ -42,40 +49,22 @@ public Card popCard(int i) { * Removes and returns the last card. */ public Card popCard() { - int i = size() - 1; + int i = cards.size() - 1; // from the end of the list return popCard(i); } - /** - * Returns the number of cards. - */ - public int size() { - return cards.size(); - } - /** * True if the collection is empty, false otherwise. */ - public boolean empty() { - return cards.size() == 0; - } - - /** - * Moves n cards from this collection to the given collection. - */ - public void deal(CardCollection that, int n) { - for (int i = 0; i < n; i++) { - Card card = popCard(); - that.addCard(card); - } + public boolean isEmpty() { + return cards.isEmpty(); } /** - * Moves all remaining cards to the given collection. + * Returns the number of cards. */ - public void dealAll(CardCollection that) { - int n = size(); - deal(that, n); + public int size() { + return cards.size(); } /** @@ -89,7 +78,7 @@ public Card getCard(int i) { * Returns the last card. */ public Card lastCard() { - int i = size() - 1; + int i = cards.size() - 1; return cards.get(i); } @@ -107,17 +96,28 @@ public void swapCards(int i, int j) { */ public void shuffle() { Random random = new Random(); - for (int i = size() - 1; i > 0; i--) { - int j = random.nextInt(i); + for (int i = cards.size() - 1; i > 0; i--) { + int j = random.nextInt(i + 1); swapCards(i, j); } } /** - * Returns a string representation of the card collection. + * Moves n cards from this collection to the given collection. */ - public String toString() { - return label + ": " + cards.toString(); + public void deal(CardCollection that, int n) { + for (int i = 0; i < n; i++) { + Card card = popCard(); + that.addCard(card); + } + } + + /** + * Moves all remaining cards to the given collection. + */ + public void dealAll(CardCollection that) { + int n = cards.size(); + deal(that, n); } } diff --git a/ch14/Eights.java b/ch14/Eights.java index 9bc0433..c5d5aea 100644 --- a/ch14/Eights.java +++ b/ch14/Eights.java @@ -1,9 +1,8 @@ import java.util.Scanner; /** - * Simulates a game of Crazy Eights. See - * https://en.wikipedia.org/wiki/Crazy_Eights - * for basic play and scoring rules. + * Simulates a game of Crazy Eights. + * See https://en.wikipedia.org/wiki/Crazy_Eights. */ public class Eights { @@ -21,12 +20,10 @@ public Eights() { deck.shuffle(); // deal cards to each player - int handSize = 5; one = new Player("Allen"); - deck.deal(one.getHand(), handSize); - + deck.deal(one.getHand(), 5); two = new Player("Chris"); - deck.deal(two.getHand(), handSize); + deck.deal(two.getHand(), 5); // turn one card face up discardPile = new Hand("Discards"); @@ -44,7 +41,7 @@ public Eights() { * Returns true if either hand is empty. */ public boolean isDone() { - return one.getHand().empty() || two.getHand().empty(); + return one.getHand().isEmpty() || two.getHand().isEmpty(); } /** @@ -68,7 +65,7 @@ public void reshuffle() { * Returns a card from the draw pile. */ public Card drawCard() { - if (drawPile.empty()) { + if (drawPile.isEmpty()) { reshuffle(); } return drawPile.popCard(); diff --git a/ch14/Player.java b/ch14/Player.java index 97870da..aec1394 100644 --- a/ch14/Player.java +++ b/ch14/Player.java @@ -70,16 +70,9 @@ public Card drawForMatch(Eights eights, Card prev) { * Checks whether two cards match. */ public static boolean cardMatches(Card card1, Card card2) { - if (card1.getSuit() == card2.getSuit()) { - return true; - } - if (card1.getRank() == card2.getRank()) { - return true; - } - if (card1.getRank() == 8) { - return true; - } - return false; + return card1.getSuit() == card2.getSuit() + || card1.getRank() == card2.getRank() + || card1.getRank() == 8; } /** From a2e4c003b672525ac0b1a0a502897bc092ff9901 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 16 Jun 2020 11:38:58 -0400 Subject: [PATCH 33/52] rename ch16 to ch17 --- {ch16 => ch17}/.checkstyle | 0 {ch16 => ch17}/.classpath | 0 {ch16 => ch17}/.project | 2 +- {ch16 => ch17}/Actor.java | 0 {ch16 => ch17}/BlinkingPolygon.java | 0 {ch16 => ch17}/DrawablePolygon.java | 0 {ch16 => ch17}/Drawing.bak | 0 {ch16 => ch17}/Drawing.java | 0 {ch16 => ch17}/Mole.java | 0 {ch16 => ch17}/MoleHill.java | 0 {ch16 => ch17}/MovingPolygon.java | 0 {ch16 => ch17}/RegularPolygon.java | 0 {ch16 => ch17}/RotatingPolygon.java | 0 {ch16 => ch17}/Sim1.java | 0 {ch16 => ch17}/Sim2.java | 0 {ch16 => ch17}/Sim3.java | 0 {ch16 => ch17}/Sprite.java | 0 {ch16 => ch17}/VideoGame.java | 0 {ch16 => ch17}/WhackAMole.java | 0 {ch16 => ch17}/face-smile.png | Bin {ch16 => ch17}/face-smile.svg | 0 {ch16 => ch17}/face-smile.txt | 0 22 files changed, 1 insertion(+), 1 deletion(-) rename {ch16 => ch17}/.checkstyle (100%) rename {ch16 => ch17}/.classpath (100%) rename {ch16 => ch17}/.project (96%) rename {ch16 => ch17}/Actor.java (100%) rename {ch16 => ch17}/BlinkingPolygon.java (100%) rename {ch16 => ch17}/DrawablePolygon.java (100%) rename {ch16 => ch17}/Drawing.bak (100%) rename {ch16 => ch17}/Drawing.java (100%) rename {ch16 => ch17}/Mole.java (100%) rename {ch16 => ch17}/MoleHill.java (100%) rename {ch16 => ch17}/MovingPolygon.java (100%) rename {ch16 => ch17}/RegularPolygon.java (100%) rename {ch16 => ch17}/RotatingPolygon.java (100%) rename {ch16 => ch17}/Sim1.java (100%) rename {ch16 => ch17}/Sim2.java (100%) rename {ch16 => ch17}/Sim3.java (100%) rename {ch16 => ch17}/Sprite.java (100%) rename {ch16 => ch17}/VideoGame.java (100%) rename {ch16 => ch17}/WhackAMole.java (100%) rename {ch16 => ch17}/face-smile.png (100%) rename {ch16 => ch17}/face-smile.svg (100%) rename {ch16 => ch17}/face-smile.txt (100%) diff --git a/ch16/.checkstyle b/ch17/.checkstyle similarity index 100% rename from ch16/.checkstyle rename to ch17/.checkstyle diff --git a/ch16/.classpath b/ch17/.classpath similarity index 100% rename from ch16/.classpath rename to ch17/.classpath diff --git a/ch16/.project b/ch17/.project similarity index 96% rename from ch16/.project rename to ch17/.project index ae6ca3f..7010276 100644 --- a/ch16/.project +++ b/ch17/.project @@ -1,6 +1,6 @@ - ch16 + ch17 diff --git a/ch16/Actor.java b/ch17/Actor.java similarity index 100% rename from ch16/Actor.java rename to ch17/Actor.java diff --git a/ch16/BlinkingPolygon.java b/ch17/BlinkingPolygon.java similarity index 100% rename from ch16/BlinkingPolygon.java rename to ch17/BlinkingPolygon.java diff --git a/ch16/DrawablePolygon.java b/ch17/DrawablePolygon.java similarity index 100% rename from ch16/DrawablePolygon.java rename to ch17/DrawablePolygon.java diff --git a/ch16/Drawing.bak b/ch17/Drawing.bak similarity index 100% rename from ch16/Drawing.bak rename to ch17/Drawing.bak diff --git a/ch16/Drawing.java b/ch17/Drawing.java similarity index 100% rename from ch16/Drawing.java rename to ch17/Drawing.java diff --git a/ch16/Mole.java b/ch17/Mole.java similarity index 100% rename from ch16/Mole.java rename to ch17/Mole.java diff --git a/ch16/MoleHill.java b/ch17/MoleHill.java similarity index 100% rename from ch16/MoleHill.java rename to ch17/MoleHill.java diff --git a/ch16/MovingPolygon.java b/ch17/MovingPolygon.java similarity index 100% rename from ch16/MovingPolygon.java rename to ch17/MovingPolygon.java diff --git a/ch16/RegularPolygon.java b/ch17/RegularPolygon.java similarity index 100% rename from ch16/RegularPolygon.java rename to ch17/RegularPolygon.java diff --git a/ch16/RotatingPolygon.java b/ch17/RotatingPolygon.java similarity index 100% rename from ch16/RotatingPolygon.java rename to ch17/RotatingPolygon.java diff --git a/ch16/Sim1.java b/ch17/Sim1.java similarity index 100% rename from ch16/Sim1.java rename to ch17/Sim1.java diff --git a/ch16/Sim2.java b/ch17/Sim2.java similarity index 100% rename from ch16/Sim2.java rename to ch17/Sim2.java diff --git a/ch16/Sim3.java b/ch17/Sim3.java similarity index 100% rename from ch16/Sim3.java rename to ch17/Sim3.java diff --git a/ch16/Sprite.java b/ch17/Sprite.java similarity index 100% rename from ch16/Sprite.java rename to ch17/Sprite.java diff --git a/ch16/VideoGame.java b/ch17/VideoGame.java similarity index 100% rename from ch16/VideoGame.java rename to ch17/VideoGame.java diff --git a/ch16/WhackAMole.java b/ch17/WhackAMole.java similarity index 100% rename from ch16/WhackAMole.java rename to ch17/WhackAMole.java diff --git a/ch16/face-smile.png b/ch17/face-smile.png similarity index 100% rename from ch16/face-smile.png rename to ch17/face-smile.png diff --git a/ch16/face-smile.svg b/ch17/face-smile.svg similarity index 100% rename from ch16/face-smile.svg rename to ch17/face-smile.svg diff --git a/ch16/face-smile.txt b/ch17/face-smile.txt similarity index 100% rename from ch16/face-smile.txt rename to ch17/face-smile.txt From ce25adb91409898b344e834df499b571dcea7770 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 16 Jun 2020 12:16:58 -0400 Subject: [PATCH 34/52] split ch15 into ch16 --- ch16/.checkstyle | 8 ++++++++ ch16/.classpath | 6 ++++++ ch16/.project | 23 +++++++++++++++++++++++ {ch15 => ch16}/Automaton.java | 0 ch16/Cell.java | 1 + {ch15 => ch16}/Conway.java | 0 ch16/GridCanvas.java | 1 + {ch15 => ch16}/Langton.java | 0 8 files changed, 39 insertions(+) create mode 100644 ch16/.checkstyle create mode 100644 ch16/.classpath create mode 100644 ch16/.project rename {ch15 => ch16}/Automaton.java (100%) create mode 120000 ch16/Cell.java rename {ch15 => ch16}/Conway.java (100%) create mode 120000 ch16/GridCanvas.java rename {ch15 => ch16}/Langton.java (100%) diff --git a/ch16/.checkstyle b/ch16/.checkstyle new file mode 100644 index 0000000..744b9f9 --- /dev/null +++ b/ch16/.checkstyle @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ch16/.classpath b/ch16/.classpath new file mode 100644 index 0000000..3f3893a --- /dev/null +++ b/ch16/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/ch16/.project b/ch16/.project new file mode 100644 index 0000000..ae6ca3f --- /dev/null +++ b/ch16/.project @@ -0,0 +1,23 @@ + + + ch16 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + net.sf.eclipsecs.core.CheckstyleBuilder + + + + + + org.eclipse.jdt.core.javanature + net.sf.eclipsecs.core.CheckstyleNature + + diff --git a/ch15/Automaton.java b/ch16/Automaton.java similarity index 100% rename from ch15/Automaton.java rename to ch16/Automaton.java diff --git a/ch16/Cell.java b/ch16/Cell.java new file mode 120000 index 0000000..1e0bc1b --- /dev/null +++ b/ch16/Cell.java @@ -0,0 +1 @@ +../ch15/Cell.java \ No newline at end of file diff --git a/ch15/Conway.java b/ch16/Conway.java similarity index 100% rename from ch15/Conway.java rename to ch16/Conway.java diff --git a/ch16/GridCanvas.java b/ch16/GridCanvas.java new file mode 120000 index 0000000..6711096 --- /dev/null +++ b/ch16/GridCanvas.java @@ -0,0 +1 @@ +../ch15/GridCanvas.java \ No newline at end of file diff --git a/ch15/Langton.java b/ch16/Langton.java similarity index 100% rename from ch15/Langton.java rename to ch16/Langton.java From be6bb5433e3f7247eab792e512c0fd078989c4d2 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 16 Jun 2020 13:58:04 -0400 Subject: [PATCH 35/52] ch15 revisions --- ch15/Cell.java | 1 + ch15/Conway.java | 148 ++++++++++++++++++++++++++++++++++++++++++++ ch15/empty.cells | 11 ---- ch15/pulsar.cells | 17 ----- ch16/Automaton.java | 2 - ch16/Conway.java | 77 +++-------------------- 6 files changed, 157 insertions(+), 99 deletions(-) create mode 100644 ch15/Conway.java delete mode 100644 ch15/empty.cells delete mode 100644 ch15/pulsar.cells diff --git a/ch15/Cell.java b/ch15/Cell.java index 17e9987..d468b6d 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -66,4 +66,5 @@ public void turnOff() { public void turnOn() { state = 1; } + } diff --git a/ch15/Conway.java b/ch15/Conway.java new file mode 100644 index 0000000..93faf28 --- /dev/null +++ b/ch15/Conway.java @@ -0,0 +1,148 @@ +import javax.swing.JFrame; + +/** + * Conway's Game of Life. + */ +public class Conway { + + private GridCanvas grid; + + /** + * Creates a grid with two Blinkers. + */ + public Conway() { + grid = new GridCanvas(5, 10, 20); + grid.turnOn(2, 1); + grid.turnOn(2, 2); + grid.turnOn(2, 3); + grid.turnOn(1, 7); + grid.turnOn(2, 7); + grid.turnOn(3, 7); + } + + /** + * Counts the number of live neighbors around a cell. + * + * @param r row index + * @param c column index + * @return number of live neighbors + */ + private int countAlive(int r, int c) { + int count = 0; + count += grid.test(r - 1, c - 1); + count += grid.test(r - 1, c); + count += grid.test(r - 1, c + 1); + count += grid.test(r, c - 1); + count += grid.test(r, c + 1); + count += grid.test(r + 1, c - 1); + count += grid.test(r + 1, c); + count += grid.test(r + 1, c + 1); + return count; + } + + /** + * Apply the update rules of Conway's Game of Life. + * + * @param cell the cell to update + * @param count number of live neighbors + */ + private static void updateCell(Cell cell, int count) { + if (cell.isOn()) { + if (count < 2 || count > 3) { + // Any live cell with fewer than two live neighbors dies, + // as if by underpopulation. + // Any live cell with more than three live neighbors dies, + // as if by overpopulation. + cell.turnOff(); + } + } else { + if (count == 3) { + // Any dead cell with exactly three live neighbors + // becomes a live cell, as if by reproduction. + cell.turnOn(); + } + } + } + + /** + * Counts the neighbors before changing anything. + * + * @return number of neighbors for each cell + */ + private int[][] countNeighbors() { + int rows = grid.numRows(); + int cols = grid.numCols(); + + int[][] counts = new int[rows][cols]; + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + counts[r][c] = countAlive(r, c); + } + } + return counts; + } + + /** + * Updates each cell based on neighbor counts. + * + * @param counts number of neighbors for each cell + */ + private void updateGrid(int[][] counts) { + int rows = grid.numRows(); + int cols = grid.numCols(); + + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + Cell cell = grid.getCell(r, c); + updateCell(cell, counts[r][c]); + } + } + } + + /** + * Simulates one round of Conway's Game of Life. + */ + public void update() { + int[][] counts = countNeighbors(); + updateGrid(counts); + } + + /** + * The simulation loop. + * + * @param rate frames per second + */ + private void mainloop() { + while (true) { + + // update the drawing + this.update(); + grid.repaint(); + + // delay the simulation + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // do nothing + } + } + } + + /** + * Creates and runs the simulation. + * + * @param args command-line arguments + */ + public static void main(String[] args) { + String title = "Conway's Game of Life"; + Conway game = new Conway(); + JFrame frame = new JFrame(title); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.add(game.grid); + frame.pack(); + frame.setVisible(true); + game.mainloop(); + } + +} diff --git a/ch15/empty.cells b/ch15/empty.cells deleted file mode 100644 index add6d90..0000000 --- a/ch15/empty.cells +++ /dev/null @@ -1,11 +0,0 @@ -!An empty 10x10 grid -.......... -.......... -.......... -.......... -.......... -.......... -.......... -.......... -.......... -.......... diff --git a/ch15/pulsar.cells b/ch15/pulsar.cells deleted file mode 100644 index 19eda57..0000000 --- a/ch15/pulsar.cells +++ /dev/null @@ -1,17 +0,0 @@ -!Name: Pulsar -!Author: John Conway -!Despite its size, this is the fourth most common oscillator (and by far the most common of period greater than 2). -!www.conwaylife.com/wiki/index.php?title=Pulsar -..OOO...OOO - -O....O.O....O -O....O.O....O -O....O.O....O -..OOO...OOO - -..OOO...OOO -O....O.O....O -O....O.O....O -O....O.O....O - -..OOO...OOO diff --git a/ch16/Automaton.java b/ch16/Automaton.java index 254bf68..66f62d0 100644 --- a/ch16/Automaton.java +++ b/ch16/Automaton.java @@ -6,8 +6,6 @@ */ public abstract class Automaton { - public static final int SIZE = 20; - protected GridCanvas grid; /** diff --git a/ch16/Conway.java b/ch16/Conway.java index 572ab78..09080c0 100644 --- a/ch16/Conway.java +++ b/ch16/Conway.java @@ -1,80 +1,19 @@ -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Scanner; - /** * Conway's Game of Life. */ public class Conway extends Automaton { /** - * Creates a grid with a Blinker and a Glider. + * Creates a grid with two Blinkers. */ public Conway() { - grid = new GridCanvas(30, 25, SIZE); - grid.turnOn(1, 2); + grid = new GridCanvas(5, 10, 20); + grid.turnOn(2, 1); grid.turnOn(2, 2); - grid.turnOn(3, 2); - grid.turnOn(6, 1); - grid.turnOn(7, 2); - grid.turnOn(7, 3); - grid.turnOn(8, 1); - grid.turnOn(8, 2); - } - - /** - * Creates a grid based on a plain text file. - * http://www.conwaylife.com/wiki/Plaintext - * - * @param path the path to the file - * @param margin how many cells to add - */ - public Conway(String path, int margin) { - - // open the file at the given path - Scanner scan = null; - try { - File file = new File(path); - scan = new Scanner(file); - } catch (FileNotFoundException e) { - e.printStackTrace(); - System.exit(1); - } - - // read file contents into memory - ArrayList data = new ArrayList(); - while (scan.hasNextLine()) { - String line = scan.nextLine(); - // only add non-comment lines - if (!line.startsWith("!")) { - data.add(line); - } - } - - // determine number of rows and columns in the pattern - int rows = data.size(); - int cols = 0; - for (String line : data) { - if (cols < line.length()) { - cols = line.length(); - } - } - if (rows == 0 || cols == 0) { - throw new IllegalArgumentException("no cells found"); - } - - // create the resulting grid with margin of extra cells - grid = new GridCanvas(rows + 2 * margin, cols + 2 * margin, SIZE); - for (int r = 0; r < rows; r++) { - String line = data.get(r); - for (int c = 0; c < line.length(); c++) { - char x = line.charAt(c); - if (x == 'O') { - grid.turnOn(r + margin, c + margin); - } - } - } + grid.turnOn(2, 3); + grid.turnOn(1, 7); + grid.turnOn(2, 7); + grid.turnOn(3, 7); } /** @@ -171,7 +110,7 @@ public void update() { */ public static void main(String[] args) { String title = "Conway's Game of Life"; - Conway game = new Conway("pulsar.cells", 2); + Conway game = new Conway(); game.run(title, 2); } From 33b1e75301e0ff4aa174a7c95491dc0bc19ee41f Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 16 Jun 2020 14:41:35 -0400 Subject: [PATCH 36/52] ch16 revisions --- ch16/Automaton.java | 34 +++++++++++++++++----------------- ch16/Langton.java | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/ch16/Automaton.java b/ch16/Automaton.java index 66f62d0..3ca63a6 100644 --- a/ch16/Automaton.java +++ b/ch16/Automaton.java @@ -13,23 +13,6 @@ public abstract class Automaton { */ public abstract void update(); - /** - * Creates a JFrame and runs the automaton. - * - * @param title the frame title - * @param rate frames per second - */ - public void run(String title, int rate) { - // set up the window frame - JFrame frame = new JFrame(title); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); - frame.add(this.grid); - frame.pack(); - frame.setVisible(true); - this.mainloop(rate); - } - /** * The simulation loop. * @@ -51,4 +34,21 @@ private void mainloop(int rate) { } } + /** + * Creates a JFrame and runs the automaton. + * + * @param title the frame title + * @param rate frames per second + */ + public void run(String title, int rate) { + // set up the window frame + JFrame frame = new JFrame(title); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.add(this.grid); + frame.pack(); + frame.setVisible(true); + this.mainloop(rate); + } + } diff --git a/ch16/Langton.java b/ch16/Langton.java index 45869a1..a39d7a2 100644 --- a/ch16/Langton.java +++ b/ch16/Langton.java @@ -1,8 +1,11 @@ +import javax.swing.JFrame; + /** * Langton's Ant. */ -public class Langton extends Automaton { +public class Langton { + private GridCanvas grid; private int xpos; private int ypos; private int head; // 0=North, 1=East, 2=South, 3=West @@ -59,6 +62,27 @@ public void update() { moveAnt(); } + /** + * The simulation loop. + * + * @param rate frames per second + */ + private void mainloop() { + while (true) { + + // update the drawing + this.update(); + grid.repaint(); + + // delay the simulation + try { + Thread.sleep(2); + } catch (InterruptedException e) { + // do nothing + } + } + } + /** * Creates and runs the simulation. * @@ -67,7 +91,13 @@ public void update() { public static void main(String[] args) { String title = "Langton's Ant"; Langton game = new Langton(61, 61); - game.run(title, 750); + JFrame frame = new JFrame(title); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.add(game.grid); + frame.pack(); + frame.setVisible(true); + game.mainloop(); } } From 4e05ec031c0c27874af423fc819ef1239c70e04a Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Tue, 16 Jun 2020 19:39:42 -0400 Subject: [PATCH 37/52] ch17 revisions --- ch17/DrawablePolygon.java | 2 +- ch17/Drawing.bak | 21 +++------- ch17/{Sim1.java => Main.java} | 4 +- ch17/Mole.java | 43 -------------------- ch17/MoleHill.java | 54 ------------------------- ch17/MovingPolygon.java | 56 -------------------------- ch17/RegularPolygon.java | 37 ++--------------- ch17/RotatingPolygon.java | 75 ----------------------------------- ch17/Sim2.java | 57 -------------------------- ch17/Sim3.java | 62 ----------------------------- ch17/Sprite.java | 12 +++--- ch17/VideoGame.java | 5 ++- ch17/WhackAMole.java | 57 -------------------------- 13 files changed, 22 insertions(+), 463 deletions(-) rename ch17/{Sim1.java => Main.java} (92%) delete mode 100644 ch17/Mole.java delete mode 100644 ch17/MoleHill.java delete mode 100644 ch17/MovingPolygon.java delete mode 100644 ch17/RotatingPolygon.java delete mode 100644 ch17/Sim2.java delete mode 100644 ch17/Sim3.java delete mode 100644 ch17/WhackAMole.java diff --git a/ch17/DrawablePolygon.java b/ch17/DrawablePolygon.java index 0efc8eb..14318f0 100644 --- a/ch17/DrawablePolygon.java +++ b/ch17/DrawablePolygon.java @@ -7,7 +7,7 @@ */ public class DrawablePolygon extends Polygon implements Actor { - public Color color; + protected Color color; /** * Creates an empty polygon. diff --git a/ch17/Drawing.bak b/ch17/Drawing.bak index 63ba8f9..fef62ef 100644 --- a/ch17/Drawing.bak +++ b/ch17/Drawing.bak @@ -4,11 +4,11 @@ import java.awt.Graphics; import java.util.ArrayList; /** - * Draws a collection of actors. + * Draws a collection of DrawablePolygons. */ public class Drawing extends Canvas { - private ArrayList list; + private ArrayList list; /** * Constructs a drawing of given size. @@ -19,7 +19,7 @@ public class Drawing extends Canvas { public Drawing(int width, int height) { setSize(width, height); setBackground(Color.WHITE); - list = new ArrayList(); + list = new ArrayList(); } /** @@ -27,19 +27,10 @@ public class Drawing extends Canvas { * * @param dp the object to add */ - public void add(ColorPolygon dp) { + public void add(DrawablePolygon dp) { list.add(dp); } - /** - * Gets current actors as an array. - * - * @return array of actor objects - */ - public Object[] getActors() { - return list.toArray(); - } - /** * Draws all the actors on the canvas. * @@ -47,7 +38,7 @@ public class Drawing extends Canvas { */ @Override public void paint(Graphics g) { - for (ColorPolygon dp : list) { + for (DrawablePolygon dp : list) { dp.draw(g); } } @@ -56,7 +47,7 @@ public class Drawing extends Canvas { * Calls the step method of each actor and updates the drawing. */ public void step() { - for (ColorPolygon dp : list) { + for (DrawablePolygon dp : list) { dp.step(); } repaint(); diff --git a/ch17/Sim1.java b/ch17/Main.java similarity index 92% rename from ch17/Sim1.java rename to ch17/Main.java index 019903e..0ab09a0 100644 --- a/ch17/Sim1.java +++ b/ch17/Main.java @@ -4,7 +4,7 @@ /** * Initial drawing of stationary objects. */ -public class Sim1 { +public class Main { /** * Test program that draws a few polygons. @@ -30,7 +30,7 @@ public static void main(String[] args) { drawing.add(p3); // set up the window frame - JFrame frame = new JFrame("Drawing (no animation)"); + JFrame frame = new JFrame("Drawing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(drawing); frame.pack(); diff --git a/ch17/Mole.java b/ch17/Mole.java deleted file mode 100644 index 75d48e0..0000000 --- a/ch17/Mole.java +++ /dev/null @@ -1,43 +0,0 @@ -import java.awt.Color; - -/** - * A polygon that represents a small burrowing mammal. - */ -public class Mole extends BlinkingPolygon { - - public static final Color BROWN = new Color(153, 102, 0); - - private boolean alive; - - /** - * Creates a mole at the given location. - * - * @param x the X coordinate - * @param y the Y coordinate - */ - public Mole(int x, int y) { - super(10, 30, BROWN); - translate(x, y); - alive = true; - } - - @Override - public void step() { - // blink on/off at random times - if (alive && Math.random() < 0.5) { - super.step(); - } - } - - /** - * Updates the state of the mole when clicked. - */ - public void whack() { - // ignore whack when invisible - if (visible) { - color = Color.LIGHT_GRAY; - alive = false; - } - } - -} diff --git a/ch17/MoleHill.java b/ch17/MoleHill.java deleted file mode 100644 index 24978e5..0000000 --- a/ch17/MoleHill.java +++ /dev/null @@ -1,54 +0,0 @@ -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -/** - * Draws a collection of moles and listens for mouse events. - */ -public class MoleHill extends Drawing implements MouseListener { - - /** - * Constructs an interactive drawing of given size. - * - * @param width the width in pixels - * @param height the height in pixels - */ - public MoleHill(int width, int height) { - super(width, height); - addMouseListener(this); - } - - @Override - public void mouseClicked(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - for (Object obj : getActors()) { - if (obj instanceof Mole) { - Mole mole = (Mole) obj; - if (mole.contains(x, y)) { - mole.whack(); - } - } - } - } - - @Override - public void mouseEntered(MouseEvent e) { - // ignore - } - - @Override - public void mouseExited(MouseEvent e) { - // ignore - } - - @Override - public void mousePressed(MouseEvent e) { - // ignore - } - - @Override - public void mouseReleased(MouseEvent e) { - // ignore - } - -} diff --git a/ch17/MovingPolygon.java b/ch17/MovingPolygon.java deleted file mode 100644 index 7c6c2f5..0000000 --- a/ch17/MovingPolygon.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * A polygon that bounces off the walls. - */ -public class MovingPolygon extends RegularPolygon { - - private int dx; - private int dy; - - /** - * Constructs a moving polygon. - * - * @param nsides the number of sides - * @param radius from center to vertex - */ - public MovingPolygon(int nsides, int radius) { - super(nsides, radius); - dx = 10; - dy = 5; - } - - /** - * @param dx how many pixels to move left/right - */ - public void setDx(int dx) { - this.dx = dx; - } - - /** - * @param dy how many pixels to move up/down - */ - public void setDy(int dy) { - this.dy = dy; - } - - @Override - public void step() { - - // edge detection - for (int i = 0; i < npoints; i++) { - if (xpoints[i] < 0 || xpoints[i] > 800) { - dx *= -1; - break; - } - } - for (int i = 0; i < npoints; i++) { - if (ypoints[i] < 0 || ypoints[i] > 600) { - dy *= -1; - break; - } - } - - // move one step - translate(dx, dy); - } - -} diff --git a/ch17/RegularPolygon.java b/ch17/RegularPolygon.java index 5aef2d3..4642355 100644 --- a/ch17/RegularPolygon.java +++ b/ch17/RegularPolygon.java @@ -6,10 +6,6 @@ */ public class RegularPolygon extends DrawablePolygon { - public static final String[] NAMES = {null, null, null, - "Triangle", "Square", "Pentagon", "Hexagon", - "Heptagon", "Octagon", "Nonagon", "Decagon"}; - /** * Constructs a regular polygon, given the number of sides. * @@ -26,7 +22,7 @@ public RegularPolygon(int nsides) { * @param radius from center to vertex */ public RegularPolygon(int nsides, int radius) { - this(nsides, radius, Color.BLACK); + this(nsides, radius, Color.GRAY); } /** @@ -57,43 +53,18 @@ public RegularPolygon(int nsides, int radius, Color color) { this.color = color; // the amount to rotate for each vertex (in radians) - double angle = 2.0 * Math.PI / nsides; + double theta = 2.0 * Math.PI / nsides; // rotation that makes the polygon right-side up double rotate = Math.PI / nsides + Math.PI / 2.0; // compute x and y coordinates, centered at the origin for (int i = 0; i < nsides; i++) { - double x = radius * Math.cos(i * angle + rotate); + double x = radius * Math.cos(i * theta + rotate); + double y = radius * Math.sin(i * theta + rotate); xpoints[i] = (int) Math.round(x); - double y = radius * Math.sin(i * angle + rotate); ypoints[i] = (int) Math.round(y); } } - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - if (npoints < NAMES.length) { - str.append(NAMES[npoints]); - } else { - str.append("Polygon"); - } - // append the list of vertexes - str.append('['); - for (int i = 0; i < npoints; i++) { - if (i > 0) { - str.append(", "); - } - // append the next (x, y) point - str.append('('); - str.append(xpoints[i]); - str.append(", "); - str.append(ypoints[i]); - str.append(')'); - } - str.append(']'); - return str.toString(); - } - } diff --git a/ch17/RotatingPolygon.java b/ch17/RotatingPolygon.java deleted file mode 100644 index f1a84ed..0000000 --- a/ch17/RotatingPolygon.java +++ /dev/null @@ -1,75 +0,0 @@ -import java.util.Arrays; - -/** - * A polygon that rotates around its center. - */ -public class RotatingPolygon extends RegularPolygon { - - private int xmid; - private int ymid; - - private int angle; // in degrees - - private int[] x0; // original xpoints - private int[] y0; // original ypoints - - /** - * Constructs a rotating polygon. - * - * @param nsides the number of sides - * @param radius from center to vertex - */ - public RotatingPolygon(int nsides, int radius) { - super(nsides, radius); - center(); - } - - /** - * Sets the rotation point to the middle. - */ - public void center() { - - // find the average x and y values - int xsum = 0; - int ysum = 0; - for (int x : xpoints) { - xsum += x; - } - for (int y : ypoints) { - ysum += y; - } - xmid = (int) Math.round(xsum / npoints); - ymid = (int) Math.round(ysum / npoints); - - // reset the rotation direction - angle = 359; - - // save the original x and y points - x0 = Arrays.copyOf(xpoints, npoints); - y0 = Arrays.copyOf(ypoints, npoints); - } - - @Override - public void step() { - // update the rotation angle - angle = (angle + 1) % 360; - final double RAD = Math.toRadians(angle); - final double COS = Math.cos(RAD); - final double SIN = Math.sin(RAD); - - // translate the polygon points - for (int i = 0; i < npoints; i++) { - double t = x0[i] - xmid; - double v = y0[i] - ymid; - xpoints[i] = (int) Math.round(xmid + t * COS - v * SIN); - ypoints[i] = (int) Math.round(ymid + t * SIN + v * COS); - } - } - - @Override - public void translate(int deltaX, int deltaY) { - super.translate(deltaX, deltaY); - center(); - } - -} diff --git a/ch17/Sim2.java b/ch17/Sim2.java deleted file mode 100644 index c1284c2..0000000 --- a/ch17/Sim2.java +++ /dev/null @@ -1,57 +0,0 @@ -import java.awt.Color; -import java.awt.Toolkit; -import javax.swing.JFrame; - -/** - * Example simulation of animated objects. - */ -public class Sim2 { - - /** - * Test program that draws a few polygons. - * - * @param args command-line arguments - */ - public static void main(String[] args) { - - // create some regular polygons - BlinkingPolygon bp = new BlinkingPolygon(3, 20, Color.BLUE); - MovingPolygon mp = new MovingPolygon(8, 30); - RotatingPolygon rp = new RotatingPolygon(5, 40); - - // move them out of the corner - bp.translate(50, 50); - mp.translate(100, 100); - rp.translate(200, 200); - - // create drawing, add polygons - Drawing drawing = new Drawing(800, 600); - drawing.add(bp); - drawing.add(mp); - drawing.add(rp); - - // set up the window frame - JFrame frame = new JFrame("Drawing with Thread.sleep"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.add(drawing); - frame.pack(); - frame.setVisible(true); - - // main simulation loop - Toolkit toolkit = frame.getToolkit(); - while (true) { - - // update the drawing - toolkit.sync(); - drawing.step(); - - // delay the simulation - try { - Thread.sleep(1000 / 30); - } catch (InterruptedException e) { - // do nothing - } - } - } - -} diff --git a/ch17/Sim3.java b/ch17/Sim3.java deleted file mode 100644 index 2bb42d0..0000000 --- a/ch17/Sim3.java +++ /dev/null @@ -1,62 +0,0 @@ -import java.awt.Color; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.JFrame; -import javax.swing.Timer; - -/** - * Smoother version of Sim2 using a timer. - */ -public class Sim3 implements ActionListener { - - private Drawing drawing; - private Toolkit toolkit; - - /** - * Set up the drawing and window frame. - */ - public Sim3() { - // create some regular polygons - BlinkingPolygon bp = new BlinkingPolygon(3, 20, Color.BLUE); - MovingPolygon mp = new MovingPolygon(8, 30); - RotatingPolygon rp = new RotatingPolygon(5, 40); - - // move them out of the corner - bp.translate(50, 50); - mp.translate(100, 100); - rp.translate(200, 200); - - // create drawing, add polygons - drawing = new Drawing(800, 600); - drawing.add(bp); - drawing.add(mp); - drawing.add(rp); - - // set up the window frame - JFrame frame = new JFrame("Drawing with ActionListener"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.add(drawing); - frame.pack(); - frame.setVisible(true); - toolkit = frame.getToolkit(); - } - - @Override - public void actionPerformed(ActionEvent e) { - toolkit.sync(); - drawing.step(); - } - - /** - * Create and start the timer. - * - * @param args command-line arguments - */ - public static void main(String[] args) { - Sim3 sim = new Sim3(); - Timer timer = new Timer(1000 / 30, sim); - timer.start(); - } - -} diff --git a/ch17/Sprite.java b/ch17/Sprite.java index 515408a..92d013e 100644 --- a/ch17/Sprite.java +++ b/ch17/Sprite.java @@ -11,11 +11,11 @@ */ public class Sprite implements Actor, KeyListener { - private Image image; private int xpos; private int ypos; private int dx; private int dy; + private Image image; /** * Reads a sprite from a png file. @@ -45,11 +45,6 @@ public void step() { ypos += dy; } - @Override - public void keyTyped(KeyEvent e) { - // do nothing - } - @Override public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { @@ -82,4 +77,9 @@ public void keyReleased(KeyEvent e) { } } + @Override + public void keyTyped(KeyEvent e) { + // do nothing + } + } diff --git a/ch17/VideoGame.java b/ch17/VideoGame.java index 3f54c3c..cf06193 100644 --- a/ch17/VideoGame.java +++ b/ch17/VideoGame.java @@ -16,11 +16,12 @@ public class VideoGame implements ActionListener { * Set up the drawing and window frame. */ public VideoGame() { - Sprite sprite = new Sprite("face-smile.png", 50, 50); + Sprite sprite = new Sprite("face-smile.png", 25, 150); drawing = new Drawing(800, 600); drawing.add(sprite); drawing.addKeyListener(sprite); drawing.setFocusable(true); + JFrame frame = new JFrame("Video Game"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(drawing); @@ -42,7 +43,7 @@ public void actionPerformed(ActionEvent e) { */ public static void main(String[] args) { VideoGame game = new VideoGame(); - Timer timer = new Timer(25, game); + Timer timer = new Timer(33, game); timer.start(); } diff --git a/ch17/WhackAMole.java b/ch17/WhackAMole.java deleted file mode 100644 index 641d6e3..0000000 --- a/ch17/WhackAMole.java +++ /dev/null @@ -1,57 +0,0 @@ -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.JFrame; -import javax.swing.Timer; - -/** - * Simulates the arcade game Whack-A-Mole. - * https://en.wikipedia.org/wiki/Whac-A-Mole - */ -public class WhackAMole implements ActionListener { - - private Drawing drawing; - private Toolkit toolkit; - - /** - * Set up the drawing and window frame. - */ - public WhackAMole() { - - // create drawing, add polygons - drawing = new MoleHill(800, 600); - drawing.add(new Mole(150, 200)); - drawing.add(new Mole(350, 200)); - drawing.add(new Mole(550, 200)); - drawing.add(new Mole(150, 400)); - drawing.add(new Mole(350, 400)); - drawing.add(new Mole(550, 400)); - - // set up the window frame - JFrame frame = new JFrame("Whack-A-Mole"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setResizable(false); - frame.add(drawing); - frame.pack(); - frame.setVisible(true); - toolkit = frame.getToolkit(); - } - - @Override - public void actionPerformed(ActionEvent e) { - toolkit.sync(); - drawing.step(); - } - - /** - * Create and start the timer. - * - * @param args command-line arguments - */ - public static void main(String[] args) { - WhackAMole sim = new WhackAMole(); - Timer timer = new Timer(1000 / 30, sim); - timer.start(); - } - -} From 44526ccd44f48ebbee601f4a9fb03d2a7f43fe81 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 12:57:54 -0400 Subject: [PATCH 38/52] appendix revisions --- Checkstyle.xml | 2 -- appb/Convert.java | 4 ++-- appb/DigitUtil.java | 12 ++++-------- appc/Mickey.java | 2 +- appc/Moire.java | 2 +- appd/Complex.java | 20 ++++++++++++++++---- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Checkstyle.xml b/Checkstyle.xml index 75ad255..6cf2192 100644 --- a/Checkstyle.xml +++ b/Checkstyle.xml @@ -34,7 +34,6 @@ Checkstyle configuration for Think Java, 2nd Edition. - @@ -62,7 +61,6 @@ Checkstyle configuration for Think Java, 2nd Edition. - diff --git a/appb/Convert.java b/appb/Convert.java index cc25cb0..232abd6 100644 --- a/appb/Convert.java +++ b/appb/Convert.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Allen Downey and Chris Mayfield + * Copyright (c) 2019 Allen Downey and Chris Mayfield * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,7 @@ import java.util.Scanner; /** - * Utility class for converting to/from the metric system. + * Methods for converting to/from the metric system. * * @author Allen Downey * @author Chris Mayfield diff --git a/appb/DigitUtil.java b/appb/DigitUtil.java index 9cd7256..04c55eb 100644 --- a/appb/DigitUtil.java +++ b/appb/DigitUtil.java @@ -13,20 +13,16 @@ public class DigitUtil { * @return true if x has one digit, false otherwise */ public static boolean isSingleDigit(int x) { - if (x > -10 && x < 10) { - return true; - } else { - return false; - } - } - - public static boolean isSingleDigit2(int x) { return x > -10 && x < 10; } public static void main(String[] args) { System.out.println(isSingleDigit(2)); + boolean bigFlag = !isSingleDigit(17); + if (bigFlag) { + System.out.println("not single"); + } int z = 9; if (isSingleDigit(z)) { diff --git a/appc/Mickey.java b/appc/Mickey.java index b303b20..73236d6 100644 --- a/appc/Mickey.java +++ b/appc/Mickey.java @@ -11,7 +11,7 @@ public static void main(String[] args) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Canvas canvas = new Mickey(); canvas.setSize(400, 400); - canvas.setBackground(Color.white); + canvas.setBackground(Color.WHITE); frame.add(canvas); frame.pack(); frame.setVisible(true); diff --git a/appc/Moire.java b/appc/Moire.java index b736d97..6c3e78c 100644 --- a/appc/Moire.java +++ b/appc/Moire.java @@ -10,7 +10,7 @@ public static void main(String[] args) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Canvas canvas = new Moire(); canvas.setSize(400, 400); - canvas.setBackground(Color.white); + canvas.setBackground(Color.WHITE); frame.add(canvas); frame.pack(); frame.setVisible(true); diff --git a/appd/Complex.java b/appd/Complex.java index ac4c50f..2a86ee6 100644 --- a/appd/Complex.java +++ b/appd/Complex.java @@ -1,10 +1,13 @@ import java.awt.Rectangle; /** - * Example from "My method doesn't return what I expect." + * Examples from Logic Errors section. */ public class Complex { + /** + * My method doesn't return what I expect. + */ public static Rectangle intersection(Rectangle a, Rectangle b) { int x1 = Math.min(a.x, b.x); int y1 = Math.min(a.y, b.y); @@ -14,10 +17,19 @@ public static Rectangle intersection(Rectangle a, Rectangle b) { return rect; } + /** + * I've got a big, hairy expression and it doesn’t do what I expect. + */ public static void main(String[] args) { - Rectangle x = new Rectangle(0, 0, 10, 10); - Rectangle y = new Rectangle(-5, -5, -5, -5); - System.out.println(intersection(x, y)); + Rectangle rect = new Rectangle(0, 0, 10, 10); + Rectangle ngle = new Rectangle(-5, -5, -5, -5); + System.out.println(intersection(rect, ngle)); + + double halfWidth = 0.5 * rect.getWidth(); + double halfHeight = 0.5 * rect.getHeight(); + int dx = (int) Math.round(halfWidth); + int dy = (int) Math.round(halfHeight); + rect.translate(dx, dy); } } From 01f9e08f528608acd095b059616707e1fbc9bc79 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 13:15:40 -0400 Subject: [PATCH 39/52] split ch02 --- ch02/DeclareAssign.java | 23 +++++++++++++ ch02/FloatingPoint.java | 21 ++++++++++++ ch02/Hello.java | 8 +++++ ch02/MemoryDiagram.java | 10 ++++++ ch02/PrintingVars.java | 28 ++++++++++++++++ ch02/StringConcat.java | 12 +++++++ ch02/Variables.java | 71 ----------------------------------------- 7 files changed, 102 insertions(+), 71 deletions(-) create mode 100644 ch02/DeclareAssign.java create mode 100644 ch02/FloatingPoint.java create mode 100644 ch02/Hello.java create mode 100644 ch02/MemoryDiagram.java create mode 100644 ch02/PrintingVars.java create mode 100644 ch02/StringConcat.java delete mode 100644 ch02/Variables.java diff --git a/ch02/DeclareAssign.java b/ch02/DeclareAssign.java new file mode 100644 index 0000000..87a8e02 --- /dev/null +++ b/ch02/DeclareAssign.java @@ -0,0 +1,23 @@ +public class DeclareAssign { + + public static void main(String[] args) { + String message; + int x; + + String firstName; + String lastName; + int hour, minute; + + message = "Hello!"; // give message the value "Hello!" + hour = 11; // assign the value 11 to hour + minute = 59; // set minute to 59 + + message = "123"; // legal + // message = 123; // not legal + + String message2 = "Hello!"; + int hour2 = 11; + int minute2 = 59; + } + +} diff --git a/ch02/FloatingPoint.java b/ch02/FloatingPoint.java new file mode 100644 index 0000000..b9afa1c --- /dev/null +++ b/ch02/FloatingPoint.java @@ -0,0 +1,21 @@ +public class FloatingPoint { + + public static void main(String[] args) { + double pi; + pi = 3.14159; + + double minute3 = 59.0; + System.out.print("Fraction of the hour that has passed: "); + System.out.println(minute3 / 60.0); + + double y = 1.0 / 3.0; // correct + + System.out.println(0.1 * 10); + System.out.println(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + + 0.1 + 0.1 + 0.1 + 0.1 + 0.1); + + double balance = 123.45; // potential rounding error + int balance2 = 12345; // total number of cents + } + +} diff --git a/ch02/Hello.java b/ch02/Hello.java new file mode 100644 index 0000000..bbc0349 --- /dev/null +++ b/ch02/Hello.java @@ -0,0 +1,8 @@ +public class Hello { + + public static void main(String[] args) { + System.out.println("Hello, "); + System.out.println("World!"); + } + +} diff --git a/ch02/MemoryDiagram.java b/ch02/MemoryDiagram.java new file mode 100644 index 0000000..1fecfd8 --- /dev/null +++ b/ch02/MemoryDiagram.java @@ -0,0 +1,10 @@ +public class MemoryDiagram { + + public static void main(String[] args) { + int a = 5; + int b = a; // a and b are now equal + a = 3; // a and b are no longer equal + int c = 0; + } + +} diff --git a/ch02/PrintingVars.java b/ch02/PrintingVars.java new file mode 100644 index 0000000..27a0f08 --- /dev/null +++ b/ch02/PrintingVars.java @@ -0,0 +1,28 @@ +public class PrintingVars { + + public static void main(String[] args) { + String firstLine = "Hello, again!"; + System.out.println(firstLine); + + System.out.print("The value of firstLine is "); + System.out.println(firstLine); + + int hour = 11; + int minute = 59; + System.out.print("The current time is "); + System.out.print(hour); + System.out.print(":"); + System.out.print(minute); + System.out.println("."); + + System.out.print("Number of minutes since midnight: "); + System.out.println(hour * 60 + minute); + + System.out.print("Fraction of the hour that has passed: "); + System.out.println(minute / 60); + + System.out.print("Percent of the hour that has passed: "); + System.out.println(minute * 100 / 60); + } + +} diff --git a/ch02/StringConcat.java b/ch02/StringConcat.java new file mode 100644 index 0000000..4ec9902 --- /dev/null +++ b/ch02/StringConcat.java @@ -0,0 +1,12 @@ +public class StringConcat { + + public static void main(String[] args) { + System.out.println(1 + 2 + "Hello"); + // the output is 3Hello + + System.out.println("Hello" + 1 + 2); + // the output is Hello12 + + } + +} diff --git a/ch02/Variables.java b/ch02/Variables.java deleted file mode 100644 index f6ce6ee..0000000 --- a/ch02/Variables.java +++ /dev/null @@ -1,71 +0,0 @@ -public class Variables { - - public static void main(String[] args) { - - String message; - int x; - - String firstName; - String lastName; - int hour, minute; - - message = "Hello!"; // give message the value "Hello!" - hour = 11; // assign the value 11 to hour - minute = 59; // set minute to 59 - - message = "123"; // legal - // message = 123; // not legal - - String message2 = "Hello!"; - int hour2 = 11; - int minute2 = 59; - - int a = 5; - int b = a; // a and b are now equal - a = 3; // a and b are no longer equal - - String firstLine = "Hello, again!"; - System.out.println(firstLine); - - System.out.print("The value of firstLine is "); - System.out.println(firstLine); - - System.out.print("The current time is "); - System.out.print(hour); - System.out.print(":"); - System.out.print(minute); - System.out.println("."); - - System.out.print("Number of minutes since midnight: "); - System.out.println(hour * 60 + minute); - - System.out.print("Fraction of the hour that has passed: "); - System.out.println(minute / 60); - - System.out.print("Percent of the hour that has passed: "); - System.out.println(minute * 100 / 60); - - double pi; - pi = 3.14159; - - double minute3 = 59.0; - System.out.print("Fraction of the hour that has passed: "); - System.out.println(minute3 / 60.0); - - double y = 1.0 / 3.0; // correct - - System.out.println(0.1 * 10); - System.out.println(0.1 + 0.1 + 0.1 + 0.1 + 0.1 - + 0.1 + 0.1 + 0.1 + 0.1 + 0.1); - - double balance = 123.45; // potential rounding error - int balance2 = 12345; // total number of cents - - System.out.println(1 + 2 + "Hello"); - // the output is 3Hello - - System.out.println("Hello" + 1 + 2); - // the output is Hello12 - } - -} From f48f47ecb2295eca49ea859d289deec00bc65b48 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 13:34:50 -0400 Subject: [PATCH 40/52] ch03 revisions --- ch03/Formatting.java | 33 +++++++++++++++++++++++++++++++++ ch03/Input.java | 16 ---------------- ch03/Literals.java | 22 ++++++++++++++++++++++ ch03/ScannerBug.java | 3 +++ 4 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 ch03/Formatting.java delete mode 100644 ch03/Input.java create mode 100644 ch03/Literals.java diff --git a/ch03/Formatting.java b/ch03/Formatting.java new file mode 100644 index 0000000..7beced4 --- /dev/null +++ b/ch03/Formatting.java @@ -0,0 +1,33 @@ +/** + * Examples from the middle of the chapter. + */ +public class Formatting { + + public static void main(String[] args) { + final double CM_PER_INCH = 2.54; + + System.out.println(System.out); + + // formatting output + + System.out.print(4.0 / 3.0); + System.out.printf("Four thirds = %.3f", 4.0 / 3.0); + + int inch = 100; + double cm = inch * CM_PER_INCH; + System.out.printf("%d in = %f cm\n", inch, cm); + + // type cast operators + + double pi = 3.14159; + int xi = (int) pi; + + double x = (int) pi * 20.0; // result is 60.0, not 62.0 + + inch = (int) (cm / CM_PER_INCH); + System.out.printf("%f cm = %d in\n", cm, inch); + + System.out.printf("inches = %d" + inch); // error + } + +} diff --git a/ch03/Input.java b/ch03/Input.java deleted file mode 100644 index de97dc0..0000000 --- a/ch03/Input.java +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Examples from Chapter 3. - */ -public class Input { - - public static void main(String[] args) { - System.out.println(System.out); - - System.out.print(4.0 / 3.0); - System.out.printf("Four thirds = %.3f", 4.0 / 3.0); - - double pi = 3.14159; - double x = (int) pi * 20.0; - } - -} diff --git a/ch03/Literals.java b/ch03/Literals.java new file mode 100644 index 0000000..3741364 --- /dev/null +++ b/ch03/Literals.java @@ -0,0 +1,22 @@ +import java.util.Scanner; + +/** + * Converts inches to centimeters. + */ +public class Literals { + + public static void main(String[] args) { + int inch; + double cm; + Scanner in = new Scanner(System.in); + + System.out.print("How many inches? "); + inch = in.nextInt(); + + final double CM_PER_INCH = 2.54; + cm = inch * CM_PER_INCH; + System.out.print(inch + " in = "); + System.out.println(cm + " cm"); + } + +} diff --git a/ch03/ScannerBug.java b/ch03/ScannerBug.java index 353affb..bef7834 100644 --- a/ch03/ScannerBug.java +++ b/ch03/ScannerBug.java @@ -16,6 +16,9 @@ public static void main(String[] args) { age = in.nextInt(); System.out.printf("Hello %s, age %d\n", name, age); + in.reset(); + System.out.println(); + System.out.print("What is your age? "); age = in.nextInt(); System.out.print("What is your name? "); From 5af8617b0a2e8beda3ca5c1d3cb7817ad28cecf5 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 13:56:34 -0400 Subject: [PATCH 41/52] ch04 revisions --- ch04/Circle.java | 69 ++----------------------- ch04/Distance.java | 45 ++++++++++++++++ ch04/{Methods.java => MathMethods.java} | 9 ++-- ch04/PrintTime.java | 3 ++ ch04/PrintTwice.java | 3 ++ 5 files changed, 59 insertions(+), 70 deletions(-) create mode 100644 ch04/Distance.java rename ch04/{Methods.java => MathMethods.java} (89%) diff --git a/ch04/Circle.java b/ch04/Circle.java index a09e594..f79af90 100644 --- a/ch04/Circle.java +++ b/ch04/Circle.java @@ -1,76 +1,13 @@ public class Circle { public static double calculateArea(double radius) { - double result = Math.PI * radius * radius; - return result; - } - - public static double calculateArea2(double radius) { return Math.PI * radius * radius; } - public static double distance - (double x1, double y1, double x2, double y2) { - double dx = x2 - x1; - double dy = y2 - y1; - System.out.println("dx is " + dx); - System.out.println("dy is " + dy); - return 0.0; - } - - public static double distance2 - (double x1, double y1, double x2, double y2) { - double dx = x2 - x1; - double dy = y2 - y1; - double dsquared = dx * dx + dy * dy; - System.out.println("dsquared is " + dsquared); - return 0.0; - } - - public static double distance3 - (double x1, double y1, double x2, double y2) { - double dx = x2 - x1; - double dy = y2 - y1; - double dsquared = dx * dx + dy * dy; - double result = Math.sqrt(dsquared); - return result; - } - - public static double circleArea - (double xc, double yc, double xp, double yp) { - double radius = distance(xc, yc, xp, yp); - double area = calculateArea(radius); - return area; - } - - public static double calculateArea - (double xc, double yc, double xp, double yp) { - return calculateArea(distance(xc, yc, xp, yp)); - } - public static void main(String[] args) { - - System.out.println("calculateArea"); - System.out.println(calculateArea(3.0)); - - System.out.println("calculateArea2"); - System.out.println(calculateArea2(3.0)); - - System.out.println("distance"); - System.out.println(distance(1.0, 2.0, 4.0, 6.0)); - - System.out.println("distance2"); - System.out.println(distance2(1.0, 2.0, 4.0, 6.0)); - - System.out.println("distance3"); - System.out.println(distance3(1.0, 2.0, 4.0, 6.0)); - - System.out.println("circleArea"); - System.out.println(circleArea(1.0, 2.0, 4.0, 6.0)); - - System.out.println("calculateArea with 4 doubles"); - System.out.println(calculateArea(1.0, 2.0, 4.0, 6.0)); - + double diameter = 10.0; + double area = calculateArea(diameter / 2); + System.out.println(area); } } diff --git a/ch04/Distance.java b/ch04/Distance.java new file mode 100644 index 0000000..5bdb9ad --- /dev/null +++ b/ch04/Distance.java @@ -0,0 +1,45 @@ +public class Distance { + + public static double distance1(double x1, double y1, double x2, double y2) { + return 0.0; // stub + } + + public static double distance2(double x1, double y1, double x2, double y2) { + double dx = x2 - x1; + double dy = y2 - y1; + System.out.println("dx is " + dx); + System.out.println("dy is " + dy); + return 0.0; // stub + } + + public static double distance3(double x1, double y1, double x2, double y2) { + double dx = x2 - x1; + double dy = y2 - y1; + double dsquared = dx * dx + dy * dy; + System.out.println("dsquared is " + dsquared); + return 0.0; // stub + } + + public static double distance4(double x1, double y1, double x2, double y2) { + double dx = x2 - x1; + double dy = y2 - y1; + double dsquared = dx * dx + dy * dy; + double result = Math.sqrt(dsquared); + return result; + } + + public static void main(String[] args) { + System.out.println("\ndistance version 1"); + System.out.println(distance1(1.0, 2.0, 4.0, 6.0)); + + System.out.println("\ndistance version 2"); + System.out.println(distance2(1.0, 2.0, 4.0, 6.0)); + + System.out.println("\ndistance version 3"); + System.out.println(distance3(1.0, 2.0, 4.0, 6.0)); + + System.out.println("\ndistance version 4"); + System.out.println(distance4(1.0, 2.0, 4.0, 6.0)); + } + +} diff --git a/ch04/Methods.java b/ch04/MathMethods.java similarity index 89% rename from ch04/Methods.java rename to ch04/MathMethods.java index 90c1b7a..51ef7dc 100644 --- a/ch04/Methods.java +++ b/ch04/MathMethods.java @@ -1,7 +1,4 @@ -/** - * Examples from Chapter 4. - */ -public class Methods { +public class MathMethods { public static void main(String[] args) { double root = Math.sqrt(17.0); @@ -10,10 +7,14 @@ public static void main(String[] args) { double degrees = 90; double angle2 = degrees / 180.0 * Math.PI; + double radians = Math.toRadians(180.0); double degrees2 = Math.toDegrees(Math.PI); + long x = Math.round(Math.PI * 20.0); + // examples of composition + double x2 = Math.cos(angle + Math.PI / 2.0); double x3 = Math.exp(Math.log(10.0)); double x4 = Math.pow(2.0, 10.0); diff --git a/ch04/PrintTime.java b/ch04/PrintTime.java index 019d579..055781f 100644 --- a/ch04/PrintTime.java +++ b/ch04/PrintTime.java @@ -10,6 +10,9 @@ public static void main(String[] args) { int hour = 11; int minute = 59; printTime(hour, minute); + + // additional example for stack diagram + printTime(hour + 1, 0); } } diff --git a/ch04/PrintTwice.java b/ch04/PrintTwice.java index 7131085..1180417 100644 --- a/ch04/PrintTwice.java +++ b/ch04/PrintTwice.java @@ -7,6 +7,9 @@ public static void printTwice(String s) { public static void main(String[] args) { printTwice("Don't make me say this twice!"); + + String message = "Never say never."; + printTwice(message); } } From 8ddb25fc2d1bc1a90d374989bd615bb507972455 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 14:17:07 -0400 Subject: [PATCH 42/52] ch05 revisions --- ch05/ChainNest.java | 25 +++++++++++++++++++ ch05/Conditional.java | 50 ------------------------------------- ch05/DigitUtil.java | 27 ++++++++++++++++++++ ch05/IfElse.java | 32 ++++++++++++++++++++++++ ch05/Logarithm.java | 2 +- ch05/LogicalOpers.java | 56 ++++++++++++++++++++++++++++++++++++++++++ ch05/Switch.java | 56 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 197 insertions(+), 51 deletions(-) create mode 100644 ch05/ChainNest.java delete mode 100644 ch05/Conditional.java create mode 100644 ch05/DigitUtil.java create mode 100644 ch05/IfElse.java create mode 100644 ch05/LogicalOpers.java create mode 100644 ch05/Switch.java diff --git a/ch05/ChainNest.java b/ch05/ChainNest.java new file mode 100644 index 0000000..9d1fd11 --- /dev/null +++ b/ch05/ChainNest.java @@ -0,0 +1,25 @@ +public class ChainNest { + + public static void main(String[] args) { + int x = 0; + + if (x > 0) { + System.out.println("x is positive"); + } else if (x < 0) { + System.out.println("x is negative"); + } else { + System.out.println("x is zero"); + } + + if (x > 0) { + System.out.println("x is positive"); + } else { + if (x < 0) { + System.out.println("x is negative"); + } else { + System.out.println("x is zero"); + } + } + } + +} diff --git a/ch05/Conditional.java b/ch05/Conditional.java deleted file mode 100644 index 5a5a4ca..0000000 --- a/ch05/Conditional.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Examples from Chapter 5. - */ -public class Conditional { - - public static void main(String[] args) { - int x = 17; - int n = 18; - - if (x > 0) { - System.out.println("x is positive"); - } - - if (x % 2 == 0) { - System.out.println("x is even"); - } else { - System.out.println("x is odd"); - } - - if (x > 0) { - System.out.println("x is positive"); - } else if (x < 0) { - System.out.println("x is negative"); - } else { - System.out.println("x is zero"); - } - - if (x > 0) { - System.out.println("x is positive"); - } else { - if (x < 0) { - System.out.println("x is negative"); - } else { - System.out.println("x is zero"); - } - } - - boolean evenFlag = (n % 2 == 0); // true if n is even - boolean positiveFlag = (x > 0); // true if x is positive - - if (evenFlag) { - System.out.println("n was even when I checked it"); - } - - if (!evenFlag) { - System.out.println("n was odd when I checked it"); - } - } - -} diff --git a/ch05/DigitUtil.java b/ch05/DigitUtil.java new file mode 100644 index 0000000..551e9a9 --- /dev/null +++ b/ch05/DigitUtil.java @@ -0,0 +1,27 @@ +public class DigitUtil { + + public static boolean isSingleDigit(int x) { + if (x > -10 && x < 10) { + return true; + } else { + return false; + } + } + + public static boolean isSingleDigit2(int x) { + return x > -10 && x < 10; + } + + public static void main(String[] args) { + System.out.println(isSingleDigit(2)); + boolean bigFlag = !isSingleDigit(17); + + int z = 9; + if (isSingleDigit(z)) { + System.out.println("z is small"); + } else { + System.out.println("z is big"); + } + } + +} diff --git a/ch05/IfElse.java b/ch05/IfElse.java new file mode 100644 index 0000000..83a0e72 --- /dev/null +++ b/ch05/IfElse.java @@ -0,0 +1,32 @@ +public class IfElse { + + public static void main(String[] args) { + int x = 17; + int n = 18; + + if (x > 0) { + System.out.println("x is positive"); + } + + if (x % 2 == 0) { + System.out.println("x is even"); + } else { + System.out.println("x is odd"); + } + + // look, no braces...bad idea! + if (x % 2 == 0) + System.out.println("x is even"); + else + System.out.println("x is odd"); + + if (x > 0) + System.out.println("x is positive"); + System.out.println("x is not zero"); + + if (x % 2 == 0); { // incorrect semicolon + System.out.println("x is even"); + } + } + +} diff --git a/ch05/Logarithm.java b/ch05/Logarithm.java index 4e2fd45..ef9e53a 100644 --- a/ch05/Logarithm.java +++ b/ch05/Logarithm.java @@ -20,7 +20,7 @@ public static void main(String[] args) { // check the range double x = in.nextDouble(); - if (x >= 0) { + if (x > 0) { double y = Math.log(x); System.out.println("The log is " + y); } else { diff --git a/ch05/LogicalOpers.java b/ch05/LogicalOpers.java new file mode 100644 index 0000000..e9dc6dd --- /dev/null +++ b/ch05/LogicalOpers.java @@ -0,0 +1,56 @@ +public class LogicalOpers { + + public static void main(String[] args) { + int x = 0; + int y = 0; + + // nested + if (x == 0) { + if (y == 0) { + System.out.println("Both x and y are zero"); + } + } + + // combined + if (x == 0 && y == 0) { + System.out.println("Both x and y are zero"); + } + + // chained + if (x == 0) { + System.out.println("Either x or y is zero"); + } else if (y == 0) { + System.out.println("Either x or y is zero"); + } + + // combined + if (x == 0 || y == 0) { + System.out.println("Either x or y is zero"); + } + + // De Morgan's + if (!(x == 0 || y == 0)) { + System.out.println("Neither x nor y is zero"); + } + if (x != 0 && y != 0) { + System.out.println("Neither x nor y is zero"); + } + + // boolean variables + boolean flag; + flag = true; + boolean testResult = false; + + boolean evenFlag = (x % 2 == 0); // true if x is even + boolean positiveFlag = (x > 0); // true if x is positive + + if (evenFlag) { + System.out.println("n was even when I checked it"); + } + + if (!evenFlag) { + System.out.println("n was odd when I checked it"); + } + } + +} diff --git a/ch05/Switch.java b/ch05/Switch.java new file mode 100644 index 0000000..70916b7 --- /dev/null +++ b/ch05/Switch.java @@ -0,0 +1,56 @@ +public class Switch { + + public static void main(String[] args) { + int number = 0; + String word; + + // if-else-if + + if (number == 1) { + word = "one"; + } else if (number == 2) { + word = "two"; + } else if (number == 3) { + word = "three"; + } else { + word = "unknown"; + } + + // same result as above + + switch (number) { + case 1: + word = "one"; + break; + case 2: + word = "two"; + break; + case 3: + word = "three"; + break; + default: + word = "unknown"; + break; + } + + System.out.print(number); + System.out.print(word); + + // switch blocks fall through + + String food = "apple"; + switch (food) { + case "apple": + case "banana": + case "cherry": + System.out.println("Fruit!"); + break; + case "asparagus": + case "broccoli": + case "carrot": + System.out.println("Vegetable!"); + break; + } + } + +} From b42cec2a6e62045379fe6f579464262f124863ff Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 14:45:36 -0400 Subject: [PATCH 43/52] ch06 revisions --- ch06/Loops.java | 28 +++++++++++++++-------- ch06/Strings.java | 58 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/ch06/Loops.java b/ch06/Loops.java index f333df9..4f59564 100644 --- a/ch06/Loops.java +++ b/ch06/Loops.java @@ -1,5 +1,5 @@ /** - * Examples from Chapter 6. + * Demonstrates uses of loops. */ public class Loops { @@ -26,7 +26,7 @@ public static void plusplus() { int i = 1; while (i <= 5) { System.out.println(i); - i++; // add 1 to i + i++; // add 1 to i } } @@ -34,7 +34,14 @@ public static void appreciate() { int i = 2; while (i <= 8) { System.out.print(i + ", "); - i += 2; // add 2 to i + i += 2; // add 2 to i + } + System.out.println("Who do we appreciate?"); + } + + public static void appreciate2() { + for (int i = 2; i <= 8; i += 2) { + System.out.print(i + ", "); } System.out.println("Who do we appreciate?"); } @@ -57,22 +64,25 @@ public static void nested() { } public static void main(String[] args) { - System.out.println("countdown"); + System.out.println("\ncountdown"); countdown(3); - System.out.println("sequence"); + System.out.println("\nsequence"); sequence(10); - System.out.println("plusplus"); + System.out.println("\nplusplus"); plusplus(); - System.out.println("appreciate"); + System.out.println("\nappreciate"); appreciate(); - System.out.println("loopvar"); + System.out.println("\nappreciate2"); + appreciate2(); + + System.out.println("\nloopvar"); loopvar(); - System.out.println("nested"); + System.out.println("\nnested"); nested(); } diff --git a/ch06/Strings.java b/ch06/Strings.java index 09b817f..ac6bc05 100644 --- a/ch06/Strings.java +++ b/ch06/Strings.java @@ -1,5 +1,7 @@ +import java.util.Scanner; + /** - * Demonstrates uses of Strings. + * Demonstrates uses of strings. */ public class Strings { @@ -10,8 +12,8 @@ public static void main(String[] args) { String fruit = "banana"; char letter0 = fruit.charAt(0); - if (letter0 == 'a') { - System.out.println('?'); + if (letter0 == 'A') { + System.out.println("It's an A!"); } System.out.print("Roman alphabet: "); @@ -26,6 +28,17 @@ public static void main(String[] args) { } System.out.println(); + // Which loop to use + + Scanner in = new Scanner(System.in); + System.out.print("Enter a number: "); + while (!in.hasNextDouble()) { + String word = in.next(); + System.err.println(word + " is not a number"); + System.out.print("Enter a number: "); + } + double number = in.nextDouble(); + // String iteration for (int i = 0; i < fruit.length(); i++) { @@ -43,8 +56,30 @@ public static void main(String[] args) { int index = fruit.indexOf('a'); int index2 = fruit.indexOf('a', 2); + // Substrings + + System.out.println(fruit.substring(0, 3)); + System.out.println(fruit.substring(2, 5)); + System.out.println(fruit.substring(6, 6)); + + System.out.println(fruit.substring(0)); + System.out.println(fruit.substring(2)); + System.out.println(fruit.substring(6)); + // String comparison + System.out.print("Play again? "); + String answer = in.nextLine(); + if (answer == "yes") { // wrong! + System.out.println("Let's go!"); + } else { + System.out.println("Goodbye!"); + } + + if (answer.equals("yes")) { // correct + System.out.println("Let's go!"); + } + String name1 = "Alan Turing"; String name2 = "Ada Lovelace"; if (name1.equals(name2)) { @@ -52,24 +87,13 @@ public static void main(String[] args) { } int diff = name1.compareTo(name2); - if (diff == 0) { - System.out.println("The names are the same."); - } else if (diff < 0) { + if (diff < 0) { System.out.println("name1 comes before name2."); } else if (diff > 0) { System.out.println("name2 comes before name1."); + } else { + System.out.println("The names are the same."); } - - // Substrings - - System.out.println(fruit.substring(0)); - System.out.println(fruit.substring(2)); - System.out.println(fruit.substring(6)); - - System.out.println(fruit.substring(0, 3)); - System.out.println(fruit.substring(2, 5)); - System.out.println(fruit.substring(6, 6)); - } /** From 69c58c27072fb011ec622e21bf8ccd0793bd7501 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 14:59:40 -0400 Subject: [PATCH 44/52] ch07 revisions --- ch07/ArrayExamples.java | 27 ++++++++++++++------------- ch07/Doubloon.java | 9 ++++----- ch07/Histogram.java | 3 +-- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/ch07/ArrayExamples.java b/ch07/ArrayExamples.java index 0ac26f3..9fecdc0 100644 --- a/ch07/ArrayExamples.java +++ b/ch07/ArrayExamples.java @@ -30,6 +30,7 @@ public static void main(String[] args) { System.out.println(counts[i]); } + // displaying arrays int[] array = {1, 2, 3, 4}; printArray(array); @@ -49,9 +50,9 @@ public static void main(String[] args) { // copying with Arrays class double[] c = Arrays.copyOf(a, a.length); - // traversal + // traversing arrays for (int i = 0; i < a.length; i++) { - a[i] = Math.pow(a[i], 2.0); + a[i] *= a[i]; } // search @@ -66,10 +67,10 @@ public static void main(String[] args) { /** * Prints the elements of an array. */ - public static void printArray(int[] array) { - System.out.print("{" + array[0]); - for (int i = 1; i < array.length; i++) { - System.out.print(", " + array[i]); + public static void printArray(int[] a) { + System.out.print("{" + a[0]); + for (int i = 1; i < a.length; i++) { + System.out.print(", " + a[i]); } System.out.println("}"); } @@ -77,22 +78,22 @@ public static void printArray(int[] array) { /** * Returns the index of the target in the array, or -1 if not found. */ - public static int search(double[] a, double target) { - for (int i = 0; i < a.length; i++) { - if (a[i] == target) { + public static int search(double[] array, double target) { + for (int i = 0; i < array.length; i++) { + if (array[i] == target) { return i; } } - return -1; + return -1; // not found } /** * Returns the total of the elements in an array. */ - public static double sum(double[] a) { + public static double sum(double[] array) { double total = 0.0; - for (int i = 0; i < a.length; i++) { - total += a[i]; + for (int i = 0; i < array.length; i++) { + total += array[i]; } return total; } diff --git a/ch07/Doubloon.java b/ch07/Doubloon.java index 61103e0..aba5ed7 100644 --- a/ch07/Doubloon.java +++ b/ch07/Doubloon.java @@ -2,7 +2,7 @@ * Example from the end of Chapter 7. */ public class Doubloon { - + public static boolean isDoubloon(String s) { // count the number of times each letter appears @@ -21,10 +21,9 @@ public static boolean isDoubloon(String s) { } return true; } - + public static void main(String[] args) { - System.out.println(isDoubloon("Mama")); - System.out.println(isDoubloon("Lama")); + System.out.println(isDoubloon("Mama")); // true + System.out.println(isDoubloon("Lama")); // false } - } diff --git a/ch07/Histogram.java b/ch07/Histogram.java index 32b029c..fe9f0b7 100644 --- a/ch07/Histogram.java +++ b/ch07/Histogram.java @@ -31,8 +31,7 @@ public static int inRange(int[] a, int low, int high) { } public static void main(String[] args) { - int numValues = 8; - int[] array = randomArray(numValues); + int[] array = randomArray(8); ArrayExamples.printArray(array); int[] scores = randomArray(30); From 4ce61936e55cbcac556a88f37537d54a5d8e46d7 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 15:09:19 -0400 Subject: [PATCH 45/52] ch08 revisions --- ch08/CodingBat.java | 23 +++++++++++----- ch08/{Recursion.java => Examples.java} | 38 ++++++++++++-------------- ch08/Series.java | 3 -- 3 files changed, 34 insertions(+), 30 deletions(-) rename ch08/{Recursion.java => Examples.java} (92%) diff --git a/ch08/CodingBat.java b/ch08/CodingBat.java index c51f2f4..f6ad0d5 100644 --- a/ch08/CodingBat.java +++ b/ch08/CodingBat.java @@ -3,26 +3,35 @@ */ public class CodingBat { - public static String noX(String str) { + /** + * See https://codingbat.com/prob/p118230. + */ + public String noX(String str) { if (str.length() == 0) { return ""; } - char c = str.charAt(0); - if (c == 'x') { - return noX(str.substring(1)); + char first = str.charAt(0); + String rest = str.substring(1); + String recurse = noX(rest); + if (first == 'x') { + return recurse; } else { - return c + noX(str.substring(1)); + return first + recurse; } } + /** + * See https://codingbat.com/prob/p135988. + */ public int array11(int[] nums, int index) { if (index >= nums.length) { return 0; } + int recurse = array11(nums, index + 1); if (nums[index] == 11) { - return 1 + array11(nums, index + 1); + return recurse + 1; } else { - return array11(nums, index + 1); + return recurse; } } diff --git a/ch08/Recursion.java b/ch08/Examples.java similarity index 92% rename from ch08/Recursion.java rename to ch08/Examples.java index 04ac198..39b22dd 100644 --- a/ch08/Recursion.java +++ b/ch08/Examples.java @@ -1,19 +1,4 @@ -public class Recursion { - - public static void main(String[] args) { - System.out.println("countdown"); - countdown(3); - - System.out.println("nLines"); - nLines(3); - - System.out.println("countup"); - countup(3); - - System.out.println("displayBinary"); - displayBinary(23); - System.out.println(); - } +public class Examples { public static void countdown(int n) { if (n == 0) { @@ -24,10 +9,6 @@ public static void countdown(int n) { } } - public static void newLine() { - System.out.println(); - } - public static void nLines(int n) { if (n > 0) { System.out.println(); @@ -56,4 +37,21 @@ public static void displayBinary(int value) { } } + public static void main(String[] args) { + System.out.println("countdown"); + countdown(3); + + System.out.println("nLines"); + nLines(3); + + // forever("Ha!"); + + System.out.println("countup"); + countup(3); + + System.out.println("displayBinary"); + displayBinary(23); + System.out.println(); + } + } diff --git a/ch08/Series.java b/ch08/Series.java index 86e8148..fb1c860 100644 --- a/ch08/Series.java +++ b/ch08/Series.java @@ -1,6 +1,3 @@ -/** - * Examples from Chapter 8. - */ public class Series { public static int factorial(int n) { From 6cc2f1082f6bfd4e0781e4bfbf36a6fd02085cec Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 15:29:48 -0400 Subject: [PATCH 46/52] ch09 revisions --- ch09/ArgValid.java | 20 ++++++++++++++++++++ ch09/BigInt.java | 20 ++++++++++++++++++++ ch09/Objects.java | 36 ++++++++++++++++++++---------------- ch09/Tables.java | 38 +++++++++++++------------------------- 4 files changed, 73 insertions(+), 41 deletions(-) create mode 100644 ch09/ArgValid.java create mode 100644 ch09/BigInt.java diff --git a/ch09/ArgValid.java b/ch09/ArgValid.java new file mode 100644 index 0000000..29e4d0a --- /dev/null +++ b/ch09/ArgValid.java @@ -0,0 +1,20 @@ +/** + * Example of argument validation. + */ +public class ArgValid { + + public static boolean isCapitalized(String str) { + if (str == null || str.isEmpty()) { + return false; + } + return Character.isUpperCase(str.charAt(0)); + } + + public static void main(String[] args) { + System.out.println(isCapitalized("Hi!")); + System.out.println(isCapitalized("bye")); + System.out.println(isCapitalized("")); + System.out.println(isCapitalized(null)); + } + +} diff --git a/ch09/BigInt.java b/ch09/BigInt.java new file mode 100644 index 0000000..05b4da5 --- /dev/null +++ b/ch09/BigInt.java @@ -0,0 +1,20 @@ +import java.math.BigInteger; + +/** + * BigInteger examples. + */ +public class BigInt { + + public static void main(String[] args) { + long x = 17; + BigInteger big = BigInteger.valueOf(x); + + String s = "12345678901234567890"; + BigInteger bigger = new BigInteger(s); + + BigInteger a = BigInteger.valueOf(17); + BigInteger b = BigInteger.valueOf(1700000000); + BigInteger c = a.add(b); + } + +} diff --git a/ch09/Objects.java b/ch09/Objects.java index 6dde3a0..ae7b350 100644 --- a/ch09/Objects.java +++ b/ch09/Objects.java @@ -1,5 +1,3 @@ -import java.math.BigInteger; - /** * Demonstrates uses of objects and wrappers. */ @@ -14,22 +12,40 @@ public static void main(String[] args) { char[] array = {'c', 'a', 't'}; String word = "dog"; + String word1 = new String("dog"); // creates a string object + String word2 = "dog"; // implicitly creates a string object + + // the null keyword + + String name0 = null; + int[] combo = null; + // System.out.println(name0.length()); // NullPointerException + // System.out.println(combo[0]); // NullPointerException + // Strings are immutable String name = "Alan Turing"; String upperName = name.toUpperCase(); + name.toUpperCase(); // ignores the return value + System.out.println(name); + name = name.toUpperCase(); // references the new string + System.out.println(name); + String text = "Computer Science is fun!"; text = text.replace("Computer Science", "CS"); // Wrapper classes + Integer i = Integer.valueOf(5); + System.out.println(i.equals(5)); // displays true + Integer x = Integer.valueOf(123); Integer y = Integer.valueOf(123); - if (x == y) { // false + if (x == y) { // false System.out.println("x and y are the same object"); } - if (x.equals(y)) { // true + if (x.equals(y)) { // true System.out.println("x and y have the same value"); } @@ -38,18 +54,6 @@ public static void main(String[] args) { num = 12345; str = Integer.toString(num); - - // BigInteger arithmetic - - long z = 17; - BigInteger big = BigInteger.valueOf(z); - - String s = "12345678901234567890"; - BigInteger bigger = new BigInteger(s); - - BigInteger a = BigInteger.valueOf(17); - BigInteger b = BigInteger.valueOf(1700000000); - BigInteger c = a.add(b); } } diff --git a/ch09/Tables.java b/ch09/Tables.java index f1a5423..1ceaec9 100644 --- a/ch09/Tables.java +++ b/ch09/Tables.java @@ -4,73 +4,61 @@ public class Tables { public static void printRow() { - int i = 1; - while (i <= 6) { + for (int i = 1; i <= 6; i++) { System.out.printf("%4d", 2 * i); - i = i + 1; } System.out.println(); } public static void printRow(int n) { - int i = 1; - while (i <= 6) { + for (int i = 1; i <= 6; i++) { System.out.printf("%4d", n * i); // generalized n - i = i + 1; } System.out.println(); } public static void printTable() { - int i = 1; - while (i <= 6) { + for (int i = 1; i <= 6; i++) { printRow(i); - i = i + 1; } } public static void printTable(int rows) { - int i = 1; - while (i <= rows) { // generalized rows + for (int i = 1; i <= rows; i++) { // generalized rows printRow(i); - i = i + 1; } } public static void printRow(int n, int cols) { - int i = 1; - while (i <= cols) { // generalized cols + for (int i = 1; i <= cols; i++) { // generalized cols System.out.printf("%4d", n * i); - i = i + 1; } System.out.println(); } public static void printTable2(int rows) { - int i = 1; - while (i <= rows) { - printRow(i, rows); // added rows argument - i = i + 1; + for (int i = 1; i <= rows; i++) { + printRow(i, rows); } } public static void main(String[] args) { - System.out.println("printRow()"); + System.out.println("\nprintRow()"); printRow(); - System.out.println("printRow(6)"); + System.out.println("\nprintRow(6)"); printRow(6); - System.out.println("printTable()"); + System.out.println("\nprintTable()"); printTable(); - System.out.println("printTable(6)"); + System.out.println("\nprintTable(6)"); printTable(6); - System.out.println("printRow(6, 6)"); + System.out.println("\nprintRow(6, 6)"); printRow(6, 6); - System.out.println("printTable2(6)"); + System.out.println("\nprintTable2(6)"); printTable2(6); } From fbd0dca5e78e17f0ea4af5de6febe9dd634f49d2 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 16:15:28 -0400 Subject: [PATCH 47/52] ch10 revisions --- ch10/Append.java | 13 ------------- ch10/Builder.java | 35 +++++++++++++++++++++++++++++++++++ ch10/PointRect.java | 21 +++++++++++++++++---- 3 files changed, 52 insertions(+), 17 deletions(-) delete mode 100644 ch10/Append.java create mode 100644 ch10/Builder.java diff --git a/ch10/Append.java b/ch10/Append.java deleted file mode 100644 index 98a9c10..0000000 --- a/ch10/Append.java +++ /dev/null @@ -1,13 +0,0 @@ -import java.util.Scanner; -public class Append { - public static void main(String[] args) { - Scanner in = new Scanner(System.in); - System.out.println("Enter 10 lines:"); - String text = ""; - for (int i = 0; i < 10; i++) { - String line = in.nextLine(); // new string - text = text + line + '\n'; // two more strings - } - System.out.print("You entered:\n" + text); - } -} diff --git a/ch10/Builder.java b/ch10/Builder.java new file mode 100644 index 0000000..8fe955e --- /dev/null +++ b/ch10/Builder.java @@ -0,0 +1,35 @@ +import java.util.Scanner; + +/* + * StringBuilder example. + */ +public class Builder { + + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + + // less efficient + System.out.println("Enter 10 lines:"); + + String slow = ""; + for (int i = 0; i < 10; i++) { + String line = in.nextLine(); // new string + slow = slow + line + '\n'; // two more strings + } + System.out.print("You entered:\n" + slow); + + // more efficient + System.out.println("Enter 10 lines:"); + + StringBuilder text = new StringBuilder(); + for (int i = 0; i < 10; i++) { + String line = in.nextLine(); + text.append(line); + text.append('\n'); + } + System.out.print("You entered:\n" + text); + + String result = text.toString(); + } + +} diff --git a/ch10/PointRect.java b/ch10/PointRect.java index cb0af07..301dd90 100644 --- a/ch10/PointRect.java +++ b/ch10/PointRect.java @@ -9,27 +9,40 @@ public class PointRect { public static void main(String[] args) { Point blank; blank = new Point(3, 4); - System.out.println(blank); int x = blank.x; System.out.println(blank.x + ", " + blank.y); int sum = blank.x * blank.x + blank.y * blank.y; + // objects as parameters + Point p1 = new Point(0, 0); Point p2 = new Point(3, 4); + double temp = distance(p1, p2); double dist = p1.distance(p2); // dist is 5.0 + System.out.println(blank); + + // objects as return values Rectangle box = new Rectangle(0, 0, 100, 200); - moveRect(box, 50, 100); + Point center = findCenter(box); + + // rectangles are mutable + + moveRect(box, 50, 100); // now at (50, 100, 100, 200) System.out.println(box); + + box = new Rectangle(0, 0, 100, 200); box.translate(50, 100); + // aliasing revisited + Rectangle box1 = new Rectangle(0, 0, 100, 200); Rectangle box2 = box1; - System.out.println(box2.width); box1.grow(50, 50); - System.out.println(box2.width); + System.out.println(box1); + System.out.println(box2); } /** From af3f177f4c923ea5c2730bf906c2bdd6f7304e6c Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Wed, 17 Jun 2020 16:37:41 -0400 Subject: [PATCH 48/52] ch11 revisions --- ch11/Time.java | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/ch11/Time.java b/ch11/Time.java index 951d5bf..fe5bfd6 100644 --- a/ch11/Time.java +++ b/ch11/Time.java @@ -25,6 +25,30 @@ public Time(int hour, int minute, double second) { this.second = second; } + public int getHour() { + return this.hour; + } + + public int getMinute() { + return this.minute; + } + + public double getSecond() { + return this.second; + } + + public void setHour(int hour) { + this.hour = hour; + } + + public void setMinute(int minute) { + this.minute = minute; + } + + public void setSecond(double second) { + this.second = second; + } + /** * Prints the time in a simple format. */ @@ -48,9 +72,10 @@ public String toString() { * Tests whether two times are equivalent. */ public boolean equals(Time that) { + final double DELTA = 0.001; return this.hour == that.hour && this.minute == that.minute - && this.second == that.second; + && Math.abs(this.second - that.second) < DELTA; } /** @@ -72,6 +97,7 @@ public Time add(Time t2) { sum.hour = this.hour + t2.hour; sum.minute = this.minute + t2.minute; sum.second = this.second + t2.second; + if (sum.second >= 60.0) { sum.second -= 60.0; sum.minute += 1; @@ -80,22 +106,10 @@ public Time add(Time t2) { sum.minute -= 60; sum.hour += 1; } - return sum; - } - - /** - * Adds the given number of seconds to this object (modifier). - */ - public void increment(double seconds) { - this.second += seconds; - while (this.second >= 60.0) { - this.second -= 60.0; - this.minute += 1; - } - while (this.minute >= 60) { - this.minute -= 60; - this.hour += 1; + if (sum.hour >= 24) { + sum.hour -= 24; } + return sum; } } From 6b758bd58cfd697764d19fc38e51b2886b0b84ac Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Mon, 29 Jun 2020 16:37:35 -0400 Subject: [PATCH 49/52] fix Scanner bug --- ch06/Strings.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ch06/Strings.java b/ch06/Strings.java index ac6bc05..f8b40f0 100644 --- a/ch06/Strings.java +++ b/ch06/Strings.java @@ -38,6 +38,7 @@ public static void main(String[] args) { System.out.print("Enter a number: "); } double number = in.nextDouble(); + in.nextLine(); // read the newline // String iteration From 76a6ee26ca7409216766342b6dd19c84b022d6d3 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Sat, 30 Jan 2021 13:42:14 -0500 Subject: [PATCH 50/52] revised Checkstyle and Formatter --- Checkstyle.xml | 83 +++--- Formatter.xml | 704 +++++++++++++++++++++++++++---------------------- user.dict | 2 + 3 files changed, 442 insertions(+), 347 deletions(-) create mode 100644 user.dict diff --git a/Checkstyle.xml b/Checkstyle.xml index 6cf2192..6788535 100644 --- a/Checkstyle.xml +++ b/Checkstyle.xml @@ -1,85 +1,110 @@ + "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" + "https://checkstyle.org/dtds/configuration_1_3.dtd"> + - + - + - + + - + - + + + + + - - + + + - + - + - + - + + + + + + + + + + + + + + + + + + - + + + + - + - + + @@ -92,42 +117,38 @@ Checkstyle configuration for Think Java, 2nd Edition. - + - - + - + + + - - - + + - + diff --git a/Formatter.xml b/Formatter.xml index f97740d..a16cdb8 100644 --- a/Formatter.xml +++ b/Formatter.xml @@ -1,318 +1,390 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/user.dict b/user.dict new file mode 100644 index 0000000..11b2406 --- /dev/null +++ b/user.dict @@ -0,0 +1,2 @@ +chris +mayfield From c215058330addb5206b3def6e1ad038058c72fdb Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Sat, 30 Jan 2021 13:42:29 -0500 Subject: [PATCH 51/52] tidy up Ch15 --- ch15/Cell.java | 15 +++++++++++---- ch15/Conway.java | 5 +++-- ch15/GridCanvas.java | 9 +++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/ch15/Cell.java b/ch15/Cell.java index d468b6d..5b6a0f9 100644 --- a/ch15/Cell.java +++ b/ch15/Cell.java @@ -3,6 +3,9 @@ /** * A square at a fixed location that changes color. + * + * @author Chris Mayfield + * @version 7.1.0 */ public class Cell { @@ -40,28 +43,32 @@ public void draw(Graphics g) { } /** - * @return true if the cell is OFF + * Tests whether the cell is off. + * + * @return true if the cell is off */ public boolean isOff() { return state == 0; } /** - * @return true if the cell is ON + * Tests whether the cell is on. + * + * @return true if the cell is on */ public boolean isOn() { return state == 1; } /** - * Sets the cell's state to OFF. + * Sets the cell's state to off. */ public void turnOff() { state = 0; } /** - * Sets the cell's state to ON. + * Sets the cell's state to on. */ public void turnOn() { state = 1; diff --git a/ch15/Conway.java b/ch15/Conway.java index 93faf28..5ac48c6 100644 --- a/ch15/Conway.java +++ b/ch15/Conway.java @@ -2,6 +2,9 @@ /** * Conway's Game of Life. + * + * @author Chris Mayfield + * @version 7.1.0 */ public class Conway { @@ -109,8 +112,6 @@ public void update() { /** * The simulation loop. - * - * @param rate frames per second */ private void mainloop() { while (true) { diff --git a/ch15/GridCanvas.java b/ch15/GridCanvas.java index c936135..3856a57 100644 --- a/ch15/GridCanvas.java +++ b/ch15/GridCanvas.java @@ -3,6 +3,9 @@ /** * 2D array of cells representing a rectangular grid. + * + * @author Chris Mayfield + * @version 7.1.0 */ public class GridCanvas extends Canvas { @@ -33,6 +36,8 @@ public GridCanvas(int rows, int cols, int size) { } /** + * Gets the number of rows. + * * @return number of rows */ public int numRows() { @@ -40,6 +45,8 @@ public int numRows() { } /** + * Gets the number of columns. + * * @return number of columns */ public int numCols() { @@ -47,6 +54,8 @@ public int numCols() { } /** + * Gets the cell at index (r, c). + * * @param r row index * @param c column index * @return the cell From a15b84d85862d0e3236fc0fe8655526a340b1856 Mon Sep 17 00:00:00 2001 From: Chris Mayfield Date: Fri, 20 Aug 2021 10:32:04 -0400 Subject: [PATCH 52/52] Checkstyle 8.44, Eclipse 2021-06 --- Checkstyle.xml | 3 ++- Formatter.xml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Checkstyle.xml b/Checkstyle.xml index 6788535..36dbd1f 100644 --- a/Checkstyle.xml +++ b/Checkstyle.xml @@ -4,7 +4,7 @@ "https://checkstyle.org/dtds/configuration_1_3.dtd"> @@ -82,6 +82,7 @@ Checkstyle configuration for Think Java, 2nd Edition. + diff --git a/Formatter.xml b/Formatter.xml index a16cdb8..ab6e68e 100644 --- a/Formatter.xml +++ b/Formatter.xml @@ -1,6 +1,6 @@ - - + +