├── .gitignore ├── LICENSE ├── README.md ├── ch02 ├── examples │ ├── HelloJava.java │ ├── HelloJava2.java │ └── HelloWorld.java ├── exercises │ ├── HelloJava.java │ └── HelloWorld.java └── solutions │ ├── GoodbyeJava.java │ └── GoodbyeWorld.java ├── ch03 ├── examples │ ├── MyTest.java │ ├── animals │ │ └── birds │ │ │ ├── BigBird.class │ │ │ └── BigBird.java │ ├── spaceblaster-src │ │ ├── manifest.mf │ │ └── spaceblaster │ │ │ └── game │ │ │ ├── Game.java │ │ │ ├── Planetoid.java │ │ │ └── SpaceShip.java │ ├── spaceblaster.jar │ └── spaceblaster │ │ ├── docs │ │ ├── help1.html │ │ └── help2.html │ │ ├── game │ │ ├── Game.class │ │ ├── Planetoid.class │ │ └── SpaceShip.class │ │ └── images │ │ ├── planetoid.png │ │ └── spaceship.png ├── exercises │ ├── HelloJar.java │ └── manifest.mf └── solutions │ ├── HelloComponent2.class │ ├── HelloJar.class │ ├── HelloJar.java │ ├── hello.jar │ └── manifest.mf ├── ch04 ├── examples │ ├── EnhancedForDemo.java │ ├── EuclidGCD.java │ ├── ForDemo.java │ ├── HelloJava.java │ ├── IfDemo.java │ ├── SwitchDemo.java │ └── WhileDemo.java ├── exercises │ ├── Euclid.java │ └── SimpleTriangle.java └── solutions │ ├── Euclid.java │ ├── SimpleTriangle.java │ └── VisualTriangle.java ├── ch05 ├── examples │ ├── Apple.java │ ├── Field.java │ ├── HelloJava3.java │ ├── PrintAppleDetails.java │ ├── PrintAppleDetails2.java │ ├── PrintAppleDetails3.java │ ├── PrintAppleDetails4.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── Physicist.java │ │ └── Tree.java ├── exercises │ ├── Zoo.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── Physicist.java │ │ └── Tree.java └── solutions │ ├── Zoo.java │ ├── Zoo2.java │ ├── Zoo3.java │ └── game │ ├── Apple.java │ ├── AppleToss.java │ ├── Field.java │ ├── GamePiece.java │ ├── Hedge.java │ ├── Physicist.java │ └── Tree.java ├── ch06 ├── examples │ ├── Euclid2.java │ └── LogTest.java ├── exercises │ ├── Euclid2.java │ ├── HelloZero.java │ └── Pause.java.bad └── solutions │ ├── Euclid2.java │ ├── Euclid3.java │ ├── GCDException.java │ ├── HelloZero.java │ ├── Pause.java │ └── severe.properties ├── ch07 ├── examples │ ├── RawType.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Hedge.java │ │ ├── Physicist.java │ │ └── Tree.java ├── exercises │ ├── Employee.java │ ├── EmployeeList.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Hedge.java │ │ ├── Physicist.java │ │ └── Tree.java └── solutions │ ├── Employee.java │ ├── Employee2.java │ ├── EmployeeList.java │ ├── EmployeeList2.java │ └── game │ ├── Apple.java │ ├── AppleToss.java │ ├── Field.java │ ├── GamePiece.java │ ├── GameUtilities.java │ ├── Hedge.java │ ├── Physicist.java │ └── Tree.java ├── ch08 ├── examples │ ├── ValidEmail.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Physicist.java │ │ └── Tree.java ├── exercises │ └── HelloChapter8.java └── solutions │ └── HelloChapter8.java ├── ch09 ├── examples │ ├── Interruption.java │ ├── Thready.java │ ├── Thready2.java │ ├── URLConsumer.java │ ├── URLConsumer3.java │ ├── URLConsumer4.java │ ├── URLDemo.java │ ├── URLDemo2.java.preview │ ├── URLDemo3.java.preview │ ├── URLDemo4.java.preview │ ├── URLProducer.java │ ├── URLProducer4.java │ ├── URLQueue.java │ ├── VirtualDemo.java.preview │ ├── VirtualDemo2.java.preview │ └── VirtualThready.java.preview ├── exercises │ ├── Clock.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Hedge.java │ │ ├── Physicist.java │ │ └── Tree.java └── solutions │ ├── Clock.java │ └── game │ ├── Apple.java │ ├── AppleToss.java │ ├── Field.java │ ├── GamePiece.java │ ├── GameUtilities.java │ ├── Hedge.java │ ├── Physicist.java │ └── Tree.java ├── ch10 ├── examples │ ├── AccessNIO.java │ ├── ListIt.java │ ├── ParseKeyboard.java │ └── access.txt ├── exercises │ └── Count.java └── solutions │ ├── Count1.java │ ├── Count2.java │ ├── Count3.java │ ├── Count4.java │ └── countlog.txt ├── ch11 ├── examples │ ├── Adjuster.java │ ├── PaidEmployee.java │ ├── Report.java │ ├── VirtualDemo2.java.preview │ ├── VirtualDemo3.java.preview │ └── WeekDayGenerator.java ├── exercises │ ├── Adjuster.java │ ├── PaidEmployee.java │ └── Report.java └── solutions │ ├── Adjuster.java │ ├── PaidEmployee.java │ ├── PaidEmployee2.java │ ├── Report.java │ └── Report2.java ├── ch12 ├── examples │ ├── ActionDemo1.java │ ├── ActionDemo2.java │ ├── BorderLayoutDemo.java │ ├── Buttons.java │ ├── HelloJavaAgain.java │ ├── HelloMouse.java │ ├── HelloMouseHelper.java │ ├── Labels.java │ ├── MenuDemo.java │ ├── ModalDemo.java │ ├── NestedPanelDemo.java │ ├── PhoneGridDemo.java │ ├── ProgressDemo.java │ ├── TextInputs.java │ ├── Widget.java │ ├── check.png │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Hedge.java │ │ ├── Physicist.java │ │ └── Tree.java ├── exercises │ ├── Calculator.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Hedge.java │ │ ├── Physicist.java │ │ └── Tree.java └── solutions │ ├── Calculator.java │ ├── Calculator2.java │ └── game │ ├── Apple.java │ ├── AppleToss.java │ ├── Field.java │ ├── GamePiece.java │ ├── GameUtilities.java │ ├── Hedge.java │ ├── Physicist.java │ └── Tree.java ├── ch13 ├── examples │ ├── DateAtHost.java │ ├── IconLabel.java │ ├── Post.java │ ├── ReadUrl.java │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Hedge.java │ │ ├── Multiplayer.java │ │ ├── Physicist.java │ │ └── Tree.java ├── exercises │ └── game │ │ ├── Apple.java │ │ ├── AppleToss.java │ │ ├── Field.java │ │ ├── GamePiece.java │ │ ├── GameUtilities.java │ │ ├── Hedge.java │ │ ├── Multiplayer.java │ │ ├── Physicist.java │ │ └── Tree.java └── solutions │ ├── FDClient.java │ ├── FDServer.java │ ├── FDServer2.java.preview │ ├── NetworkInt.java │ └── game │ ├── Apple.java │ ├── AppleToss.java │ ├── Field.java │ ├── GamePiece.java │ ├── GameUtilities.java │ ├── Hedge.java │ ├── Multiplayer.java │ ├── Physicist.java │ └── Tree.java ├── game ├── Apple.java ├── AppleToss.java ├── Field.java ├── GamePiece.java ├── GameUtilities.java ├── Hedge.java ├── Multiplayer.java ├── Physicist.java └── Tree.java └── quiz ├── .gitignore ├── build.sh ├── lj6review.jar ├── manifest.mf ├── quizgen.pl └── src ├── com └── loyinc │ ├── quiz │ ├── Answer.java │ ├── Chapter.java │ ├── Question.java │ ├── QuestionPane.java │ ├── QuizFrame.java │ ├── QuizPane.java │ ├── QuizTree.java │ ├── Quizzes.java │ └── Review.java │ └── util │ ├── CWButton.java │ ├── CWLabel.java │ ├── Config.java │ ├── RollingButtonGroup.java │ ├── StateProvider.java │ └── StateProviderCellRenderer.java └── res ├── ch_done_ok.png ├── ch_filled.png ├── ch_list.png ├── ch_list_inv.png ├── ch_not_ok.png ├── ch_open.png ├── correct01.png ├── cover-480.png ├── cover.png ├── notquite01.png ├── quiz-data.txt └── unknown01.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | # Don't skip as we occasionally provide pre-compiled classes for readers 3 | #*.class 4 | 5 | # Log file 6 | *.log 7 | 8 | # BlueJ files 9 | *.ctxt 10 | 11 | # Mobile Tools for Java (J2ME) 12 | .mtj.tmp/ 13 | 14 | # Package Files # 15 | #*.jar # we include a few jars as solutions and pre-built apps 16 | *.war 17 | *.nar 18 | *.ear 19 | *.zip 20 | *.tar.gz 21 | *.rar 22 | 23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 24 | hs_err_pid* 25 | 26 | # VS Code stuffs 27 | settings.json 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # learnjava6e 2 | Code examples for O'Reilly's Learning Java, 6e by Marc Loy, Patrick Niemeyer, and Daniel Leuck 3 | -------------------------------------------------------------------------------- /ch02/examples/HelloJava.java: -------------------------------------------------------------------------------- 1 | package ch02.examples; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * A bare bones graphical version of Hello World. 7 | */ 8 | public class HelloJava { 9 | public static void main( String[] args ) { 10 | JFrame frame = new JFrame( "Hello, Java!" ); 11 | JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); 12 | frame.add(label); 13 | frame.setSize( 300, 300 ); 14 | frame.setVisible( true ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch02/examples/HelloJava2.java: -------------------------------------------------------------------------------- 1 | package ch02.examples; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | /** 8 | * An upgraded graphical application with interactivity! 9 | */ 10 | public class HelloJava2 { 11 | public static void main( String[] args ) { 12 | JFrame frame = new JFrame( "HelloJava2" ); 13 | frame.add( new HelloComponent2("Hello, Java!") ); 14 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 15 | frame.setSize( 300, 300 ); 16 | frame.setVisible( true ); 17 | } 18 | } 19 | 20 | /* 21 | * Inheritence (the "extends" keyword below) and interfaces 22 | * (the "implements MouseMotionListener" portion) are covered in 23 | * more detail in Chapter 5. 24 | */ 25 | class HelloComponent2 extends JComponent implements MouseMotionListener { 26 | String theMessage; 27 | int messageX = 125, messageY = 95; // Coordinates of the message 28 | 29 | /** 30 | * Create a new component that can draw its message at an arbitrary position. 31 | * That position can be changed by dragging the mouse; we attach a listener 32 | * to pick up those drag events. 33 | */ 34 | public HelloComponent2( String message ) { 35 | theMessage = message; 36 | addMouseMotionListener(this); 37 | } 38 | 39 | public void paintComponent( Graphics g ) { 40 | g.drawString( theMessage, messageX, messageY ); 41 | } 42 | 43 | public void mouseDragged(MouseEvent e) { 44 | // Save the mouse coordinates and paint the message. 45 | messageX = e.getX(); 46 | messageY = e.getY(); 47 | repaint(); 48 | } 49 | 50 | public void mouseMoved(MouseEvent e) { 51 | // Ignore simple movements 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ch02/examples/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package ch02.examples; 2 | 3 | /** 4 | * The canonical first program: Hello, world! 5 | */ 6 | public class HelloWorld { 7 | public static void main( String[] args ) { 8 | System.out.println("Hello, world!"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch02/exercises/HelloJava.java: -------------------------------------------------------------------------------- 1 | package ch02.exercises; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * A simple variation on the HelloJava class. 7 | * Added the step to quit when the window is closed. 8 | * (See HelloWorld.java for the commandline version.) 9 | */ 10 | public class HelloJava { 11 | public static void main( String[] args ) { 12 | JFrame frame = new JFrame( "Chapter 2, Exercise 1" ); 13 | JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); 14 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 15 | frame.add(label); 16 | frame.setSize( 300, 200 ); 17 | frame.setVisible( true ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch02/exercises/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package ch02.exercises; 2 | 3 | /** 4 | * A simple variation on the commandline version 5 | * of Hello, world. (See HelloJava.java for the 6 | * graphical version.) 7 | */ 8 | public class HelloWorld { 9 | public static void main( String[] args ) { 10 | System.out.println("Hello, world!"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ch02/solutions/GoodbyeJava.java: -------------------------------------------------------------------------------- 1 | package ch02.solutions; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * A simple variation on the HelloJava class. 7 | * Added the step to quit when the window is closed. 8 | * (See GoodbyeWorld.java for the commandline version.) 9 | */ 10 | public class GoodbyeJava { 11 | public static void main( String[] args ) { 12 | JFrame frame = new JFrame( "Exercise: Goodbye, Java" ); 13 | JLabel label = new JLabel("Goodbye, Java!", JLabel.CENTER ); 14 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 15 | frame.add(label); 16 | frame.setSize( 300, 200 ); 17 | frame.setVisible( true ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch02/solutions/GoodbyeWorld.java: -------------------------------------------------------------------------------- 1 | package ch02.solutions; 2 | 3 | /** 4 | * A simple variation on the commandline version 5 | * of Hello, world. (See GoodbyeJava.java for the 6 | * graphical version.) 7 | */ 8 | public class GoodbyeWorld { 9 | public static void main( String[] args ) { 10 | System.out.println("Goodbye, world!"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ch03/examples/MyTest.java: -------------------------------------------------------------------------------- 1 | // No package declared here. This class will be part of the 2 | // "default" package. 3 | 4 | public class MyTest { 5 | public static void main(String args[]) { 6 | System.out.println("Congrats! You ran MyTest correctly!"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ch03/examples/animals/birds/BigBird.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/examples/animals/birds/BigBird.class -------------------------------------------------------------------------------- /ch03/examples/animals/birds/BigBird.java: -------------------------------------------------------------------------------- 1 | package animals.birds; 2 | 3 | public class BigBird { 4 | public static void main(String args[]) { 5 | System.out.println("This is the animals.birds.BigBird class."); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ch03/examples/spaceblaster-src/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Created-By: 11.0.16 3 | Main-Class: spaceblaster.game.Game 4 | 5 | -------------------------------------------------------------------------------- /ch03/examples/spaceblaster-src/spaceblaster/game/Game.java: -------------------------------------------------------------------------------- 1 | package spaceblaster.game; 2 | 3 | public class Game { 4 | public static void main(String args[]) { 5 | SpaceShip ship = new SpaceShip(); 6 | Planetoid planet = new Planetoid(); 7 | 8 | ship.fireOn(planet); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch03/examples/spaceblaster-src/spaceblaster/game/Planetoid.java: -------------------------------------------------------------------------------- 1 | package spaceblaster.game; 2 | 3 | public class Planetoid { 4 | public void destroy() { 5 | System.out.println("We've been hit! It's as if millions of voices suddenly cried out"); 6 | System.out.println("in terror and were suddenly silenced. I fear... oh wait..."); 7 | System.out.println("Nevermind. I accidentally hit the mute button. We're fine."); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ch03/examples/spaceblaster-src/spaceblaster/game/SpaceShip.java: -------------------------------------------------------------------------------- 1 | package spaceblaster.game; 2 | 3 | public class SpaceShip { 4 | private String laserSound = "pew"; 5 | 6 | public void fireOn(Planetoid target) { 7 | System.out.print("Firing:"); 8 | for (int i = 0; i < 3; i++) { 9 | System.out.print(" " + laserSound); 10 | } 11 | System.out.println("!\n"); 12 | target.destroy(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch03/examples/spaceblaster.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/examples/spaceblaster.jar -------------------------------------------------------------------------------- /ch03/examples/spaceblaster/docs/help1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SpaceBlaster Help, Page 1 5 | 6 | 7 | 12 | 13 | 14 |

Welcome to SpaceBlaster!

15 |

This example doesn't really do much, but it will print a fun message when you run it.

16 |

The help continues on page 2.

17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch03/examples/spaceblaster/docs/help2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SpaceBlaster Help, Page 2 5 | 6 | 7 | 12 | 13 | 14 |

More SpaceBlaster!

15 |

16 | To run the game, you'll need Java 17 or higher and a terminal window. 17 | Type in java -jar spaceblaster.jar and off you go! 18 |

19 |

This help is continued from page 1.

20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch03/examples/spaceblaster/game/Game.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/examples/spaceblaster/game/Game.class -------------------------------------------------------------------------------- /ch03/examples/spaceblaster/game/Planetoid.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/examples/spaceblaster/game/Planetoid.class -------------------------------------------------------------------------------- /ch03/examples/spaceblaster/game/SpaceShip.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/examples/spaceblaster/game/SpaceShip.class -------------------------------------------------------------------------------- /ch03/examples/spaceblaster/images/planetoid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/examples/spaceblaster/images/planetoid.png -------------------------------------------------------------------------------- /ch03/examples/spaceblaster/images/spaceship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/examples/spaceblaster/images/spaceship.png -------------------------------------------------------------------------------- /ch03/exercises/HelloJar.java: -------------------------------------------------------------------------------- 1 | package ch03.exercises; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | /** 8 | * Reusing our graphical application with interactivity! 9 | */ 10 | public class HelloJar { 11 | public static void main( String[] args ) { 12 | String msg = "You cheated! :)"; 13 | if ( HelloJar.class.getProtectionDomain() 14 | .getCodeSource() 15 | .getLocation() 16 | .getFile() 17 | .endsWith(".jar") ) { 18 | // You didn't cheat, so let's fix the message 19 | msg = "Hello from a JAR file!"; 20 | } 21 | JFrame frame = new JFrame( "Hello Jar" ); 22 | frame.add( new HelloComponent2(msg) ); 23 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 24 | frame.setSize( 300, 300 ); 25 | frame.setVisible( true ); 26 | } 27 | } 28 | 29 | /* 30 | * Inheritence (the "extends" keyword below) and interfaces 31 | * (the "implements MouseMotionListener" portion) are covered in 32 | * more detail in Chapter 5. 33 | */ 34 | class HelloComponent2 extends JComponent implements MouseMotionListener { 35 | String theMessage; 36 | int messageX = 125, messageY = 95; // Coordinates of the message 37 | 38 | /** 39 | * Create a new component that can draw its message at an arbitrary position. 40 | * That position can be changed by dragging the mouse; we attach a listener 41 | * to pick up those drag events. 42 | */ 43 | public HelloComponent2( String message ) { 44 | theMessage = message; 45 | addMouseMotionListener(this); 46 | } 47 | 48 | public void paintComponent( Graphics g ) { 49 | g.drawString( theMessage, messageX, messageY ); 50 | } 51 | 52 | public void mouseDragged(MouseEvent e) { 53 | // Save the mouse coordinates and paint the message. 54 | messageX = e.getX(); 55 | messageY = e.getY(); 56 | repaint(); 57 | } 58 | 59 | public void mouseMoved(MouseEvent e) { 60 | // Ignore simple movements 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch03/exercises/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Created-By: 11.0.16 3 | 4 | -------------------------------------------------------------------------------- /ch03/solutions/HelloComponent2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/solutions/HelloComponent2.class -------------------------------------------------------------------------------- /ch03/solutions/HelloJar.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/solutions/HelloJar.class -------------------------------------------------------------------------------- /ch03/solutions/HelloJar.java: -------------------------------------------------------------------------------- 1 | package ch03.solutions; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | /** 8 | * Reusing our graphical application with interactivity! 9 | */ 10 | public class HelloJar { 11 | public static void main( String[] args ) { 12 | String msg = "You cheated! :)"; 13 | if ( HelloJar.class.getProtectionDomain() 14 | .getCodeSource() 15 | .getLocation() 16 | .getFile() 17 | .endsWith(".jar") ) { 18 | // You didn't cheat, so let's fix the message 19 | msg = "Hello from a JAR file!"; 20 | } 21 | JFrame frame = new JFrame( "Hello Jar" ); 22 | frame.add( new HelloComponent2(msg) ); 23 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 24 | frame.setSize( 300, 300 ); 25 | frame.setVisible( true ); 26 | } 27 | } 28 | 29 | /* 30 | * Inheritence (the "extends" keyword below) and interfaces 31 | * (the "implements MouseMotionListener" portion) are covered in 32 | * more detail in Chapter 5. 33 | */ 34 | class HelloComponent2 extends JComponent implements MouseMotionListener { 35 | String theMessage; 36 | int messageX = 125, messageY = 95; // Coordinates of the message 37 | 38 | /** 39 | * Create a new component that can draw its message at an arbitrary position. 40 | * That position can be changed by dragging the mouse; we attach a listener 41 | * to pick up those drag events. 42 | */ 43 | public HelloComponent2( String message ) { 44 | theMessage = message; 45 | addMouseMotionListener(this); 46 | } 47 | 48 | public void paintComponent( Graphics g ) { 49 | g.drawString( theMessage, messageX, messageY ); 50 | } 51 | 52 | public void mouseDragged(MouseEvent e) { 53 | // Save the mouse coordinates and paint the message. 54 | messageX = e.getX(); 55 | messageY = e.getY(); 56 | repaint(); 57 | } 58 | 59 | public void mouseMoved(MouseEvent e) { 60 | // Ignore simple movements 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch03/solutions/hello.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch03/solutions/hello.jar -------------------------------------------------------------------------------- /ch03/solutions/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Created-By: 11.0.16 3 | Main-Class: ch03.solutions.HelloJar 4 | 5 | -------------------------------------------------------------------------------- /ch04/examples/EnhancedForDemo.java: -------------------------------------------------------------------------------- 1 | package ch04.examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class EnhancedForDemo { 6 | public static void main(String args[]) { 7 | int [] arrayOfInts = new int [] { 1, 2, 3, 4 }; 8 | int total = 0; 9 | 10 | for( int i : arrayOfInts ) { 11 | System.out.println( i ); 12 | total = total + i; 13 | } 14 | System.out.println("Total: " + total); 15 | 16 | // ArrayList is a popular collection class 17 | // Chapter 7 discusses collections in more detail 18 | ArrayList list = new ArrayList(); 19 | list.add("foo"); 20 | list.add("bar"); 21 | 22 | for( String s : list ) 23 | System.out.println( s ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch04/examples/EuclidGCD.java: -------------------------------------------------------------------------------- 1 | package ch04.examples; 2 | 3 | /** 4 | * A basic implementation of Euclid's greatest common denominator 5 | * algorithm. 6 | * 7 | * https://en.wikipedia.org/wiki/Algorithm 8 | */ 9 | public class EuclidGCD { 10 | public static void main(String args[]) { 11 | // For now, just "hard code" the two numbers to compare 12 | int a = 2701; 13 | int b = 222; 14 | while (b != 0) { 15 | if (a > b) { 16 | a = a - b; 17 | } else { 18 | b = b - a; 19 | } 20 | } 21 | System.out.println("GCD is " + a); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch04/examples/ForDemo.java: -------------------------------------------------------------------------------- 1 | package ch04.examples; 2 | 3 | public class ForDemo { 4 | public static void main(String args[]) { 5 | System.out.println("Count up from 0 to 99:"); 6 | for ( int i = 0; i < 100; i++ ) { 7 | System.out.println( i ); 8 | int j = i; 9 | // do any other work needed 10 | } 11 | 12 | System.out.println("\nGenerate some coordinates:"); 13 | for (int x = 0, y = 10; x < y; x++, y-- ) { 14 | System.out.println(x + ", " + y); 15 | // do other stuff with our new (x, y)... 16 | } 17 | 18 | System.out.println("\nCount from 0 to 9, but skip 5 using a continue statement:"); 19 | for ( int i = 0; i < 10; i++ ) { 20 | if ( i == 5 ) 21 | continue; 22 | System.out.println( i ); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch04/examples/HelloJava.java: -------------------------------------------------------------------------------- 1 | package ch04.examples; 2 | 3 | import javax.swing.*; 4 | 5 | public class HelloJava { 6 | public static void main( String[] args ) { 7 | JFrame frame = new JFrame( "Hello, Java!" ); 8 | JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); 9 | frame.add(label); 10 | frame.setSize( 300, 300 ); 11 | frame.setVisible( true ); 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /ch04/examples/IfDemo.java: -------------------------------------------------------------------------------- 1 | package ch04.examples; 2 | 3 | public class IfDemo { 4 | public static void main(String args[]) { 5 | int i = 0; 6 | // you can use i now to do other work and then 7 | // we can test it to see if anything has changed 8 | if (i == 0) 9 | System.out.println("i is still zero"); 10 | else 11 | System.out.println("i is most definitely not zero"); 12 | 13 | int j = 0; 14 | // you can use j now to do work like i before, 15 | // then make sure that work didn't drop 16 | // j's value below zero 17 | if (j < 0) { 18 | System.out.println("j is less than 0! Resetting."); 19 | j = 0; 20 | } else { 21 | System.out.println("j is positive or 0. Continuing."); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch04/examples/WhileDemo.java: -------------------------------------------------------------------------------- 1 | package ch04.examples; 2 | 3 | public class WhileDemo { 4 | public static void main(String args[]) { 5 | // A simple example of counting down 6 | int count = 10; 7 | while( count > 0 ) { 8 | System.out.println("Counting down: " + count); 9 | // maybe do other useful things 10 | // and decrement our count 11 | count = count - 1; 12 | } 13 | System.out.println("Done"); 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch04/exercises/Euclid.java: -------------------------------------------------------------------------------- 1 | package ch04.exercises; 2 | 3 | /** 4 | * A basic implementation of Euclid's greatest common denominator 5 | * algorithm. 6 | * 7 | * https://en.wikipedia.org/wiki/Algorithm 8 | */ 9 | public class Euclid { 10 | public static void main(String args[]) { 11 | // For now, just "hard code" the two numbers to compare 12 | int a = 2701; 13 | int b = 222; 14 | // Exercise 1, fill in the algorithm from Chapter 4 15 | 16 | // Can you include the original numbers in the output? 17 | System.out.println("The GCD is " + a); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch04/exercises/SimpleTriangle.java: -------------------------------------------------------------------------------- 1 | package ch04.exercises; 2 | 3 | // Exercise 2. Print out the contents of our 4 | // "triangular" array. 5 | 6 | public class SimpleTriangle { 7 | public static void main(String args[]) { 8 | // Create our "triangular" two-dimensional array 9 | int[][] triangle = new int[5][]; 10 | 11 | // Use nested loops to fill it 12 | for (int i = 0; i < triangle.length; i++) { 13 | triangle[i] = new int [i + 1]; 14 | for (int j = 0; j < i + 1; j++) 15 | triangle[i][j] = i + j; 16 | } 17 | 18 | // Add your code to display the nested arrays here 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch04/solutions/Euclid.java: -------------------------------------------------------------------------------- 1 | package ch04.solutions; 2 | 3 | /** 4 | * A basic implementation of Euclid's greatest common denominator 5 | * algorithm. 6 | * 7 | * https://en.wikipedia.org/wiki/Algorithm 8 | */ 9 | public class Euclid { 10 | public static void main(String args[]) { 11 | // For now, just "hard code" the two numbers to compare 12 | int a = 2701; 13 | int b = 222; 14 | int original_a = a; 15 | int original_b = b; 16 | while (b != 0) { 17 | if (a > b) { 18 | a = a - b; 19 | } else { 20 | b = b - a; 21 | } 22 | } 23 | System.out.println("The GCD of " + original_a + " and " + original_b + " is " + a); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch04/solutions/SimpleTriangle.java: -------------------------------------------------------------------------------- 1 | package ch04.solutions; 2 | 3 | public class SimpleTriangle { 4 | public static void main(String args[]) { 5 | // Create our "triangular" two-dimensional array 6 | int[][] triangle = new int[5][]; 7 | 8 | // Use nested loops to fill it 9 | for (int i = 0; i < triangle.length; i++) { 10 | triangle[i] = new int [i + 1]; 11 | for (int j = 0; j < i + 1; j++) 12 | triangle[i][j] = i + j; 13 | } 14 | 15 | // And finally, use nested loops to display it 16 | for (int i = 0; i < triangle.length; i++) { 17 | for (int j = 0; j < triangle[i].length; j++) { 18 | System.out.println(triangle[i][j]); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch04/solutions/VisualTriangle.java: -------------------------------------------------------------------------------- 1 | package ch04.solutions; 2 | 3 | public class VisualTriangle { 4 | public static void main(String args[]) { 5 | // Create our "triangular" two-dimensional array 6 | int[][] triangle = new int[5][]; 7 | 8 | // Use nested loops to fill it 9 | for (int i = 0; i < triangle.length; i++) { 10 | triangle[i] = new int [i + 1]; 11 | for (int j = 0; j < i + 1; j++) 12 | triangle[i][j] = i + j; 13 | } 14 | 15 | // And finally, use nested loops to display it 16 | for (int i = 0; i < triangle.length; i++) { 17 | for (int j = 0; j < triangle[i].length; j++) { 18 | System.out.print(triangle[i][j]); 19 | System.out.print(" "); 20 | } 21 | System.out.println(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch05/examples/Field.java: -------------------------------------------------------------------------------- 1 | package ch05.examples; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | 6 | /** 7 | * A reduced playing field for our game. This class sets up the apples 8 | * similar to our real game (in the ch05/examples/game folder) but leaves out 9 | * other details. It is meant for use with the various PrintDetails classes. 10 | */ 11 | public class Field extends JComponent { 12 | 13 | public static final int APPLE_SIZE_IN_PIXELS = 30; 14 | 15 | Color fieldColor = Color.LIGHT_GRAY; 16 | 17 | Apple a1 = new Apple(); 18 | Apple a2 = new Apple(); 19 | 20 | public void setupApples() { 21 | // For now, just play with our apple attributes directly 22 | a1.diameter = 3.0f; 23 | a1.mass = 5.0f; 24 | a1.x = 20; 25 | a1.y = 40; 26 | a2.diameter = 8.0f; 27 | a2.mass = 10.0f; 28 | a2.x = 70; 29 | a2.y = 200; 30 | } 31 | 32 | protected void paintComponent(Graphics g) { 33 | g.setColor(fieldColor); 34 | g.fillRect(0, 0, getWidth(), getHeight()); 35 | a1.draw(g); 36 | a2.draw(g); 37 | } 38 | 39 | public void detectCollisions() { 40 | if (a1.isTouching(a2)) { 41 | System.out.println("Collision detected!"); 42 | } else { 43 | System.out.println("Apples are not touching."); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ch05/examples/HelloJava3.java: -------------------------------------------------------------------------------- 1 | package ch05.examples; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | /** 8 | * Another (minor) upgrade to our graphical Hello, World example. 9 | * This variation introduces an inner class for the message component 10 | * and an anonymous inner class for the listener handling the mouse 11 | * drag events. (More on events and listeners in Chapter 10.) 12 | */ 13 | public class HelloJava3 extends JFrame { 14 | public static void main( String[] args ) { 15 | HelloJava3 demo = new HelloJava3(); 16 | demo.setVisible( true ); 17 | } 18 | 19 | public HelloJava3() { 20 | super( "HelloJava3" ); 21 | add( new HelloComponent3("Hello, Inner Java!") ); 22 | setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 23 | setSize( 300, 300 ); 24 | } 25 | 26 | class HelloComponent3 extends JComponent { 27 | String theMessage; 28 | int messageX = 125, messageY = 95; // Coordinates of the message 29 | 30 | public HelloComponent3( String message ) { 31 | theMessage = message; 32 | addMouseMotionListener(new MouseMotionListener() { 33 | public void mouseDragged(MouseEvent e) { 34 | messageX = e.getX(); 35 | messageY = e.getY(); 36 | repaint(); 37 | } 38 | 39 | public void mouseMoved(MouseEvent e) { } 40 | }); 41 | } 42 | 43 | public void paintComponent( Graphics g ) { 44 | g.drawString( theMessage, messageX, messageY ); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ch05/examples/PrintAppleDetails.java: -------------------------------------------------------------------------------- 1 | package ch05.examples; 2 | 3 | /** 4 | * A simple demonstration of accessing the contents of an object. We create 5 | * a new apple and print out some of its details. 6 | */ 7 | public class PrintAppleDetails { 8 | public static void main(String args[]) { 9 | String niceNames[] = Apple.getAppleSizes(); 10 | Apple a1 = new Apple(); 11 | System.out.println("Apple a1:"); 12 | System.out.println(" mass: " + a1.mass); 13 | System.out.println(" diameter: " + a1.diameter); 14 | System.out.println(" position: (" + a1.x + ", " + a1.y +")"); 15 | if (a1.diameter < 5.0f) { 16 | System.out.println("This is a " + niceNames[Apple.SMALL] + " apple."); 17 | } else if (a1.diameter < 10.0f) { 18 | System.out.println("This is a " + niceNames[Apple.MEDIUM] + " apple."); 19 | } else { 20 | System.out.println("This is a " + niceNames[Apple.LARGE] + " apple."); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch05/examples/PrintAppleDetails2.java: -------------------------------------------------------------------------------- 1 | package ch05.examples; 2 | 3 | /** 4 | * Another quick example of working with an object. This time we print 5 | * the initial details of an apple, change some of those details, and 6 | * then do the same printing to provide a comparison of the results. 7 | */ 8 | public class PrintAppleDetails2 { 9 | public static void main(String args[]) { 10 | Apple a1 = new Apple(); 11 | System.out.println("Apple a1:"); 12 | System.out.println(" mass: " + a1.mass); 13 | System.out.println(" diameter: " + a1.diameter); 14 | System.out.println(" position: (" + a1.x + ", " + a1.y +")"); 15 | // fill in some information on a1 16 | a1.mass = 10.0f; 17 | a1.x = 20; 18 | a1.y = 42; 19 | System.out.println("Updated a1:"); 20 | System.out.println(" mass: " + a1.mass); 21 | System.out.println(" diameter: " + a1.diameter); 22 | System.out.println(" position: (" + a1.x + ", " + a1.y +")"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch05/examples/PrintAppleDetails3.java: -------------------------------------------------------------------------------- 1 | package ch05.examples; 2 | 3 | /** 4 | * A variation on PrintAppleDetails2 where we have moved the printing code 5 | * to the Apple class. Notice that this file is smaller than PrintAppleDetails2 6 | * meaning fewer lines to make mistakes! 7 | */ 8 | public class PrintAppleDetails3 { 9 | public static void main(String args[]) { 10 | Apple a1 = new Apple(); 11 | System.out.println("Apple a1:"); 12 | a1.printDetails(); 13 | // fill in some information on a1 14 | a1.mass = 10.0f; 15 | a1.x = 20; 16 | a1.y = 42; 17 | System.out.println("Updated a1:"); 18 | a1.printDetails(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch05/examples/PrintAppleDetails4.java: -------------------------------------------------------------------------------- 1 | package ch05.examples; 2 | 3 | /** 4 | * One final iteration of manipulating and printing apple details. 5 | * Now the Field class understands apples so we access those apples 6 | * through the field object. Notice the double dot-notation. 7 | */ 8 | public class PrintAppleDetails4 { 9 | public static void main(String args[]) { 10 | Field f = new Field(); 11 | f.setupApples(); 12 | System.out.println("Apple a1:"); 13 | f.a1.printDetails(); 14 | System.out.println("Apple a2:"); 15 | f.a2.printDetails(); 16 | f.detectCollisions(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch05/examples/game/AppleToss.java: -------------------------------------------------------------------------------- 1 | package ch05.examples.game; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * Our apple tossing game. This class extends JFrame to create our 7 | * main application window. We'll be filling this out along the way, 8 | * but for now we can setup a field with some trees and our player. 9 | */ 10 | public class AppleToss extends JFrame { 11 | 12 | Field field = new Field(); 13 | Physicist player1 = new Physicist(); 14 | 15 | public AppleToss() { 16 | // Create our frame 17 | super("Apple Toss Game"); 18 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 | setSize(800,600); 20 | setResizable(false); 21 | 22 | // Build the field with our player and some trees 23 | setupFieldForOnePlayer(); 24 | } 25 | 26 | /** 27 | * A helper method to populate a one player field with target trees. 28 | */ 29 | private void setupFieldForOnePlayer() { 30 | // Place our (new) physicist in the lower left corner and connect them to the field 31 | player1.setPosition(100,500); 32 | field.setPlayer(player1); 33 | player1.setField(field); 34 | field.setupApples(); 35 | field.setupTree(); 36 | add(field); 37 | } 38 | 39 | public static void main(String args[]) { 40 | AppleToss game = new AppleToss(); 41 | game.setVisible(true); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ch05/examples/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch05.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * - methods for positioning on a Field 8 | * - methods for Drawing 9 | * - methods for detecting a collision with other GamePieces 10 | */ 11 | 12 | public interface GamePiece { 13 | /** 14 | * Sets the position of the piece on the playing field. 15 | * (0,0) is the upper left per standard Java drawing methods. 16 | * 17 | * @param x 18 | * @param y 19 | */ 20 | void setPosition(int x, int y); 21 | 22 | /** 23 | * Gets the current horizontal position of the piece on the field. 24 | * 25 | * @return current X position of the piece 26 | */ 27 | int getPositionX(); 28 | 29 | /** 30 | * Gets the current vertical position of the piece on the field. 31 | * 32 | * @return current Y position of the piece 33 | */ 34 | int getPositionY(); 35 | 36 | /** 37 | * Gets the bounding box of this piece. 38 | * 39 | * @return a Rectangle encompassing the visual elements of the piece 40 | */ 41 | Rectangle getBoundingBox(); 42 | 43 | /** 44 | * Draws the piece inside the given graphics context. 45 | * Do not assume anything about the state of the context. 46 | * 47 | * @param g 48 | */ 49 | void draw(Graphics g); 50 | 51 | /** 52 | * Detect a collision with another piece on the field. 53 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 54 | * 55 | * @param otherPiece 56 | * @return 57 | */ 58 | boolean isTouching(GamePiece otherPiece); 59 | } 60 | -------------------------------------------------------------------------------- /ch05/examples/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch05.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | // We don't really have any collisions to detect yet, so just return "no". 57 | // As we fill out all of the game pieces, we'll come back to this method 58 | // and provide a more useful response. 59 | return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ch05/exercises/Zoo.java: -------------------------------------------------------------------------------- 1 | package ch05.exercises; 2 | 3 | import java.util.*; 4 | 5 | public class Zoo { 6 | 7 | abstract class Animal { 8 | public abstract void speak(); 9 | } 10 | 11 | class Lion extends Animal { 12 | public void speak() { 13 | System.out.print("roar"); 14 | } 15 | } 16 | 17 | class Gibbon extends Animal { 18 | public void speak() { 19 | } 20 | } 21 | 22 | public void listen() { 23 | Lion lion = new Lion(); 24 | Gibbon gibbon = new Gibbon(); 25 | System.out.println("Let's listen to some animals!"); 26 | System.out.print("The lion goes \""); 27 | lion.speak(); 28 | System.out.println("\""); 29 | System.out.print("The gibbon goes \""); 30 | gibbon.speak(); 31 | System.out.println("\""); 32 | } 33 | 34 | public static void main(String args[]) { 35 | Zoo myZoo = new Zoo(); 36 | myZoo.listen(); 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /ch05/exercises/game/AppleToss.java: -------------------------------------------------------------------------------- 1 | package ch05.exercises.game; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * Our apple tossing game. This class extends JFrame to create our 7 | * main application window. We'll be filling this out along the way, 8 | * but for now we can setup a field with some trees and our player. 9 | */ 10 | public class AppleToss extends JFrame { 11 | 12 | Field field = new Field(); 13 | Physicist player1 = new Physicist(); 14 | 15 | public AppleToss() { 16 | // Create our frame 17 | super("Apple Toss Game"); 18 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 | setSize(800,600); 20 | setResizable(false); 21 | 22 | // Build the field with our player and some trees 23 | setupFieldForOnePlayer(); 24 | } 25 | 26 | /** 27 | * A helper method to populate a one player field with target trees. 28 | */ 29 | private void setupFieldForOnePlayer() { 30 | // Place our (new) physicist in the lower left corner and connect them to the field 31 | player1.setPosition(100,500); 32 | field.setPlayer(player1); 33 | player1.setField(field); 34 | field.setupApples(); 35 | field.setupTree(); 36 | add(field); 37 | } 38 | 39 | public static void main(String args[]) { 40 | AppleToss game = new AppleToss(); 41 | game.setVisible(true); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ch05/exercises/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch05.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * - methods for positioning on a Field 8 | * - methods for Drawing 9 | * - methods for detecting a collision with other GamePieces 10 | */ 11 | 12 | public interface GamePiece { 13 | /** 14 | * Sets the position of the piece on the playing field. 15 | * (0,0) is the upper left per standard Java drawing methods. 16 | * 17 | * @param x 18 | * @param y 19 | */ 20 | void setPosition(int x, int y); 21 | 22 | /** 23 | * Gets the current horizontal position of the piece on the field. 24 | * 25 | * @return current X position of the piece 26 | */ 27 | int getPositionX(); 28 | 29 | /** 30 | * Gets the current vertical position of the piece on the field. 31 | * 32 | * @return current Y position of the piece 33 | */ 34 | int getPositionY(); 35 | 36 | /** 37 | * Gets the bounding box of this piece. 38 | * 39 | * @return a Rectangle encompassing the visual elements of the piece 40 | */ 41 | Rectangle getBoundingBox(); 42 | 43 | /** 44 | * Draws the piece inside the given graphics context. 45 | * Do not assume anything about the state of the context. 46 | * 47 | * @param g 48 | */ 49 | void draw(Graphics g); 50 | 51 | /** 52 | * Detect a collision with another piece on the field. 53 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 54 | * 55 | * @param otherPiece 56 | * @return 57 | */ 58 | boolean isTouching(GamePiece otherPiece); 59 | } 60 | -------------------------------------------------------------------------------- /ch05/exercises/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch05.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | // We don't really have any collisions to detect yet, so just return "no". 57 | // As we fill out all of the game pieces, we'll come back to this method 58 | // and provide a more useful response. 59 | return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ch05/solutions/Zoo.java: -------------------------------------------------------------------------------- 1 | package ch05.solutions; 2 | 3 | import java.util.*; 4 | 5 | public class Zoo { 6 | 7 | abstract class Animal { 8 | public abstract void speak(); 9 | } 10 | 11 | class Lion extends Animal { 12 | public void speak() { 13 | System.out.print("roar"); 14 | } 15 | } 16 | 17 | class Gibbon extends Animal { 18 | public void speak() { 19 | System.out.print("hoot"); 20 | } 21 | } 22 | 23 | public void listen() { 24 | Lion lion = new Lion(); 25 | Gibbon gibbon = new Gibbon(); 26 | System.out.println("Let's listen to some animals!"); 27 | System.out.print("The lion goes \""); 28 | lion.speak(); 29 | System.out.println("\""); 30 | System.out.print("The gibbon goes \""); 31 | gibbon.speak(); 32 | System.out.println("\""); 33 | } 34 | 35 | public static void main(String args[]) { 36 | Zoo myZoo = new Zoo(); 37 | myZoo.listen(); 38 | } 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /ch05/solutions/Zoo2.java: -------------------------------------------------------------------------------- 1 | package ch05.solutions; 2 | 3 | import java.util.*; 4 | 5 | public class Zoo2 { 6 | 7 | abstract class Animal { 8 | public abstract void speak(); 9 | } 10 | 11 | class Lion extends Animal { 12 | public void speak() { 13 | System.out.print("roar"); 14 | } 15 | } 16 | 17 | class Gibbon extends Animal { 18 | public void speak() { 19 | System.out.print("hoot"); 20 | } 21 | } 22 | 23 | class Seal extends Animal { 24 | public void speak() { 25 | System.out.print("bark"); 26 | } 27 | } 28 | 29 | public void listen() { 30 | Lion lion = new Lion(); 31 | Gibbon gibbon = new Gibbon(); 32 | Seal seal = new Seal(); 33 | System.out.println("Let's listen to some animals!"); 34 | System.out.print("The lion goes \""); 35 | lion.speak(); 36 | System.out.println("\""); 37 | System.out.print("The gibbon goes \""); 38 | gibbon.speak(); 39 | System.out.println("\""); 40 | System.out.print("The seal goes \""); 41 | seal.speak(); 42 | System.out.println("\""); 43 | } 44 | 45 | public static void main(String args[]) { 46 | Zoo2 myZoo = new Zoo2(); 47 | myZoo.listen(); 48 | } 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /ch05/solutions/Zoo3.java: -------------------------------------------------------------------------------- 1 | package ch05.solutions; 2 | 3 | import java.util.*; 4 | 5 | public class Zoo3 { 6 | 7 | abstract class Animal { 8 | public abstract void speak(); 9 | public abstract String getSpecies(); 10 | } 11 | 12 | class Lion extends Animal { 13 | public void speak() { 14 | System.out.print("roar"); 15 | } 16 | public String getSpecies() { 17 | return "lion"; 18 | } 19 | } 20 | 21 | class Gibbon extends Animal { 22 | public void speak() { 23 | System.out.print("hoot"); 24 | } 25 | public String getSpecies() { 26 | return "gibbon"; 27 | } 28 | } 29 | 30 | class Seal extends Animal { 31 | public void speak() { 32 | System.out.print("bark"); 33 | } 34 | public String getSpecies() { 35 | return "seal"; 36 | } 37 | } 38 | 39 | public void listen() { 40 | System.out.println("Let's listen to our menagerie!"); 41 | Animal[] menagerie = { new Lion(), new Gibbon(), new Seal() }; 42 | for (Animal animal : menagerie) { 43 | System.out.print("The "); 44 | System.out.print(animal.getSpecies()); 45 | System.out.print(" goes \""); 46 | animal.speak(); 47 | System.out.println("\""); 48 | } 49 | } 50 | 51 | public static void main(String args[]) { 52 | Zoo3 myZoo = new Zoo3(); 53 | myZoo.listen(); 54 | } 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /ch05/solutions/game/AppleToss.java: -------------------------------------------------------------------------------- 1 | package ch05.solutions.game; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * Our apple tossing game. This class extends JFrame to create our 7 | * main application window. We'll be filling this out along the way, 8 | * but for now we can setup a field with some trees and our player. 9 | */ 10 | public class AppleToss extends JFrame { 11 | 12 | Field field = new Field(); 13 | Physicist player1 = new Physicist(); 14 | 15 | public AppleToss() { 16 | // Create our frame 17 | super("Apple Toss Game"); 18 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 | setSize(800,600); 20 | setResizable(false); 21 | 22 | // Build the field with our player and some trees 23 | setupFieldForOnePlayer(); 24 | } 25 | 26 | /** 27 | * A helper method to populate a one player field with target trees. 28 | */ 29 | private void setupFieldForOnePlayer() { 30 | // Place our (new) physicist in the lower left corner and connect them to the field 31 | player1.setPosition(100,500); 32 | field.setPlayer(player1); 33 | player1.setField(field); 34 | field.setupApples(); 35 | field.setupTree(); 36 | field.setupHedge(); 37 | add(field); 38 | } 39 | 40 | public static void main(String args[]) { 41 | AppleToss game = new AppleToss(); 42 | game.setVisible(true); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ch05/solutions/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch05.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * - methods for positioning on a Field 8 | * - methods for Drawing 9 | * - methods for detecting a collision with other GamePieces 10 | */ 11 | 12 | public interface GamePiece { 13 | /** 14 | * Sets the position of the piece on the playing field. 15 | * (0,0) is the upper left per standard Java drawing methods. 16 | * 17 | * @param x 18 | * @param y 19 | */ 20 | void setPosition(int x, int y); 21 | 22 | /** 23 | * Gets the current horizontal position of the piece on the field. 24 | * 25 | * @return current X position of the piece 26 | */ 27 | int getPositionX(); 28 | 29 | /** 30 | * Gets the current vertical position of the piece on the field. 31 | * 32 | * @return current Y position of the piece 33 | */ 34 | int getPositionY(); 35 | 36 | /** 37 | * Gets the bounding box of this piece. 38 | * 39 | * @return a Rectangle encompassing the visual elements of the piece 40 | */ 41 | Rectangle getBoundingBox(); 42 | 43 | /** 44 | * Draws the piece inside the given graphics context. 45 | * Do not assume anything about the state of the context. 46 | * 47 | * @param g 48 | */ 49 | void draw(Graphics g); 50 | 51 | /** 52 | * Detect a collision with another piece on the field. 53 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 54 | * 55 | * @param otherPiece 56 | * @return 57 | */ 58 | boolean isTouching(GamePiece otherPiece); 59 | } 60 | -------------------------------------------------------------------------------- /ch05/solutions/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch05.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color hedgeColor = Color.GREEN.darker(); 14 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 15 | private int hedgeHeight = (int)(hedgeWidth / 2); 16 | 17 | // Boundary helpers 18 | private Rectangle boundingBox; 19 | 20 | @Override 21 | public void setPosition(int x, int y) { 22 | this.x = x; 23 | this.y = y; 24 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(hedgeColor); 45 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 46 | } 47 | 48 | @Override 49 | public boolean isTouching(GamePiece otherPiece) { 50 | // We don't really have any collisions to detect yet, so just return "no". 51 | // As we fill out all of the game pieces, we'll come back to this method 52 | // and provide a more useful response. 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch05/solutions/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch05.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | // We don't really have any collisions to detect yet, so just return "no". 57 | // As we fill out all of the game pieces, we'll come back to this method 58 | // and provide a more useful response. 59 | return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ch06/examples/Euclid2.java: -------------------------------------------------------------------------------- 1 | package ch06.examples; 2 | 3 | /** 4 | * A basic implementation of Euclid's greatest common denominator 5 | * algorithm. This version build on ch04 allowing you to pass the 6 | * numbers to use as command line arguments. 7 | */ 8 | public class Euclid2 { 9 | public static void main(String args[]) { 10 | int a = 2701; 11 | int b = 222; 12 | // Only try to parse arguments if we have exactly 2 13 | if (args.length == 2) { 14 | try { 15 | a = Integer.parseInt(args[0]); 16 | b = Integer.parseInt(args[1]); 17 | } catch (NumberFormatException nfe) { 18 | System.err.println("Arguments were not both numbers. Using defaults."); 19 | } 20 | } else { 21 | System.err.println("Wrong number of arguments (expected 2). Using defaults."); 22 | } 23 | System.out.print("The GCD of " + a + " and " + b + " is "); 24 | while (b != 0) { 25 | if (a > b) { 26 | a = a - b; 27 | } else { 28 | b = b - a; 29 | } 30 | } 31 | System.out.println(a); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch06/examples/LogTest.java: -------------------------------------------------------------------------------- 1 | package ch06.examples; 2 | 3 | import java.util.logging.*; 4 | 5 | public class LogTest { 6 | public static void main(String argv[]) { 7 | Logger logger = Logger.getLogger("ch06.LogTest"); 8 | 9 | logger.severe("Power lost - running on backup!"); 10 | logger.warning("Database connection lost, retrying..."); 11 | logger.info("Startup complete."); 12 | logger.config("Server configuration: standalone, Java 20"); 13 | logger.fine("Loading graphing package."); 14 | logger.finer("Doing pie chart"); 15 | logger.finest("Starting bubble sort: value ="+42); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /ch06/exercises/Euclid2.java: -------------------------------------------------------------------------------- 1 | package ch06.exercises; 2 | 3 | public class Euclid2 { 4 | public static void main(String args[]) { 5 | int a = 2701; 6 | int b = 222; 7 | // Only try to parse arguments if we have exactly 2 8 | if (args.length == 2) { 9 | try { 10 | a = Integer.parseInt(args[0]); 11 | b = Integer.parseInt(args[1]); 12 | } catch (NumberFormatException nfe) { 13 | System.err.println("Arguments were not both numbers."); 14 | System.err.println("Using defaults."); 15 | } 16 | } else { 17 | System.err.print("Wrong number of arguments"); 18 | System.err.println(" expected 2)."); 19 | System.err.println("Using defaults."); 20 | } 21 | System.out.print("The GCD of " + a + " and " + b + " is "); 22 | while (b != 0) { 23 | if (a > b) { 24 | a = a - b; 25 | } else { 26 | b = b - a; 27 | } 28 | } 29 | System.out.println(a); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /ch06/exercises/HelloZero.java: -------------------------------------------------------------------------------- 1 | package ch06.exercises; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | /** 8 | * An upgraded graphical application with interactivity! 9 | * Use this template to add assertions to guarantee our 10 | * message displays itself in a visible part of the window. 11 | */ 12 | public class HelloZero { 13 | public static void main( String[] args ) { 14 | JFrame frame = new JFrame( "Chapter 6, Exercise 2" ); 15 | frame.add( new HelloComponent0("Hello, Zero!") ); 16 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 17 | frame.setSize( 300, 300 ); 18 | frame.setVisible( true ); 19 | } 20 | } 21 | 22 | /* 23 | * Our custom component to display a message and move 24 | * it around as the user drags their mouse. Hopefully 25 | * more of the extends/implements details make sense 26 | * now that you've worked with them more in Chapters 27 | * 5 and 6. 28 | */ 29 | class HelloComponent0 extends JComponent implements MouseMotionListener { 30 | String theMessage; 31 | int messageX = 125, messageY = 95; // Coordinates of the message 32 | 33 | /** 34 | * Create a new component that can draw its message at an arbitrary position. 35 | * That position can be changed by dragging the mouse; we attach a listener 36 | * to pick up those drag events. 37 | */ 38 | public HelloComponent0( String message ) { 39 | theMessage = message; 40 | addMouseMotionListener(this); 41 | } 42 | 43 | public void paintComponent( Graphics g ) { 44 | g.drawString( theMessage, messageX, messageY ); 45 | } 46 | 47 | public void mouseDragged(MouseEvent e) { 48 | // Save the mouse coordinates and paint the message. 49 | messageX = e.getX(); 50 | messageY = e.getY(); 51 | repaint(); 52 | } 53 | 54 | public void mouseMoved(MouseEvent e) { 55 | // Ignore simple movements 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ch06/exercises/Pause.java.bad: -------------------------------------------------------------------------------- 1 | package ch06.exercises; 2 | 3 | // NOTE: Be sure to rename this file to Pause.java when you want to 4 | // work on the exercise. We had to supply this "bad" file extension to 5 | // keep IDEs such as IntelliJ IDEA from failing. Many IDEs compile 6 | // every class in the project. If one fails, you can't run any of the 7 | // classes with main() methods. This is a quirk of our project that we 8 | // really have dozens and dozens of "projects" under one umbrella. 9 | 10 | public class Pause { 11 | public static void main(String args[]) { 12 | System.out.print("Starting... "); 13 | Thread.sleep(5000); 14 | System.out.println("done"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch06/solutions/Euclid2.java: -------------------------------------------------------------------------------- 1 | package ch06.solutions; 2 | 3 | import java.util.logging.Logger; 4 | 5 | public class Euclid2 { 6 | static Logger log = Logger.getLogger("ch06.Euclid2"); 7 | public static void main(String args[]) { 8 | int a = 2701; 9 | int b = 222; 10 | // Only try to parse arguments if we have exactly 2 11 | if (args.length == 2) { 12 | try { 13 | a = Integer.parseInt(args[0]); 14 | b = Integer.parseInt(args[1]); 15 | } catch (NumberFormatException nfe) { 16 | log.warning("Arguments were not both numbers."); 17 | log.warning("Using defaults."); 18 | } 19 | } else { 20 | System.err.print("Wrong number of arguments"); 21 | System.err.println(" expected 2)."); 22 | System.err.println("Using defaults."); 23 | } 24 | System.out.print("The GCD of " + a + " and " + b + " is "); 25 | while (b != 0) { 26 | if (a > b) { 27 | a = a - b; 28 | } else { 29 | b = b - a; 30 | } 31 | } 32 | System.out.println(a); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /ch06/solutions/Euclid3.java: -------------------------------------------------------------------------------- 1 | package ch06.solutions; 2 | 3 | public class Euclid3 { 4 | public static void main(String args[]) { 5 | int a1, b1; 6 | int a = 2701; 7 | int b = 222; 8 | // Only try to parse arguments if we have exactly 2 9 | if (args.length == 2) { 10 | try { 11 | a = Integer.parseInt(args[0]); 12 | b = Integer.parseInt(args[1]); 13 | } catch (NumberFormatException nfe) { 14 | System.err.println("Arguments were not both numbers."); 15 | System.err.println("Using defaults."); 16 | } 17 | } else { 18 | System.err.print("Wrong number of arguments"); 19 | System.err.println(" expected 2)."); 20 | System.err.println("Using defaults."); 21 | } 22 | // Store our originals for messaging and such 23 | a1 = a; 24 | b1 = b; 25 | while (b != 0) { 26 | if (a > b) { 27 | a = a - b; 28 | } else { 29 | b = b - a; 30 | } 31 | } 32 | try { 33 | if (a == 1) { 34 | throw new GCDException(a1, b1); 35 | } else { 36 | System.out.print("The GCD of " + a1 + " and " + b1 + " is "); 37 | System.out.println(a); 38 | } 39 | } catch (GCDException gcde) { 40 | System.err.println(gcde.getA() + " and " + gcde.getB() + " have no common denominator."); 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /ch06/solutions/GCDException.java: -------------------------------------------------------------------------------- 1 | package ch06.solutions; 2 | 3 | public class GCDException extends Exception { 4 | private int badA; 5 | private int badB; 6 | 7 | GCDException(int a, int b) { 8 | super("No common factors for " + a + ", " + b); 9 | badA = a; 10 | badB = b; 11 | } 12 | 13 | public int getA() { return badA; } 14 | public int getB() { return badB; } 15 | } 16 | -------------------------------------------------------------------------------- /ch06/solutions/HelloZero.java: -------------------------------------------------------------------------------- 1 | package ch06.solutions; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | /** 8 | * An upgraded graphical application with interactivity! 9 | * Use this template to add assertions to guarantee our 10 | * message displays itself in a visible part of the window. 11 | */ 12 | public class HelloZero { 13 | public static void main( String[] args ) { 14 | JFrame frame = new JFrame( "Chapter 6, Exercise 2" ); 15 | frame.add( new HelloComponent0("Hello, Zero!") ); 16 | frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 17 | frame.setSize( 300, 300 ); 18 | frame.setVisible( true ); 19 | } 20 | } 21 | 22 | /* 23 | * Our custom component to display a message and move 24 | * it around as the user drags their mouse. Hopefully 25 | * more of the extends/implements details make sense 26 | * now that you've worked with them more in Chapters 27 | * 5 and 6. 28 | */ 29 | class HelloComponent0 extends JComponent implements MouseMotionListener { 30 | String theMessage; 31 | int messageX = -125, messageY = 95; // Coordinates of the message 32 | 33 | /** 34 | * Create a new component that can draw its message at an arbitrary position. 35 | * That position can be changed by dragging the mouse; we attach a listener 36 | * to pick up those drag events. 37 | */ 38 | public HelloComponent0( String message ) { 39 | theMessage = message; 40 | addMouseMotionListener(this); 41 | assert messageX > 0 : "X coordinate is too small"; 42 | assert messageY > 0 : "Y coordinate is too small"; 43 | } 44 | 45 | public void paintComponent( Graphics g ) { 46 | g.drawString( theMessage, messageX, messageY ); 47 | } 48 | 49 | public void mouseDragged(MouseEvent e) { 50 | // Save the mouse coordinates and paint the message. 51 | messageX = e.getX(); 52 | messageY = e.getY(); 53 | repaint(); 54 | } 55 | 56 | public void mouseMoved(MouseEvent e) { 57 | // Ignore simple movements 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ch06/solutions/Pause.java: -------------------------------------------------------------------------------- 1 | package ch06.solutions; 2 | 3 | public class Pause { 4 | public static void main(String args[]) { 5 | System.out.print("Starting... "); 6 | try { 7 | Thread.sleep(5000); 8 | } catch(InterruptedException ie) { 9 | System.out.println("Interrupted!"); 10 | } 11 | System.out.println("done"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch06/solutions/severe.properties: -------------------------------------------------------------------------------- 1 | # Set the default logging level 2 | .level = SEVERE 3 | # Direct output to the console 4 | handlers = java.util.logging.ConsoleHandler 5 | 6 | -------------------------------------------------------------------------------- /ch07/examples/RawType.java: -------------------------------------------------------------------------------- 1 | package ch07.examples; 2 | 3 | import java.util.*; 4 | 5 | public class RawType { 6 | public static void main(String args[]) { 7 | List list = new ArrayList(); 8 | list.add("foo"); 9 | 10 | String[] sa = {"hi", "there"}; 11 | List ls = Arrays.asList(sa); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch07/examples/game/AppleToss.java: -------------------------------------------------------------------------------- 1 | package ch07.examples.game; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * Our apple tossing game. This class extends JFrame to create our 7 | * main application window. We'll be filling this out along the way, 8 | * but for now we can setup a field with some trees and our player. 9 | */ 10 | public class AppleToss extends JFrame { 11 | 12 | Field field = new Field(); 13 | Physicist player1 = new Physicist(); 14 | 15 | public AppleToss() { 16 | // Create our frame 17 | super("Apple Toss Game"); 18 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 | setSize(800,600); 20 | setResizable(false); 21 | 22 | // Build the field with our player and some trees 23 | setupFieldForOnePlayer(); 24 | } 25 | 26 | /** 27 | * A helper method to populate a one player field with target trees. 28 | */ 29 | private void setupFieldForOnePlayer() { 30 | // Place our (new) physicist in the lower left corner and connect them to the field 31 | player1.setPosition(100,500); 32 | field.setPlayer(player1); 33 | player1.setField(field); 34 | 35 | // Place our lone hedge 36 | field.setupHedge(); 37 | 38 | // And now make a few trees for target practice 39 | for (int row = 1; row <= 2; row++) { 40 | for (int col = 1; col <=3; col++) { 41 | field.addTree(col * 100, row * 100); 42 | } 43 | } 44 | add(field); 45 | } 46 | 47 | public static void main(String args[]) { 48 | AppleToss game = new AppleToss(); 49 | game.setVisible(true); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ch07/examples/game/Field.java: -------------------------------------------------------------------------------- 1 | package ch07.examples.game; 2 | 3 | import javax.swing.*; 4 | import java.awt.Color; 5 | import java.awt.Graphics; 6 | import java.util.*; 7 | 8 | /** 9 | * The playing field for our game. Now we can setup some constants for 10 | * other game classes to use and create member variables for our player and some trees. 11 | */ 12 | public class Field extends JComponent { 13 | public static final float GRAVITY = 9.8f; // feet per second per second 14 | public static final int STEP = 40; // duration of an animation frame in milliseconds 15 | public static final int APPLE_SIZE_IN_PIXELS = 30; 16 | public static final int TREE_WIDTH_IN_PIXELS = 60; 17 | public static final int TREE_HEIGHT_IN_PIXELS = 2 * TREE_WIDTH_IN_PIXELS; 18 | public static final int PHYSICIST_SIZE_IN_PIXELS = 75; 19 | public static final int MAX_TREES = 12; 20 | 21 | Color fieldColor = Color.LIGHT_GRAY; 22 | Random random = new Random(); 23 | 24 | // List and ArrayList are covered in chapter 8 on Generics 25 | // synchronizedArrayList is covered in chapter 9 on Threads 26 | Physicist physicist; 27 | List trees = Collections.synchronizedList(new ArrayList<>()); 28 | Hedge hedge = new Hedge(); 29 | 30 | protected void paintComponent(Graphics g) { 31 | g.setColor(fieldColor); 32 | g.fillRect(0,0, getWidth(), getHeight()); 33 | for (Tree t : trees) { 34 | t.draw(g); 35 | } 36 | hedge.draw(g); 37 | physicist.draw(g); 38 | } 39 | 40 | public void setPlayer(Physicist p) { 41 | physicist = p; 42 | } 43 | 44 | public void setupHedge() { 45 | // Setup our new obstacle similar to the tree 46 | hedge.setPosition(500,200); 47 | } 48 | 49 | public void addTree(int x, int y) { 50 | Tree tree = new Tree(); 51 | tree.setPosition(x,y); 52 | trees.add(tree); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ch07/examples/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch07.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch07/examples/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch07.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color hedgeColor = Color.GREEN.darker(); 14 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 15 | private int hedgeHeight = (int)(hedgeWidth / 2); 16 | 17 | // Boundary helpers 18 | private Rectangle boundingBox; 19 | 20 | @Override 21 | public void setPosition(int x, int y) { 22 | this.x = x; 23 | this.y = y; 24 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(hedgeColor); 45 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 46 | } 47 | 48 | @Override 49 | public boolean isTouching(GamePiece otherPiece) { 50 | // We don't really have any collisions to detect yet, so just return "no". 51 | // As we fill out all of the game pieces, we'll come back to this method 52 | // and provide a more useful response. 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch07/examples/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch07.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | if (this == otherPiece) { 57 | // By definition we don't collide with ourselves 58 | return false; 59 | } 60 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch07/exercises/Employee.java: -------------------------------------------------------------------------------- 1 | package ch07.exercises; 2 | 3 | public class Employee { 4 | private Integer id; 5 | private String first; 6 | private String last; 7 | 8 | public Employee(String firstname, String lastname, Integer id) { 9 | this.first = firstname; 10 | this.last = lastname; 11 | this.id = id; 12 | } 13 | 14 | public String getFirstName() { return first; } 15 | public String getLastName() { return last; } 16 | public Integer getID() { return id; } 17 | } 18 | -------------------------------------------------------------------------------- /ch07/exercises/EmployeeList.java: -------------------------------------------------------------------------------- 1 | package ch07.exercises; 2 | 3 | import java.util.*; 4 | 5 | public class EmployeeList { 6 | public static void main(String args[]) { 7 | Map employees = new HashMap<>(); 8 | employees.put(2, new Employee("Plato", "Athens", 2)); 9 | employees.put(4, new Employee("Alcibiades", "Athens", 4)); 10 | employees.put(27, new Employee("Crito", "Alopece", 27)); 11 | employees.put(64, new Employee("Phaedo", "Elis", 64)); 12 | employees.put(125, new Employee("Apollodorus", "Phaleron", 125)); 13 | 14 | for (Integer id : employees.keySet()) { 15 | Employee e = employees.get(id); 16 | System.out.print("Employee #" + id + " : "); 17 | System.out.println(e.getFirstName() + " " + e.getLastName()); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch07/exercises/game/AppleToss.java: -------------------------------------------------------------------------------- 1 | package ch07.exercises.game; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * Our apple tossing game. This class extends JFrame to create our 7 | * main application window. We'll be filling this out along the way, 8 | * but for now we can setup a field with some trees and our player. 9 | */ 10 | public class AppleToss extends JFrame { 11 | 12 | Field field = new Field(); 13 | Physicist player1 = new Physicist(); 14 | 15 | public AppleToss() { 16 | // Create our frame 17 | super("Apple Toss Game"); 18 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 | setSize(800,600); 20 | setResizable(false); 21 | 22 | // Build the field with our player and some trees 23 | setupFieldForOnePlayer(); 24 | } 25 | 26 | /** 27 | * A helper method to populate a one player field with target trees. 28 | */ 29 | private void setupFieldForOnePlayer() { 30 | // Place our (new) physicist in the lower left corner and connect them to the field 31 | player1.setPosition(100,500); 32 | field.setPlayer(player1); 33 | player1.setField(field); 34 | 35 | // Place our lone hedge 36 | field.setupHedge(); 37 | 38 | // And now make a few trees for target practice 39 | for (int row = 1; row <= 2; row++) { 40 | for (int col = 1; col <=3; col++) { 41 | field.addTree(col * 100, row * 100); 42 | } 43 | } 44 | add(field); 45 | } 46 | 47 | public static void main(String args[]) { 48 | AppleToss game = new AppleToss(); 49 | game.setVisible(true); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ch07/exercises/game/Field.java: -------------------------------------------------------------------------------- 1 | package ch07.exercises.game; 2 | 3 | import javax.swing.*; 4 | import java.awt.Color; 5 | import java.awt.Graphics; 6 | import java.util.*; 7 | 8 | /** 9 | * The playing field for our game. Now we can setup some constants for 10 | * other game classes to use and create member variables for our player and some trees. 11 | */ 12 | public class Field extends JComponent { 13 | public static final float GRAVITY = 9.8f; // feet per second per second 14 | public static final int STEP = 40; // duration of an animation frame in milliseconds 15 | public static final int APPLE_SIZE_IN_PIXELS = 30; 16 | public static final int TREE_WIDTH_IN_PIXELS = 60; 17 | public static final int TREE_HEIGHT_IN_PIXELS = 2 * TREE_WIDTH_IN_PIXELS; 18 | public static final int PHYSICIST_SIZE_IN_PIXELS = 75; 19 | public static final int MAX_TREES = 12; 20 | 21 | Color fieldColor = Color.LIGHT_GRAY; 22 | Random random = new Random(); 23 | 24 | // List and ArrayList are covered in chapter 8 on Generics 25 | // synchronizedArrayList is covered in chapter 9 on Threads 26 | Physicist physicist; 27 | List trees = Collections.synchronizedList(new ArrayList<>()); 28 | Hedge hedge = new Hedge(); 29 | 30 | protected void paintComponent(Graphics g) { 31 | g.setColor(fieldColor); 32 | g.fillRect(0,0, getWidth(), getHeight()); 33 | for (Tree t : trees) { 34 | t.draw(g); 35 | } 36 | hedge.draw(g); 37 | physicist.draw(g); 38 | } 39 | 40 | public void setPlayer(Physicist p) { 41 | physicist = p; 42 | } 43 | 44 | public void setupHedge() { 45 | // Setup our new obstacle similar to the tree 46 | hedge.setPosition(500,200); 47 | } 48 | 49 | public void addTree(int x, int y) { 50 | Tree tree = new Tree(); 51 | tree.setPosition(x,y); 52 | trees.add(tree); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ch07/exercises/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch07.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch07/exercises/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch07.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color hedgeColor = Color.GREEN.darker(); 14 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 15 | private int hedgeHeight = (int)(hedgeWidth / 2); 16 | 17 | // Boundary helpers 18 | private Rectangle boundingBox; 19 | 20 | @Override 21 | public void setPosition(int x, int y) { 22 | this.x = x; 23 | this.y = y; 24 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(hedgeColor); 45 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 46 | } 47 | 48 | @Override 49 | public boolean isTouching(GamePiece otherPiece) { 50 | // We don't really have any collisions to detect yet, so just return "no". 51 | // As we fill out all of the game pieces, we'll come back to this method 52 | // and provide a more useful response. 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch07/exercises/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch07.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | if (this == otherPiece) { 57 | // By definition we don't collide with ourselves 58 | return false; 59 | } 60 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch07/solutions/Employee.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions; 2 | 3 | public class Employee { 4 | private Integer id; 5 | private String first; 6 | private String last; 7 | 8 | public Employee(String firstname, String lastname, Integer id) { 9 | this.first = firstname; 10 | this.last = lastname; 11 | this.id = id; 12 | } 13 | 14 | public String getFirstName() { return first; } 15 | public String getLastName() { return last; } 16 | public Integer getID() { return id; } 17 | } 18 | -------------------------------------------------------------------------------- /ch07/solutions/Employee2.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions; 2 | 3 | public class Employee2 implements Comparable { 4 | private Integer id; 5 | private String first; 6 | private String last; 7 | 8 | public Employee2(String firstname, String lastname, Integer id) { 9 | this.first = firstname; 10 | this.last = lastname; 11 | this.id = id; 12 | } 13 | 14 | public String getFirstName() { return first; } 15 | public String getLastName() { return last; } 16 | public Integer getID() { return id; } 17 | 18 | public int compareTo(Employee2 other) { 19 | // Let's be a little fancy and sort on a constructed name 20 | String myName = last + ", " + first; 21 | //String otherName = other.getLastName() + ", " + other.getFirstName(); 22 | String otherName = other.last + ", " + other.first; 23 | return myName.compareToIgnoreCase(otherName); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch07/solutions/EmployeeList.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions; 2 | 3 | import java.util.*; 4 | 5 | public class EmployeeList { 6 | public static void main(String args[]) { 7 | Map employees = new HashMap<>(); 8 | employees.put(2, new Employee("Plato", "Athens", 2)); 9 | employees.put(4, new Employee("Alcibiades", "Athens", 4)); 10 | employees.put(27, new Employee("Crito", "Alopece", 27)); 11 | employees.put(64, new Employee("Phaedo", "Elis", 64)); 12 | employees.put(125, new Employee("Apollodorus", "Phaleron", 125)); 13 | 14 | List ids = new ArrayList<>(employees.keySet()); 15 | Collections.sort(ids); 16 | 17 | for (Integer id : ids) { 18 | Employee e = employees.get(id); 19 | System.out.print("Employee #" + id + " : "); 20 | System.out.println(e.getFirstName() + " " + e.getLastName()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch07/solutions/EmployeeList2.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions; 2 | 3 | import java.util.*; 4 | 5 | public class EmployeeList2 { 6 | public static void main(String args[]) { 7 | Map employees = new HashMap<>(); 8 | employees.put(2, new Employee2("Plato", "Athens", 2)); 9 | employees.put(4, new Employee2("Alcibiades", "Athens", 4)); 10 | employees.put(27, new Employee2("Crito", "Alopece", 27)); 11 | employees.put(64, new Employee2("Phaedo", "Elis", 64)); 12 | employees.put(125, new Employee2("Apollodorus", "Phaleron", 125)); 13 | 14 | List es = new ArrayList<>(employees.values()); 15 | Collections.sort(es); 16 | 17 | for (Employee2 e : es) { 18 | System.out.print("Employee #" + e.getID() + " : "); 19 | System.out.println(e.getFirstName() + " " + e.getLastName()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch07/solutions/game/AppleToss.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions.game; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * Our apple tossing game. This class extends JFrame to create our 7 | * main application window. We'll be filling this out along the way, 8 | * but for now we can setup a field with some trees and our player. 9 | */ 10 | public class AppleToss extends JFrame { 11 | 12 | Field field = new Field(); 13 | Physicist player1 = new Physicist(); 14 | 15 | public AppleToss() { 16 | // Create our frame 17 | super("Apple Toss Game"); 18 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 19 | setSize(800,600); 20 | setResizable(false); 21 | 22 | // Build the field with our player and some trees 23 | setupFieldForOnePlayer(); 24 | } 25 | 26 | /** 27 | * A helper method to populate a one player field with target trees. 28 | * Expanded to include setting up hedges as part of Advanced Exercise 1. 29 | */ 30 | private void setupFieldForOnePlayer() { 31 | // Place our (new) physicist in the lower left corner and connect them to the field 32 | player1.setPosition(100,500); 33 | field.setPlayer(player1); 34 | player1.setField(field); 35 | 36 | // Make a few trees for target practice 37 | for (int row = 1; row <= 2; row++) { 38 | for (int col = 1; col <=3; col++) { 39 | field.addTree(col * 100, row * 100); 40 | } 41 | } 42 | 43 | // And add one row of hedges similar to the trees 44 | for (int h = 1; h <= 4; h++) { 45 | field.addHedge(h * 80 + 380, 240); 46 | } 47 | 48 | add(field); 49 | } 50 | 51 | public static void main(String args[]) { 52 | AppleToss game = new AppleToss(); 53 | game.setVisible(true); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch07/solutions/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch07/solutions/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color hedgeColor = Color.GREEN.darker(); 14 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 15 | private int hedgeHeight = (int)(hedgeWidth / 2); 16 | 17 | // Boundary helpers 18 | private Rectangle boundingBox; 19 | 20 | @Override 21 | public void setPosition(int x, int y) { 22 | this.x = x; 23 | this.y = y; 24 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(hedgeColor); 45 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 46 | } 47 | 48 | @Override 49 | public boolean isTouching(GamePiece otherPiece) { 50 | // We don't really have any collisions to detect yet, so just return "no". 51 | // As we fill out all of the game pieces, we'll come back to this method 52 | // and provide a more useful response. 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch07/solutions/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch07.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | if (this == otherPiece) { 57 | // By definition we don't collide with ourselves 58 | return false; 59 | } 60 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch08/examples/ValidEmail.java: -------------------------------------------------------------------------------- 1 | package ch08.examples; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | public class ValidEmail { 6 | static String[] validators = { 7 | ".*@.*", 8 | "[^@]+@[^@]+", 9 | "[^@]+@[^@]+\\.(com|org)", 10 | "[^@]+@[^@]+\\.[a-z]+", 11 | "(?i)[^@]+@[^@]+\\.[a-z]+" 12 | }; 13 | 14 | public static void main(String args[]) { 15 | String sample = "my.name@some.domain"; 16 | if (args.length == 1) { 17 | // Got one command-line arg, use it as the address to check 18 | sample = args[0]; 19 | } else { 20 | System.out.println("Using default email address: " + sample); 21 | System.out.println("To use your own address, provide it as the sole command-line argument."); 22 | } 23 | 24 | // To make pretty output, let's find the longest pattern 25 | int max = 0; 26 | for (String v : validators) { 27 | if (v.length() > max) { max = v.length(); } 28 | } 29 | 30 | // Now let's try each validator and show our result 31 | for (String v : validators) { 32 | System.out.print(sample + " : "); 33 | System.out.print(v + " => "); 34 | for (int s = (max - v.length()); s > 0; s--) { 35 | System.out.print(" "); 36 | } 37 | System.out.println(Pattern.matches(v, sample)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch08/examples/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch08.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch08/examples/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch08.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | if (this == otherPiece) { 57 | // By definition we don't collide with ourselves 58 | return false; 59 | } 60 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch08/exercises/HelloChapter8.java: -------------------------------------------------------------------------------- 1 | package ch08.exercises; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | /** 8 | * Starting with the HelloJava3 class as the basis for this 9 | * new variation. For this exercise, you need to process the 10 | * command-line arguments for the message and its initial 11 | * position on the screen. 12 | */ 13 | public class HelloChapter8 extends JFrame { 14 | 15 | public static void main(String[] args) { 16 | String msg = "Hello, utilities!"; 17 | int x = 150; 18 | int y = 150; 19 | HelloChapter8 demo = new HelloChapter8(msg, x, y); 20 | demo.setVisible(true); 21 | } 22 | 23 | public HelloChapter8(String msg, int x, int y) { 24 | super("Chapter 8, Exercise 1"); 25 | add(new HelloComponent8(msg, x, y)); 26 | setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 27 | setSize(300, 300); 28 | } 29 | 30 | class HelloComponent8 extends JComponent { 31 | String theMessage; 32 | int messageX = 125, messageY = 95; // Coordinates of the message 33 | 34 | public HelloComponent8(String message, int x, int y) { 35 | theMessage = message; 36 | messageX = x; 37 | messageY = y; 38 | addMouseMotionListener(new MouseMotionListener() { 39 | public void mouseDragged(MouseEvent e) { 40 | messageX = e.getX(); 41 | messageY = e.getY(); 42 | repaint(); 43 | } 44 | 45 | public void mouseMoved(MouseEvent e) { } 46 | }); 47 | } 48 | 49 | public void paintComponent( Graphics g ) { 50 | g.drawString( theMessage, messageX, messageY ); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ch09/examples/Thready.java: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | public class Thready { 4 | public static void main( String args [] ) { 5 | new Thread(new ShowThread("Foo")).start(); 6 | new Thread(new ShowThread("Bar")).start(); 7 | } 8 | 9 | static class ShowThread implements Runnable { 10 | String message; 11 | 12 | ShowThread( String message ) { 13 | this.message = message; 14 | } 15 | public void run() { 16 | while ( true ) 17 | System.out.println( message ); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch09/examples/Thready2.java: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | public class Thready2 { 4 | public static void main( String args [] ) { 5 | Thread foo = new Thread(new ShowThread("Foo")); 6 | foo.setPriority( Thread.MIN_PRIORITY ); 7 | Thread bar = new Thread(new ShowThread("Bar")); 8 | bar.setPriority( Thread.MAX_PRIORITY ); 9 | 10 | foo.start(); 11 | bar.start(); 12 | } 13 | 14 | static class ShowThread implements Runnable { 15 | String message; 16 | 17 | ShowThread( String message ) { 18 | this.message = message; 19 | } 20 | public void run() { 21 | while ( true ) 22 | System.out.println( message ); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch09/examples/URLConsumer3.java: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * A threaded client for our URL producer. Uses a synchronized queue 7 | * to safely read a URL for processing. (Our simple demo "processes" 8 | * by printing out the ID of this consumer and the url it consumed.) 9 | * 10 | * This version handles one URL and ends. There is no "keep working" 11 | * flag nor delay. 12 | */ 13 | public class URLConsumer3 implements Runnable { 14 | String consumerID; 15 | URLQueue queue; 16 | 17 | /** 18 | * Creates a new consumer with the given ID and reference to the shared queue. 19 | * 20 | * @param id A unique (unenforced) name for this consumer 21 | * @param queue The shared queue for storing and distributing URLs 22 | */ 23 | public URLConsumer3(String id, URLQueue queue) { 24 | if (queue == null) { 25 | throw new IllegalArgumentException("Shared queue cannot be null"); 26 | } 27 | consumerID = id; 28 | this.queue = queue; 29 | } 30 | 31 | /** 32 | * Our working method for the thread. Watches the boolean flag 33 | * keepWorking as well as the state of the queue to determine 34 | * whether or not to complete the loop. While working, grab a 35 | * URL and print it out then repeat. 36 | */ 37 | public void run() { 38 | String url = queue.getURL(); 39 | if (url != null) { 40 | if (url.endsWith("0000")) { 41 | System.out.println(consumerID + " consumed " + url); 42 | } 43 | } else { 44 | System.out.println(consumerID + " skipped empty queue"); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ch09/examples/URLDemo.java: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | /** 4 | * Manage multiple producers and consumers to demonstrate how 5 | * threads work in tandem. Creates a pair of producers and a 6 | * pair of consumers all with access to a shared queue. 7 | * 8 | * @see URLQueue 9 | * @see URLProducer 10 | * @see URLConsumer 11 | */ 12 | public class URLDemo { 13 | public static void main(String args[]) { 14 | // Create our shared queue object 15 | URLQueue queue = new URLQueue(); 16 | 17 | // Now create some producers with unique names and a reference to our queue 18 | URLProducer p1 = new URLProducer("P1", 3, queue); 19 | URLProducer p2 = new URLProducer("P2", 3, queue); 20 | 21 | // And some consumers with their own names and a reference to our queue 22 | URLConsumer c1 = new URLConsumer("C1", queue); 23 | URLConsumer c2 = new URLConsumer("C2", queue); 24 | 25 | // Get everyone going! 26 | System.out.println("Starting..."); 27 | Thread tp1 = new Thread(p1); 28 | tp1.start(); 29 | Thread tp2 = new Thread(p2); 30 | tp2.start(); 31 | Thread tc1 = new Thread(c1); 32 | tc1.start(); 33 | Thread tc2 = new Thread(c2); 34 | tc2.start(); 35 | 36 | // First wait around for the producers to finish 37 | try { 38 | tp1.join(); 39 | tp2.join(); 40 | } catch (InterruptedException ie) { 41 | System.err.println("Interrupted waiting for producers to finish"); 42 | } 43 | 44 | // OK, we know there won't be any more URLs made, so let the consumers 45 | // finish once the queue is empty 46 | c1.setKeepWorking(false); 47 | c2.setKeepWorking(false); 48 | try { 49 | tc1.join(); 50 | tc2.join(); 51 | } catch (InterruptedException ie) { 52 | System.err.println("Interrupted waiting for consumers to finish"); 53 | } 54 | 55 | System.out.println("Done"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ch09/examples/URLDemo2.java.preview: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | /** 4 | * Manage multiple producers and consumers to demonstrate how 5 | * threads work in tandem. Creates a pair of producers and a 6 | * pair of consumers all with access to a shared queue. 7 | * 8 | * This version uses virtual threads rather than the platform 9 | * threads in URLDemo.java 10 | * 11 | * @see URLQueue 12 | * @see URLProducer 13 | * @see URLConsumer 14 | */ 15 | public class URLDemo2 { 16 | public static void main(String args[]) { 17 | // Create our shared queue object 18 | URLQueue queue = new URLQueue(); 19 | 20 | // Now create some producers with unique names and a reference to our queue 21 | URLProducer p1 = new URLProducer("P1", 3, queue); 22 | URLProducer p2 = new URLProducer("P2", 3, queue); 23 | 24 | // And some consumers with their own names and a reference to our queue 25 | URLConsumer c1 = new URLConsumer("C1", queue); 26 | URLConsumer c2 = new URLConsumer("C2", queue); 27 | 28 | // Get everyone going! 29 | System.out.println("Starting virtual threads..."); 30 | Thread vp1 = Thread.startVirtualThread(p1); 31 | Thread vp2 = Thread.startVirtualThread(p2); 32 | Thread vc1 = Thread.startVirtualThread(c1); 33 | Thread vc2 = Thread.startVirtualThread(c2); 34 | 35 | // First wait around for the producers to finish 36 | try { 37 | vp1.join(); 38 | vp2.join(); 39 | } catch (InterruptedException ie) { 40 | System.err.println("Interrupted waiting for producers to finish"); 41 | } 42 | 43 | // OK, we know there won't be any more URLs made, so let the consumers 44 | // finish once the queue is empty 45 | c1.setKeepWorking(false); 46 | c2.setKeepWorking(false); 47 | try { 48 | vc1.join(); 49 | vc2.join(); 50 | } catch (InterruptedException ie) { 51 | System.err.println("Interrupted waiting for consumers to finish"); 52 | } 53 | 54 | System.out.println("Done"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ch09/examples/URLProducer.java: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Simple producer for use in our multithreaded example. 7 | * Uses a synchronized queue to safely store URLs for processing. 8 | */ 9 | public class URLProducer implements Runnable { 10 | String producerID; 11 | int urlCount; 12 | URLQueue queue; 13 | 14 | Random delay; 15 | 16 | /** 17 | * Create a new producer with the given name. It will produce the 18 | * specified number of URLs and store them in the provided queue. 19 | * 20 | * @param id A unique (unenforced) name for this producer 21 | * @param count How many URLs this producer will create before quitting 22 | * @param queue The shared, synchronized queue for URLs 23 | */ 24 | public URLProducer(String id, int count, URLQueue queue) { 25 | // Don't even create this producer if a negative count was supplied or there's no queue 26 | if (count <= 0) { 27 | throw new IllegalArgumentException("Count must be positive"); 28 | } 29 | if (queue == null) { 30 | throw new IllegalArgumentException("Shared queue cannot be null"); 31 | } 32 | producerID = id; 33 | urlCount = count; 34 | this.queue = queue; 35 | delay = new Random(); 36 | } 37 | 38 | /** 39 | * Our working method for the thread. Uses the count supplied to 40 | * the constructor to produce a batch of URLs and store them to 41 | * the shared queue. To make it a little more interesting, a random 42 | * delay is added at the end of each iteration. 43 | */ 44 | public void run() { 45 | for (int i = 1; i <= urlCount; i++) { 46 | String url = "https://some.url/at/path/" + i; 47 | queue.addURL(producerID + " " + url); 48 | System.out.println(producerID + " produced " + url); 49 | try { 50 | Thread.sleep(delay.nextInt(500)); 51 | } catch (InterruptedException ie) { 52 | System.err.println("Producer " + producerID + " interrupted. Quitting."); 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ch09/examples/URLProducer4.java: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | import java.util.Random; 4 | import java.util.Queue; 5 | 6 | /** 7 | * Simple producer for use in our multithreaded example. 8 | * Uses a synchronized queue to safely store URLs for processing. 9 | */ 10 | public class URLProducer4 implements Runnable { 11 | String producerID; 12 | int urlCount; 13 | Queue queue; 14 | 15 | Random delay; 16 | 17 | /** 18 | * Create a new producer with the given name. It will produce the 19 | * specified number of URLs and store them in the provided queue. 20 | * 21 | * @param id A unique (unenforced) name for this producer 22 | * @param count How many URLs this producer will create before quitting 23 | * @param queue The shared, synchronized queue for URLs 24 | */ 25 | public URLProducer4(String id, int count, Queue queue) { 26 | // Don't even create this producer if a negative count was supplied or there's no queue 27 | if (count <= 0) { 28 | throw new IllegalArgumentException("Count must be positive"); 29 | } 30 | if (queue == null) { 31 | throw new IllegalArgumentException("Shared queue cannot be null"); 32 | } 33 | producerID = id; 34 | urlCount = count; 35 | this.queue = queue; 36 | delay = new Random(); 37 | } 38 | 39 | /** 40 | * Our working method for the thread. Uses the count supplied to 41 | * the constructor to produce a batch of URLs and store them to 42 | * the shared queue. To make it a little more interesting, a random 43 | * delay is added at the end of each iteration. 44 | */ 45 | public void run() { 46 | for (int i = 1; i <= urlCount; i++) { 47 | String url = "https://some.url/at/path/" + i; 48 | queue.add(producerID + " " + url); 49 | System.out.println(producerID + " produced " + url); 50 | try { 51 | Thread.sleep(delay.nextInt(500)); 52 | } catch (InterruptedException ie) { 53 | System.err.println("Producer " + producerID + " interrupted. Quitting."); 54 | break; 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ch09/examples/URLQueue.java: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * A manually synchronized wrapper for a LinkedList. 7 | * Allows for safely adding and removing URLs in order. 8 | */ 9 | public class URLQueue { 10 | LinkedList urlQueue = new LinkedList<>(); 11 | 12 | public synchronized void addURL(String url) { 13 | urlQueue.add(url); 14 | } 15 | 16 | public synchronized String getURL() { 17 | if (!urlQueue.isEmpty()) { 18 | return urlQueue.removeFirst(); 19 | } 20 | return null; 21 | } 22 | 23 | public boolean isEmpty() { 24 | return urlQueue.isEmpty(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch09/examples/VirtualDemo.java.preview: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | public class VirtualDemo { 4 | public static void main(String args[]) throws Exception { 5 | Runnable runnable = () -> System.out.println("Hello virtual thread! ID: " + Thread.currentThread().threadId()); 6 | Thread thread = Thread.startVirtualThread(runnable); 7 | thread.join(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ch09/examples/VirtualDemo2.java.preview: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | public class VirtualDemo2 { 4 | public static void main(String args[]) throws Exception { 5 | Runnable runnable = new Runnable() { 6 | public void run() { 7 | Thread t = Thread.currentThread(); 8 | System.out.println("Hello thread! " + 9 | (t.isVirtual() ? "virtual " : "platform ") + 10 | "ID: " + t.threadId()); 11 | } 12 | }; 13 | Thread thread1 = new Thread(runnable); 14 | thread1.start(); 15 | Thread thread2 = Thread.startVirtualThread(runnable); 16 | thread1.join(); 17 | thread2.join(); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /ch09/examples/VirtualThready.java.preview: -------------------------------------------------------------------------------- 1 | package ch09.examples; 2 | 3 | public class VirtualThready { 4 | public static void main( String args [] ) throws InterruptedException { 5 | Thread t1 = Thread.startVirtualThread(new ShowThread("VFoo")); 6 | Thread t2 = Thread.startVirtualThread(new ShowThread("VBar")); 7 | t1.join(); 8 | t2.join(); 9 | } 10 | 11 | static class ShowThread implements Runnable { 12 | String message; 13 | 14 | ShowThread( String message ) { 15 | this.message = message; 16 | } 17 | public void run() { 18 | while ( true ) 19 | System.out.println( message ); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch09/exercises/Clock.java: -------------------------------------------------------------------------------- 1 | package ch09.exercises; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | 6 | public class Clock extends JFrame { 7 | JLabel clockLabel; 8 | 9 | public Clock() { 10 | super("Java Clock"); 11 | setSize(400,200); 12 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 13 | clockLabel = new JLabel("00:00:00", JLabel.CENTER); 14 | clockLabel.setFont(new Font("Arial", Font.BOLD, 24)); 15 | getContentPane().add(clockLabel, BorderLayout.CENTER); 16 | } 17 | 18 | public void startClock() { 19 | // Set up your thread here. It should sleep for one second 20 | // and then update the text in clockLabel. 21 | } 22 | 23 | public static void main(String args[]) { 24 | Clock c = new Clock(); 25 | c.setVisible(true); 26 | c.startClock(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch09/exercises/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch09.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch09/exercises/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch09.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color hedgeColor = Color.GREEN.darker(); 14 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 15 | private int hedgeHeight = (int)(hedgeWidth / 2); 16 | 17 | // Boundary helpers 18 | private Rectangle boundingBox; 19 | 20 | @Override 21 | public void setPosition(int x, int y) { 22 | this.x = x; 23 | this.y = y; 24 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(hedgeColor); 45 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 46 | } 47 | 48 | @Override 49 | public boolean isTouching(GamePiece otherPiece) { 50 | // We don't really have any collisions to detect yet, so just return "no". 51 | // As we fill out all of the game pieces, we'll come back to this method 52 | // and provide a more useful response. 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch09/exercises/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch09.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | if (this == otherPiece) { 57 | // By definition we don't collide with ourselves 58 | return false; 59 | } 60 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch09/solutions/Clock.java: -------------------------------------------------------------------------------- 1 | package ch09.solutions; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | import java.time.LocalTime; 6 | import java.time.format.DateTimeFormatter; 7 | 8 | public class Clock extends JFrame { 9 | JLabel clockLabel; 10 | Thread runner; 11 | DateTimeFormatter hms = DateTimeFormatter.ofPattern("hh:mm:ss"); 12 | 13 | public Clock() { 14 | super("Java Clock"); 15 | setSize(400,200); 16 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 17 | clockLabel = new JLabel("00:00:00", JLabel.CENTER); 18 | clockLabel.setFont(new Font("Arial", Font.BOLD, 24)); 19 | getContentPane().add(clockLabel, BorderLayout.CENTER); 20 | } 21 | 22 | public void startClock() { 23 | runner = new Thread(new Runnable() { 24 | public void run() { 25 | while (true) { 26 | String time = hms.format(LocalTime.now()); 27 | clockLabel.setText(time); 28 | clockLabel.repaint(); 29 | try { 30 | Thread.sleep(1000); 31 | } catch (InterruptedException ie) { 32 | clockLabel.setText("--:--:--"); 33 | break; 34 | } 35 | } 36 | } 37 | }); 38 | runner.start(); 39 | } 40 | 41 | public static void main(String args[]) { 42 | Clock c = new Clock(); 43 | c.setVisible(true); 44 | c.startClock(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ch09/solutions/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch09.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch09/solutions/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch09.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color hedgeColor = Color.GREEN.darker(); 14 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 15 | private int hedgeHeight = (int)(hedgeWidth / 2); 16 | 17 | // Boundary helpers 18 | private Rectangle boundingBox; 19 | 20 | @Override 21 | public void setPosition(int x, int y) { 22 | this.x = x; 23 | this.y = y; 24 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(hedgeColor); 45 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 46 | } 47 | 48 | @Override 49 | public boolean isTouching(GamePiece otherPiece) { 50 | // We don't really have any collisions to detect yet, so just return "no". 51 | // As we fill out all of the game pieces, we'll come back to this method 52 | // and provide a more useful response. 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch09/solutions/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch09.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | int x, y; 11 | 12 | // Drawing helpers 13 | private Color leafColor = Color.GREEN.darker(); 14 | private Color trunkColor = new Color(101, 67, 33); 15 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 16 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 17 | private int trunkX, trunkY; 18 | 19 | // Boundary helpers 20 | private Rectangle boundingBox; 21 | 22 | @Override 23 | public void setPosition(int x, int y) { 24 | this.x = x; 25 | this.y = y; 26 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 27 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 28 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 29 | } 30 | 31 | @Override 32 | public int getPositionX() { 33 | return x; 34 | } 35 | 36 | @Override 37 | public int getPositionY() { 38 | return y; 39 | } 40 | 41 | @Override 42 | public Rectangle getBoundingBox() { 43 | return boundingBox; 44 | } 45 | 46 | @Override 47 | public void draw(Graphics g) { 48 | g.setColor(trunkColor); 49 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 50 | g.setColor(leafColor); 51 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 52 | } 53 | 54 | @Override 55 | public boolean isTouching(GamePiece otherPiece) { 56 | if (this == otherPiece) { 57 | // By definition we don't collide with ourselves 58 | return false; 59 | } 60 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ch10/examples/ListIt.java: -------------------------------------------------------------------------------- 1 | package ch10.examples; 2 | 3 | import java.io.*; 4 | 5 | /** 6 | * A quick demo of file and directory operations. If the file 7 | * exists and is a directory, the directory gets listed. If it 8 | * is a readable file, the content is dumped to the console. 9 | */ 10 | public class ListIt { 11 | public static void main ( String args[] ) throws Exception { 12 | File file = new File( args[0] ); 13 | 14 | if ( !file.exists() || !file.canRead( ) ) { 15 | System.out.println( "Can't read " + file ); 16 | return; 17 | } 18 | 19 | if ( file.isDirectory( ) ) { 20 | String [] files = file.list( ); 21 | for (int i=0; i< files.length; i++) 22 | System.out.println( files[i] ); 23 | } 24 | else 25 | try { 26 | Reader ir = new InputStreamReader( new FileInputStream( file ) ); 27 | BufferedReader in = new BufferedReader( ir ); 28 | String line; 29 | while ((line = in.readLine( )) != null) 30 | System.out.println(line); 31 | } 32 | catch ( FileNotFoundException e ) { 33 | System.out.println( "File Disappeared" ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch10/examples/ParseKeyboard.java: -------------------------------------------------------------------------------- 1 | package ch10.examples; 2 | 3 | import java.io.*; 4 | import java.text.*; 5 | 6 | public class ParseKeyboard { 7 | public static void main(String args[]) { 8 | try { 9 | System.out.println("Enter a line starting with a number:"); 10 | 11 | InputStream in = System.in; 12 | InputStreamReader charsIn = new InputStreamReader( in ); 13 | BufferedReader bufferedCharsIn = new BufferedReader( charsIn ); 14 | 15 | String line = bufferedCharsIn.readLine(); 16 | int i = NumberFormat.getInstance().parse( line ).intValue(); 17 | 18 | System.out.println("Read line: " + line); 19 | System.out.println("Parsed number: " + i); 20 | bufferedCharsIn.close(); 21 | } catch ( IOException e ) { 22 | System.err.println("Error reading data: " + e); 23 | } catch ( ParseException pe ) { 24 | System.err.println("Error parsing data: " + pe); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch10/examples/access.txt: -------------------------------------------------------------------------------- 1 | This file has been accessed 5 times. 2 | -------------------------------------------------------------------------------- /ch10/exercises/Count.java: -------------------------------------------------------------------------------- 1 | package ch10.exercises; 2 | 3 | import java.io.*; 4 | 5 | public class Count { 6 | String fileToCount; 7 | 8 | public Count(String fileToCount) { 9 | this.fileToCount = fileToCount; 10 | // ... 11 | } 12 | 13 | public void printStats() { 14 | System.out.println("Analyzing " + fileToCount); 15 | // ... 16 | } 17 | 18 | public static void main(String args[]) { 19 | // Check for a filename argument; if it's missing, print an error 20 | // ... 21 | 22 | // Create a new instance of Count with the given file and get its stats 23 | Count c = new Count(args[0]); 24 | c.printStats(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ch10/solutions/Count1.java: -------------------------------------------------------------------------------- 1 | package ch10.solutions; 2 | 3 | import java.io.*; 4 | 5 | public class Count1 { 6 | File toCount; 7 | 8 | public Count1(String fileToCount) { 9 | toCount = new File(fileToCount); 10 | } 11 | 12 | public void printStats() { 13 | System.out.println("Analyzing " + toCount.getName()); 14 | if (toCount.exists()) { 15 | System.out.println(" Size: " + toCount.length() + " bytes"); 16 | } else { 17 | System.out.println(" (Not found)"); 18 | } 19 | } 20 | 21 | public static void main(String args[]) { 22 | // Check for a filename argument; if it's missing, print an error 23 | if (args.length != 1) { 24 | System.err.println("Must supply one filename to analyze."); 25 | System.exit(1); 26 | } 27 | 28 | // Create a new instance of Count with the given file and get its stats 29 | Count1 c = new Count1(args[0]); 30 | c.printStats(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch10/solutions/Count2.java: -------------------------------------------------------------------------------- 1 | package ch10.solutions; 2 | 3 | import java.io.*; 4 | 5 | public class Count2 { 6 | File toCount; 7 | long lineCount; 8 | long wordCount; 9 | 10 | public Count2(String fileToCount) { 11 | toCount = new File(fileToCount); 12 | } 13 | 14 | public void printStats() { 15 | System.out.println("Analyzing " + toCount.getName()); 16 | if (toCount.canRead()) { 17 | System.out.println(" Size: " + toCount.length() + " bytes"); 18 | try (BufferedReader br = new BufferedReader(new FileReader(toCount))) { 19 | String line = null; 20 | while ((line = br.readLine()) != null) { 21 | lineCount++; 22 | String words[] = line.split("\\s+"); 23 | wordCount += words.length; 24 | } 25 | System.out.println(" Lines: " + lineCount); 26 | System.out.println(" Words: " + wordCount); 27 | } catch (IOException ioe) { 28 | System.err.println("Failed to complete the analysis: " + ioe); 29 | ioe.printStackTrace(System.err); 30 | } 31 | } else { 32 | // Hmm, two possible reasons we can't read the file: 33 | // either it doesn't exist, or it exists but we don't have permission 34 | if (toCount.exists()) { 35 | System.out.println(" (No permission)"); 36 | } else { 37 | System.out.println(" (Not found)"); 38 | } 39 | } 40 | } 41 | 42 | public static void main(String args[]) { 43 | // Check for a filename argument; if it's missing, print an error 44 | if (args.length != 1) { 45 | System.err.println("Must supply one filename to analyze."); 46 | System.exit(1); 47 | } 48 | 49 | // Create a new instance of Count with the given file and get its stats 50 | Count2 c = new Count2(args[0]); 51 | c.printStats(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ch10/solutions/Count3.java: -------------------------------------------------------------------------------- 1 | package ch10.solutions; 2 | 3 | import java.util.List; 4 | import java.io.IOException; 5 | import java.nio.file.Path; 6 | import java.nio.file.Files; 7 | 8 | public class Count3 { 9 | Path toCount; 10 | long lineCount; 11 | long wordCount; 12 | 13 | public Count3(String fileToCount) { 14 | toCount = Path.of(fileToCount); 15 | } 16 | 17 | public void printStats() { 18 | System.out.println("Analyzing " + toCount.getFileName()); 19 | try { 20 | if (Files.isReadable(toCount)) { 21 | System.out.println(" Size: " + Files.size(toCount) + " bytes"); 22 | List lines = Files.readAllLines(toCount); 23 | for (String line : lines) { 24 | lineCount++; 25 | String words[] = line.split("\\s+"); 26 | wordCount += words.length; 27 | } 28 | System.out.println(" Lines: " + lineCount); 29 | System.out.println(" Words: " + wordCount); 30 | } else { 31 | // Hmm, two possible reasons we can't read the file: 32 | // either it doesn't exist, or it exists but we don't have permission 33 | if (Files.exists(toCount)) { 34 | System.out.println(" (No permission)"); 35 | } else { 36 | System.out.println(" (Not found)"); 37 | } 38 | } 39 | } catch (IOException ioe) { 40 | System.err.println("Failed to complete the analysis: " + ioe); 41 | ioe.printStackTrace(System.err); 42 | } 43 | } 44 | 45 | public static void main(String args[]) { 46 | // Check for a filename argument; if it's missing, print an error 47 | if (args.length != 1) { 48 | System.err.println("Must supply one filename to analyze."); 49 | System.exit(1); 50 | } 51 | 52 | // Create a new instance of Count with the given file and get its stats 53 | Count3 c = new Count3(args[0]); 54 | c.printStats(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ch10/solutions/countlog.txt: -------------------------------------------------------------------------------- 1 | 2023-01-23 02:49:59 Count4.java 108 490 3526 2 | 2023-01-23 02:50:36 ListIt.java 36 178 1011 3 | -------------------------------------------------------------------------------- /ch11/examples/Adjuster.java: -------------------------------------------------------------------------------- 1 | package ch11.examples; 2 | 3 | import java.util.function.DoubleUnaryOperator; 4 | 5 | public class Adjuster { 6 | public static double adjust(double val, DoubleUnaryOperator adjustment) { 7 | return adjustment.applyAsDouble(val); 8 | } 9 | 10 | public static void main(String args[]) { 11 | double sample = 70.2; 12 | System.out.println("Initial reading: " + sample); 13 | System.out.print("Adding 3: "); 14 | System.out.println(adjust(sample, s -> s + 3)); 15 | System.out.print("Reducing by 10%: "); 16 | System.out.println(adjust(sample, s -> s * 0.9)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch11/examples/PaidEmployee.java: -------------------------------------------------------------------------------- 1 | package ch11.examples; 2 | 3 | public class PaidEmployee { 4 | private int id; 5 | private String name; 6 | private int salary; // annual, in whole dollars 7 | 8 | public PaidEmployee(String fullname, int id, int salary) { 9 | this.name = fullname; 10 | this.id = id; 11 | this.salary = salary; 12 | } 13 | 14 | public String getName() { return name; } 15 | public int getID() { return id; } 16 | public int getSalary() { return salary; } 17 | } 18 | -------------------------------------------------------------------------------- /ch11/examples/Report.java: -------------------------------------------------------------------------------- 1 | package ch11.examples; 2 | 3 | import java.util.*; 4 | 5 | public class Report { 6 | List employees = new ArrayList<>(); 7 | 8 | void buildEmployeeList() { 9 | employees.add(new PaidEmployee("Fozzi", 4, 30_000)); 10 | employees.add(new PaidEmployee("Gonzo", 2, 50_000)); 11 | employees.add(new PaidEmployee("Kermit", 1, 60_000)); 12 | employees.add(new PaidEmployee("Piggy", 3, 80_000)); 13 | } 14 | 15 | public void publishNames() { 16 | employees.stream().map(e -> e.getName()).forEach(System.out::println); 17 | } 18 | 19 | public void publishBudget() { 20 | int b = employees.stream().mapToInt(e -> e.getSalary()).sum(); 21 | System.out.println("Annual bugdet is " + b); 22 | } 23 | 24 | public static void main(String args[]) { 25 | Report r = new Report(); 26 | r.buildEmployeeList(); 27 | r.publishNames(); 28 | r.publishBudget(); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /ch11/examples/VirtualDemo2.java.preview: -------------------------------------------------------------------------------- 1 | package ch11.examples; 2 | 3 | public class VirtualDemo2 { 4 | public static void main(String args[]) throws Exception { 5 | Runnable runnable = new Runnable() { 6 | public void run() { 7 | System.out.println("Hello thread! " + 8 | "ID: " + Thread.currentThread().threadId()); 9 | } 10 | }; 11 | Thread t = Thread.startVirtualThread(runnable); 12 | t.join(); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /ch11/examples/VirtualDemo3.java.preview: -------------------------------------------------------------------------------- 1 | package ch11.examples; 2 | 3 | public class VirtualDemo3 { 4 | public static void main(String args[]) throws Exception { 5 | Thread t = Thread.startVirtualThread( () -> 6 | System.out.println("Hello thread! " + 7 | "ID: " + Thread.currentThread().threadId()) 8 | ); 9 | t.join(); 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /ch11/examples/WeekDayGenerator.java: -------------------------------------------------------------------------------- 1 | package ch11.examples; 2 | 3 | import java.util.Random; 4 | import java.util.stream.Stream; 5 | import java.util.function.Supplier; 6 | 7 | public class WeekDayGenerator implements Supplier { 8 | private static String[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 9 | private Random randSrc = new Random(); 10 | 11 | public String get() { 12 | return days[randSrc.nextInt(days.length)]; 13 | } 14 | 15 | public static void main(String args[]) { 16 | Stream.generate(new WeekDayGenerator()) 17 | .limit(5) 18 | .forEach(System.out::println); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /ch11/exercises/Adjuster.java: -------------------------------------------------------------------------------- 1 | package ch11.exercises; 2 | 3 | import java.util.function.DoubleUnaryOperator; 4 | 5 | public class Adjuster { 6 | public static double adjust(double val, DoubleUnaryOperator adjustment) { 7 | return adjustment.applyAsDouble(val); 8 | } 9 | 10 | public static void main(String args[]) { 11 | double sample = 70.2; 12 | System.out.println("Initial reading: " + sample); 13 | System.out.print("Adding 3: "); 14 | System.out.println(adjust(sample, s -> s + 3)); 15 | System.out.print("Reducing by 10%: "); 16 | System.out.println(adjust(sample, s -> s * 0.9)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch11/exercises/PaidEmployee.java: -------------------------------------------------------------------------------- 1 | package ch11.exercises; 2 | 3 | public class PaidEmployee { 4 | private int id; 5 | private String name; 6 | private int salary; // annual, in whole dollars 7 | 8 | public PaidEmployee(String fullname, int id, int salary) { 9 | this.name = fullname; 10 | this.id = id; 11 | this.salary = salary; 12 | } 13 | 14 | public String getName() { return name; } 15 | public int getID() { return id; } 16 | public int getSalary() { return salary; } 17 | } 18 | -------------------------------------------------------------------------------- /ch11/exercises/Report.java: -------------------------------------------------------------------------------- 1 | package ch11.exercises; 2 | 3 | import java.util.*; 4 | 5 | public class Report { 6 | List employees = new ArrayList<>(); 7 | 8 | void buildEmployeeList() { 9 | employees.add(new PaidEmployee("Fozzi", 4, 30_000)); 10 | employees.add(new PaidEmployee("Gonzo", 2, 50_000)); 11 | employees.add(new PaidEmployee("Kermit", 1, 60_000)); 12 | employees.add(new PaidEmployee("Piggy", 3, 80_000)); 13 | } 14 | 15 | public void publishNames() { 16 | employees.stream().map(e -> e.getName()).forEach(System.out::println); 17 | } 18 | 19 | public void publishBudget() { 20 | int b = employees.stream().mapToInt(e -> e.getSalary()).sum(); 21 | System.out.println("Annual bugdet is " + b); 22 | } 23 | 24 | public static void main(String args[]) { 25 | Report r = new Report(); 26 | r.buildEmployeeList(); 27 | r.publishNames(); 28 | r.publishBudget(); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /ch11/solutions/Adjuster.java: -------------------------------------------------------------------------------- 1 | package ch11.solutions; 2 | 3 | import java.util.function.DoubleUnaryOperator; 4 | 5 | public class Adjuster { 6 | public static double adjust(double val, DoubleUnaryOperator adjustment) { 7 | return adjustment.applyAsDouble(val); 8 | } 9 | 10 | public static void main(String args[]) { 11 | double sample = 70.2; 12 | System.out.println("Initial reading: " + sample); 13 | System.out.print("Adding 3: "); 14 | System.out.println(adjust(sample, s -> s + 3)); 15 | System.out.print("Reducing by 10%: "); 16 | System.out.println(adjust(sample, s -> s * 0.9)); 17 | System.out.print("Converting to Celsius: "); 18 | System.out.println(adjust(sample, s -> (s - 32) * 5 / 9)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch11/solutions/PaidEmployee.java: -------------------------------------------------------------------------------- 1 | package ch11.solutions; 2 | 3 | public class PaidEmployee { 4 | private int id; 5 | private String name; 6 | private int salary; // annual, in whole dollars 7 | 8 | public PaidEmployee(String fullname, int id, int salary) { 9 | this.name = fullname; 10 | this.id = id; 11 | this.salary = salary; 12 | } 13 | 14 | public String getName() { return name; } 15 | public int getID() { return id; } 16 | public int getSalary() { return salary; } 17 | } 18 | -------------------------------------------------------------------------------- /ch11/solutions/PaidEmployee2.java: -------------------------------------------------------------------------------- 1 | package ch11.solutions; 2 | 3 | public class PaidEmployee2 { 4 | private int id; 5 | private String name; 6 | private int salary; // annual, in whole dollars 7 | private String role; 8 | 9 | public PaidEmployee2(String fullname, int id, int salary, String role) { 10 | this.name = fullname; 11 | this.id = id; 12 | this.salary = salary; 13 | this.role = role; 14 | } 15 | 16 | public String getName() { return name; } 17 | public int getID() { return id; } 18 | public int getSalary() { return salary; } 19 | public String getRole() { return role; } 20 | } 21 | -------------------------------------------------------------------------------- /ch11/solutions/Report.java: -------------------------------------------------------------------------------- 1 | package ch11.solutions; 2 | 3 | import java.util.*; 4 | 5 | public class Report { 6 | List employees = new ArrayList<>(); 7 | 8 | void buildEmployeeList() { 9 | employees.add(new PaidEmployee("Fozzi", 4, 30_000)); 10 | employees.add(new PaidEmployee("Gonzo", 2, 50_000)); 11 | employees.add(new PaidEmployee("Kermit", 1, 60_000)); 12 | employees.add(new PaidEmployee("Piggy", 3, 80_000)); 13 | } 14 | 15 | public void publishNames() { 16 | employees.stream().map(e -> e.getName()).forEach(System.out::println); 17 | } 18 | 19 | public void publishBudget() { 20 | int b = employees.stream().mapToInt(e -> e.getSalary()).sum(); 21 | System.out.println("Annual bugdet is " + b); 22 | } 23 | 24 | public void publishAverage() { 25 | OptionalDouble avg = employees.stream().mapToInt(e -> e.getSalary()).average(); 26 | if (avg.isPresent()) { 27 | System.out.println("Average salary is " + avg.getAsDouble()); 28 | } else { 29 | System.out.println("No salaries were available."); 30 | } 31 | } 32 | 33 | public static void main(String args[]) { 34 | Report r = new Report(); 35 | r.buildEmployeeList(); 36 | r.publishNames(); 37 | r.publishBudget(); 38 | r.publishAverage(); 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /ch12/examples/ActionDemo1.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | 8 | /** 9 | * A simple, classic demonstration of event handling. Create a frame 10 | * with a button and a label. As the button is pressed, a counter 11 | * shown in the label is incremented. 12 | */ 13 | public class ActionDemo1 extends JFrame implements ActionListener { 14 | int counterValue = 0; 15 | JLabel counterLabel; 16 | 17 | public ActionDemo1() { 18 | super( "ActionEvent Counter Demo" ); 19 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 20 | setLayout(new FlowLayout()); 21 | setSize( 300, 180 ); 22 | 23 | counterLabel = new JLabel("Count: 0", JLabel.CENTER ); 24 | add(counterLabel); 25 | 26 | JButton incrementer = new JButton("Increment"); 27 | incrementer.addActionListener(this); 28 | add(incrementer); 29 | } 30 | 31 | public void actionPerformed(ActionEvent e) { 32 | counterValue++; 33 | counterLabel.setText("Count: " + counterValue); 34 | } 35 | 36 | public static void main( String[] args ) { 37 | ActionDemo1 demo = new ActionDemo1(); 38 | demo.setVisible(true); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ch12/examples/ActionDemo2.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | 8 | /** 9 | * A simple, classic demonstration of event handling. Create a frame 10 | * with a button and a label. As the button is pressed, a counter 11 | * shown in the label is incremented. 12 | * 13 | * This second variation uses a separate class to handle the action 14 | * events rather than implementing the ActionListener interface 15 | * directly as in ActionDemo1. 16 | */ 17 | public class ActionDemo2 { 18 | public static void main( String[] args ) { 19 | JFrame frame = new JFrame( "ActionListener Demo" ); 20 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 21 | frame.setLayout(new FlowLayout()); 22 | frame.setSize( 300, 180 ); 23 | 24 | JLabel label = new JLabel("Results go here", JLabel.CENTER ); 25 | ActionCommandHelper helper = new ActionCommandHelper(label); 26 | 27 | JButton simpleButton = new JButton("Button"); 28 | simpleButton.addActionListener(helper); 29 | 30 | JTextField simpleField = new JTextField(10); 31 | simpleField.addActionListener(helper); 32 | 33 | frame.add(simpleButton); 34 | frame.add(simpleField); 35 | frame.add(label); 36 | 37 | frame.setVisible( true ); 38 | } 39 | } 40 | 41 | /** 42 | * Helper class to show the command property of any ActionEvent in a given label. 43 | */ 44 | class ActionCommandHelper implements ActionListener { 45 | JLabel resultLabel; 46 | 47 | public ActionCommandHelper(JLabel label) { 48 | resultLabel = label; 49 | } 50 | 51 | public void actionPerformed(ActionEvent ae) { 52 | resultLabel.setText(ae.getActionCommand()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ch12/examples/BorderLayoutDemo.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | 6 | /** 7 | * A basic demonstration of the BorderLayout with higlighted 8 | * areas in different colors. 9 | */ 10 | public class BorderLayoutDemo { 11 | public static void main( String[] args ) { 12 | JFrame frame = new JFrame("BorderLayout Demo"); 13 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 14 | frame.setSize(400, 200); 15 | 16 | JLabel northLabel = new JLabel("Top - North", JLabel.CENTER); 17 | JLabel southLabel = new JLabel("Bottom - South", JLabel.CENTER); 18 | JLabel eastLabel = new JLabel("Right - East", JLabel.CENTER); 19 | JLabel westLabel = new JLabel("Left - West", JLabel.CENTER); 20 | JLabel centerLabel = new JLabel("Center (everything else)", JLabel.CENTER); 21 | 22 | // Color the labels so we can see their boundaries better 23 | northLabel.setOpaque(true); 24 | northLabel.setBackground(Color.GREEN); 25 | southLabel.setOpaque(true); 26 | southLabel.setBackground(Color.GREEN); 27 | eastLabel.setOpaque(true); 28 | eastLabel.setBackground(Color.RED); 29 | westLabel.setOpaque(true); 30 | westLabel.setBackground(Color.RED); 31 | centerLabel.setOpaque(true); 32 | centerLabel.setBackground(Color.YELLOW); 33 | 34 | frame.add(northLabel, BorderLayout.NORTH); 35 | frame.add(southLabel, BorderLayout.SOUTH); 36 | frame.add(eastLabel, BorderLayout.EAST); 37 | frame.add(westLabel, BorderLayout.WEST); 38 | frame.add(centerLabel, BorderLayout.CENTER); 39 | 40 | frame.setVisible(true); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ch12/examples/Buttons.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | 6 | /** 7 | * A very simple button placed on a frame. This button is 8 | * not connected to any listener so it will "press" when 9 | * clicked but action is taken in response. 10 | */ 11 | public class Buttons { 12 | public static void main( String[] args ) { 13 | JFrame frame = new JFrame( "JButton Examples" ); 14 | frame.setLayout(new FlowLayout()); 15 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 | frame.setSize( 300, 200 ); 17 | 18 | JButton basic = new JButton("Try me!"); 19 | frame.add(basic); 20 | 21 | frame.setVisible( true ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch12/examples/HelloJavaAgain.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import javax.swing.*; 4 | 5 | /** 6 | * A simple label placed on a frame. 7 | */ 8 | public class HelloJavaAgain { 9 | public static void main( String[] args ) { 10 | JFrame frame = new JFrame( "Hello, Java!" ); 11 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 12 | frame.setSize( 300, 150 ); 13 | 14 | JLabel label = new JLabel("Hello, Java!", JLabel.CENTER ); 15 | frame.add(label); 16 | 17 | frame.setVisible( true ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch12/examples/HelloMouse.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | import java.awt.event.MouseEvent; 6 | import java.awt.event.MouseListener; 7 | 8 | /** 9 | * A quick demo of how mouse events work. Clicking around the 10 | * frame will move the label. 11 | * 12 | * Note that "mouse" events are the up, down, and click actions 13 | * of mouse buttons. If you want to catch the mouse moving or dragging, 14 | * those are handled by the MouseMotionListener interface. 15 | */ 16 | public class HelloMouse extends JFrame implements MouseListener { 17 | JLabel label; 18 | 19 | public HelloMouse() { 20 | super("MouseEvent Demo"); 21 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 22 | setLayout(null); 23 | setSize( 300, 100 ); 24 | 25 | label = new JLabel("Hello, Mouse!", JLabel.CENTER ); 26 | label.setOpaque(true); 27 | label.setBackground(Color.YELLOW); 28 | label.setSize(100,20); 29 | label.setLocation(100,100); 30 | add(label); 31 | 32 | getContentPane().addMouseListener(this); 33 | } 34 | 35 | public void mouseClicked(MouseEvent e) { 36 | label.setLocation(e.getX(), e.getY()); 37 | } 38 | 39 | public void mousePressed(MouseEvent e) { } 40 | public void mouseReleased(MouseEvent e) { } 41 | public void mouseEntered(MouseEvent e) { } 42 | public void mouseExited(MouseEvent e) { } 43 | 44 | public static void main( String[] args ) { 45 | HelloMouse frame = new HelloMouse(); 46 | frame.setVisible( true ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ch12/examples/HelloMouseHelper.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import java.awt.*; 4 | import java.awt.event.MouseAdapter; 5 | import java.awt.event.MouseEvent; 6 | import javax.swing.*; 7 | 8 | /** 9 | * A variation on HelloMouse with a separate class implementing 10 | * the mouse event handler. Note that we have to pass a reference 11 | * to the label we wish to affect when creating the event 12 | * helper. 13 | */ 14 | public class HelloMouseHelper { 15 | public static void main( String[] args ) { 16 | JFrame frame = new JFrame( "MouseAdapter Demo" ); 17 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 18 | frame.setLayout(null); 19 | frame.setSize( 300, 200 ); 20 | 21 | JLabel label = new JLabel("Hello, Mouse!", JLabel.CENTER ); 22 | label.setOpaque(true); 23 | label.setBackground(Color.YELLOW); 24 | label.setSize(100,20); 25 | label.setLocation(100,100); 26 | frame.add(label); 27 | 28 | LabelMover mover = new LabelMover(label); 29 | frame.getContentPane().addMouseListener(mover); 30 | frame.setVisible( true ); 31 | } 32 | } 33 | 34 | /** 35 | * Helper class to move a label to the position of a mouse click. 36 | */ 37 | class LabelMover extends MouseAdapter { 38 | JLabel labelToMove; 39 | 40 | public LabelMover(JLabel label) { 41 | labelToMove = label; 42 | } 43 | 44 | public void mouseClicked(MouseEvent e) { 45 | labelToMove.setLocation(e.getX(), e.getY()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ch12/examples/NestedPanelDemo.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | 6 | /** 7 | * An alternate way to arrange complex UIs. Rather than 8 | * use more flexible (but complicated) layout managers, 9 | * you can nest containers each with simpler managers. 10 | */ 11 | public class NestedPanelDemo { 12 | public static void main( String[] args ) { 13 | JFrame frame = new JFrame("Nested Panel Demo"); 14 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 15 | frame.setSize(400, 200); 16 | 17 | // Create the text area and go ahead and add it to the center 18 | JTextArea messageArea = new JTextArea(); 19 | frame.add(messageArea, BorderLayout.CENTER); 20 | 21 | // Create the button container 22 | //JPanel buttonPanel = new JPanel(new FlowLayout()); 23 | JPanel buttonPanel = new JPanel(new GridLayout(1,0)); 24 | 25 | // Create the buttons 26 | JButton sendButton = new JButton("Send"); 27 | JButton saveButton = new JButton("Save"); 28 | JButton resetButton = new JButton("Reset"); 29 | JButton cancelButton = new JButton("Cancel"); 30 | 31 | // Add the buttons to their container 32 | buttonPanel.add(sendButton); 33 | buttonPanel.add(saveButton); 34 | buttonPanel.add(resetButton); 35 | buttonPanel.add(cancelButton); 36 | 37 | // And finally, add the button container to the bottom of the app 38 | frame.add(buttonPanel, BorderLayout.SOUTH); 39 | 40 | frame.setVisible(true); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ch12/examples/PhoneGridDemo.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | 6 | /** 7 | * Demo of the GridLayout manager used to create a 8 | * dial pad like you might find on a phone. 9 | */ 10 | public class PhoneGridDemo { 11 | public static void main( String[] args ) { 12 | JFrame frame = new JFrame("Nested Panel Demo"); 13 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 14 | frame.setSize(200, 300); 15 | 16 | // Create the phone pad container 17 | JPanel phonePad = new JPanel(new GridLayout(4,3)); 18 | 19 | // Create and add the 12 buttons, top-left to bottom-right 20 | phonePad.add(new JButton("1")); 21 | phonePad.add(new JButton("2")); 22 | phonePad.add(new JButton("3")); 23 | 24 | phonePad.add(new JButton("4")); 25 | phonePad.add(new JButton("5")); 26 | phonePad.add(new JButton("6")); 27 | 28 | phonePad.add(new JButton("7")); 29 | phonePad.add(new JButton("8")); 30 | phonePad.add(new JButton("9")); 31 | 32 | phonePad.add(new JButton("*")); 33 | phonePad.add(new JButton("0")); 34 | phonePad.add(new JButton("#")); 35 | 36 | // And finally, add the pad to the center of the app 37 | frame.add(phonePad, BorderLayout.CENTER); 38 | 39 | frame.setVisible(true); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ch12/examples/TextInputs.java: -------------------------------------------------------------------------------- 1 | package ch12.examples; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | 6 | /** 7 | * Some example text inputs including a text area embedded in a 8 | * JScrollPane. 9 | */ 10 | public class TextInputs { 11 | public static void main( String[] args ) { 12 | JFrame frame = new JFrame( "JTextField Examples" ); 13 | frame.setLayout(new FlowLayout()); 14 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 15 | frame.setSize( 400, 300 ); 16 | 17 | JLabel nameLabel = new JLabel("Name:"); 18 | JTextField nameField = new JTextField(10); 19 | JLabel emailLabel = new JLabel("Email:"); 20 | JTextField emailField = new JTextField(24); 21 | 22 | JLabel bodyLabel = new JLabel("Body:"); 23 | JTextArea bodyArea = new JTextArea(10,30); 24 | bodyArea.setLineWrap(true); 25 | bodyArea.setWrapStyleWord(true); 26 | JScrollPane bodyScroller = new JScrollPane(bodyArea); 27 | bodyScroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 28 | bodyScroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 29 | 30 | frame.add(nameLabel); 31 | frame.add(nameField); 32 | frame.add(emailLabel); 33 | frame.add(emailField); 34 | frame.add(bodyLabel); 35 | frame.add(bodyScroller); 36 | 37 | frame.setVisible( true ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ch12/examples/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/ch12/examples/check.png -------------------------------------------------------------------------------- /ch12/examples/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch12.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | public interface GamePiece { 14 | /** 15 | * Sets the position of the piece on the playing field. 16 | * (0,0) is the upper left per standard Java drawing methods. 17 | * 18 | * @param x 19 | * @param y 20 | */ 21 | void setPosition(int x, int y); 22 | 23 | /** 24 | * Gets the current horizontal position of the piece on the field. 25 | * 26 | * @return current X position of the piece 27 | */ 28 | int getPositionX(); 29 | 30 | /** 31 | * Gets the current vertical position of the piece on the field. 32 | * 33 | * @return current Y position of the piece 34 | */ 35 | int getPositionY(); 36 | 37 | /** 38 | * Gets the bounding box of this piece. 39 | * 40 | * @return a Rectangle encompassing the visual elements of the piece 41 | */ 42 | Rectangle getBoundingBox(); 43 | 44 | /** 45 | * Draws the piece inside the given graphics context. 46 | * Do not assume anything about the state of the context. 47 | * 48 | * @param g 49 | */ 50 | void draw(Graphics g); 51 | 52 | /** 53 | * Detect a collision with another piece on the field. 54 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 55 | * 56 | * @param otherPiece 57 | * @return 58 | */ 59 | boolean isTouching(GamePiece otherPiece); 60 | } 61 | -------------------------------------------------------------------------------- /ch12/examples/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch12.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color hedgeColor = Color.GREEN.darker(); 15 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 16 | private int hedgeHeight = (int) (hedgeWidth / 2); 17 | 18 | // Boundary helpers 19 | private Rectangle boundingBox; 20 | 21 | @Override 22 | public void setPosition(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 26 | } 27 | 28 | @Override 29 | public int getPositionX() { 30 | return x; 31 | } 32 | 33 | @Override 34 | public int getPositionY() { 35 | return y; 36 | } 37 | 38 | @Override 39 | public Rectangle getBoundingBox() { 40 | return boundingBox; 41 | } 42 | 43 | @Override 44 | public void draw(Graphics g) { 45 | g.setColor(hedgeColor); 46 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 47 | } 48 | 49 | @Override 50 | public boolean isTouching(GamePiece otherPiece) { 51 | // We don't really have any collisions to detect yet, so just return "no". 52 | // As we fill out all of the game pieces, we'll come back to this method 53 | // and provide a more useful response. 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ch12/examples/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch12.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color leafColor = Color.GREEN.darker(); 15 | private Color trunkColor = new Color(101, 67, 33); 16 | private int trunkWidth = (int) (Field.TREE_WIDTH_IN_PIXELS * 0.2); 17 | private int trunkHeight = (int) (Field.TREE_WIDTH_IN_PIXELS * 1.1); 18 | private int trunkX, trunkY; 19 | 20 | // Boundary helpers 21 | private Rectangle boundingBox; 22 | 23 | @Override 24 | public void setPosition(int x, int y) { 25 | this.x = x; 26 | this.y = y; 27 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 28 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 29 | boundingBox = 30 | new Rectangle( 31 | x, 32 | y, 33 | Field.TREE_WIDTH_IN_PIXELS, 34 | Field.TREE_HEIGHT_IN_PIXELS 35 | ); 36 | } 37 | 38 | @Override 39 | public int getPositionX() { 40 | return x; 41 | } 42 | 43 | @Override 44 | public int getPositionY() { 45 | return y; 46 | } 47 | 48 | @Override 49 | public Rectangle getBoundingBox() { 50 | return boundingBox; 51 | } 52 | 53 | @Override 54 | public void draw(Graphics g) { 55 | g.setColor(trunkColor); 56 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 57 | g.setColor(leafColor); 58 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 59 | } 60 | 61 | @Override 62 | public boolean isTouching(GamePiece otherPiece) { 63 | if (this == otherPiece) { 64 | // By definition we don't collide with ourselves 65 | return false; 66 | } 67 | return GameUtilities.doBoxesIntersect( 68 | boundingBox, 69 | otherPiece.getBoundingBox() 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ch12/exercises/Calculator.java: -------------------------------------------------------------------------------- 1 | package ch12.exercises; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.event.*; 6 | 7 | public class Calculator extends JFrame implements ActionListener { 8 | 9 | public Calculator() { 10 | super("Ex. 12.1"); 11 | setSize(300,450); 12 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 13 | } 14 | 15 | public void actionPerformed(ActionEvent ae) { 16 | System.out.println(ae.getActionCommand()); 17 | } 18 | 19 | public static void main(String args[]) { 20 | Calculator calc = new Calculator(); 21 | SwingUtilities.invokeLater(() -> calc.setVisible(true)); 22 | } 23 | } -------------------------------------------------------------------------------- /ch12/exercises/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch12.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | public interface GamePiece { 14 | /** 15 | * Sets the position of the piece on the playing field. 16 | * (0,0) is the upper left per standard Java drawing methods. 17 | * 18 | * @param x 19 | * @param y 20 | */ 21 | void setPosition(int x, int y); 22 | 23 | /** 24 | * Gets the current horizontal position of the piece on the field. 25 | * 26 | * @return current X position of the piece 27 | */ 28 | int getPositionX(); 29 | 30 | /** 31 | * Gets the current vertical position of the piece on the field. 32 | * 33 | * @return current Y position of the piece 34 | */ 35 | int getPositionY(); 36 | 37 | /** 38 | * Gets the bounding box of this piece. 39 | * 40 | * @return a Rectangle encompassing the visual elements of the piece 41 | */ 42 | Rectangle getBoundingBox(); 43 | 44 | /** 45 | * Draws the piece inside the given graphics context. 46 | * Do not assume anything about the state of the context. 47 | * 48 | * @param g 49 | */ 50 | void draw(Graphics g); 51 | 52 | /** 53 | * Detect a collision with another piece on the field. 54 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 55 | * 56 | * @param otherPiece 57 | * @return 58 | */ 59 | boolean isTouching(GamePiece otherPiece); 60 | } 61 | -------------------------------------------------------------------------------- /ch12/exercises/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch12.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color hedgeColor = Color.GREEN.darker(); 15 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 16 | private int hedgeHeight = (int) (hedgeWidth / 2); 17 | 18 | // Boundary helpers 19 | private Rectangle boundingBox; 20 | 21 | @Override 22 | public void setPosition(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 26 | } 27 | 28 | @Override 29 | public int getPositionX() { 30 | return x; 31 | } 32 | 33 | @Override 34 | public int getPositionY() { 35 | return y; 36 | } 37 | 38 | @Override 39 | public Rectangle getBoundingBox() { 40 | return boundingBox; 41 | } 42 | 43 | @Override 44 | public void draw(Graphics g) { 45 | g.setColor(hedgeColor); 46 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 47 | } 48 | 49 | @Override 50 | public boolean isTouching(GamePiece otherPiece) { 51 | // We don't really have any collisions to detect yet, so just return "no". 52 | // As we fill out all of the game pieces, we'll come back to this method 53 | // and provide a more useful response. 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ch12/exercises/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch12.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color leafColor = Color.GREEN.darker(); 15 | private Color trunkColor = new Color(101, 67, 33); 16 | private int trunkWidth = (int) (Field.TREE_WIDTH_IN_PIXELS * 0.2); 17 | private int trunkHeight = (int) (Field.TREE_WIDTH_IN_PIXELS * 1.1); 18 | private int trunkX, trunkY; 19 | 20 | // Boundary helpers 21 | private Rectangle boundingBox; 22 | 23 | @Override 24 | public void setPosition(int x, int y) { 25 | this.x = x; 26 | this.y = y; 27 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 28 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 29 | boundingBox = 30 | new Rectangle( 31 | x, 32 | y, 33 | Field.TREE_WIDTH_IN_PIXELS, 34 | Field.TREE_HEIGHT_IN_PIXELS 35 | ); 36 | } 37 | 38 | @Override 39 | public int getPositionX() { 40 | return x; 41 | } 42 | 43 | @Override 44 | public int getPositionY() { 45 | return y; 46 | } 47 | 48 | @Override 49 | public Rectangle getBoundingBox() { 50 | return boundingBox; 51 | } 52 | 53 | @Override 54 | public void draw(Graphics g) { 55 | g.setColor(trunkColor); 56 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 57 | g.setColor(leafColor); 58 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 59 | } 60 | 61 | @Override 62 | public boolean isTouching(GamePiece otherPiece) { 63 | if (this == otherPiece) { 64 | // By definition we don't collide with ourselves 65 | return false; 66 | } 67 | return GameUtilities.doBoxesIntersect( 68 | boundingBox, 69 | otherPiece.getBoundingBox() 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ch12/solutions/Calculator.java: -------------------------------------------------------------------------------- 1 | package ch12.solutions; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.event.*; 6 | 7 | public class Calculator extends JFrame implements ActionListener { 8 | JLabel display; 9 | String buttonLabels = "789/456*123-.0=+"; 10 | Font displayFont = new Font(Font.MONOSPACED, Font.BOLD, 36); 11 | Font buttonFont = new Font(Font.MONOSPACED, Font.BOLD, 20); 12 | 13 | public Calculator() { 14 | super("Ex. 12.1"); 15 | setSize(300,450); 16 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 17 | 18 | JPanel content = (JPanel)getContentPane(); 19 | 20 | // Set up our display label with a nice, readable font 21 | display = new JLabel("0", SwingConstants.RIGHT); 22 | display.setFont(displayFont); 23 | display.setBorder(BorderFactory.createEmptyBorder(8,8,8,8)); 24 | content.add(display, BorderLayout.NORTH); 25 | 26 | // Set up our buttons 27 | JPanel buttonPane = new JPanel(new GridLayout(4,4)); 28 | for (String label : buttonLabels.split("")) { 29 | JButton b = new JButton(label); 30 | b.setFont(buttonFont); 31 | b.addActionListener(this); 32 | buttonPane.add(b); 33 | } 34 | content.add(buttonPane, BorderLayout.CENTER); 35 | } 36 | 37 | public void actionPerformed(ActionEvent ae) { 38 | System.out.println(ae.getActionCommand()); 39 | } 40 | 41 | public static void main(String args[]) { 42 | Calculator calc = new Calculator(); 43 | SwingUtilities.invokeLater(() -> calc.setVisible(true)); 44 | } 45 | } -------------------------------------------------------------------------------- /ch12/solutions/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch12.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | public interface GamePiece { 14 | /** 15 | * Sets the position of the piece on the playing field. 16 | * (0,0) is the upper left per standard Java drawing methods. 17 | * 18 | * @param x 19 | * @param y 20 | */ 21 | void setPosition(int x, int y); 22 | 23 | /** 24 | * Gets the current horizontal position of the piece on the field. 25 | * 26 | * @return current X position of the piece 27 | */ 28 | int getPositionX(); 29 | 30 | /** 31 | * Gets the current vertical position of the piece on the field. 32 | * 33 | * @return current Y position of the piece 34 | */ 35 | int getPositionY(); 36 | 37 | /** 38 | * Gets the bounding box of this piece. 39 | * 40 | * @return a Rectangle encompassing the visual elements of the piece 41 | */ 42 | Rectangle getBoundingBox(); 43 | 44 | /** 45 | * Draws the piece inside the given graphics context. 46 | * Do not assume anything about the state of the context. 47 | * 48 | * @param g 49 | */ 50 | void draw(Graphics g); 51 | 52 | /** 53 | * Detect a collision with another piece on the field. 54 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 55 | * 56 | * @param otherPiece 57 | * @return 58 | */ 59 | boolean isTouching(GamePiece otherPiece); 60 | } 61 | -------------------------------------------------------------------------------- /ch12/solutions/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch12.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color hedgeColor = Color.GREEN.darker(); 15 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 16 | private int hedgeHeight = (int) (hedgeWidth / 2); 17 | 18 | // Boundary helpers 19 | private Rectangle boundingBox; 20 | 21 | @Override 22 | public void setPosition(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 26 | } 27 | 28 | @Override 29 | public int getPositionX() { 30 | return x; 31 | } 32 | 33 | @Override 34 | public int getPositionY() { 35 | return y; 36 | } 37 | 38 | @Override 39 | public Rectangle getBoundingBox() { 40 | return boundingBox; 41 | } 42 | 43 | @Override 44 | public void draw(Graphics g) { 45 | g.setColor(hedgeColor); 46 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 47 | } 48 | 49 | @Override 50 | public boolean isTouching(GamePiece otherPiece) { 51 | // We don't really have any collisions to detect yet, so just return "no". 52 | // As we fill out all of the game pieces, we'll come back to this method 53 | // and provide a more useful response. 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ch12/solutions/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch12.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * An obstacle for our game. Trees includ a simple circle and rectangle shape. 7 | * They are built using sizes determined by the constants in the Field class. 8 | */ 9 | public class Tree implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color leafColor = Color.GREEN.darker(); 15 | private Color trunkColor = new Color(101, 67, 33); 16 | private int trunkWidth = (int) (Field.TREE_WIDTH_IN_PIXELS * 0.2); 17 | private int trunkHeight = (int) (Field.TREE_WIDTH_IN_PIXELS * 1.1); 18 | private int trunkX, trunkY; 19 | 20 | // Boundary helpers 21 | private Rectangle boundingBox; 22 | 23 | @Override 24 | public void setPosition(int x, int y) { 25 | this.x = x; 26 | this.y = y; 27 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 28 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 29 | boundingBox = 30 | new Rectangle( 31 | x, 32 | y, 33 | Field.TREE_WIDTH_IN_PIXELS, 34 | Field.TREE_HEIGHT_IN_PIXELS 35 | ); 36 | } 37 | 38 | @Override 39 | public int getPositionX() { 40 | return x; 41 | } 42 | 43 | @Override 44 | public int getPositionY() { 45 | return y; 46 | } 47 | 48 | @Override 49 | public Rectangle getBoundingBox() { 50 | return boundingBox; 51 | } 52 | 53 | @Override 54 | public void draw(Graphics g) { 55 | g.setColor(trunkColor); 56 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 57 | g.setColor(leafColor); 58 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 59 | } 60 | 61 | @Override 62 | public boolean isTouching(GamePiece otherPiece) { 63 | if (this == otherPiece) { 64 | // By definition we don't collide with ourselves 65 | return false; 66 | } 67 | return GameUtilities.doBoxesIntersect( 68 | boundingBox, 69 | otherPiece.getBoundingBox() 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ch13/examples/DateAtHost.java: -------------------------------------------------------------------------------- 1 | package ch13.examples; 2 | 3 | import java.net.Socket; 4 | import java.io.*; 5 | 6 | public class DateAtHost extends java.util.Date { 7 | static int timePort = 37; 8 | // seconds from start of 20th century to Jan 1, 1970 00:00 GMT 9 | static final long offset = 2208988800L; 10 | 11 | public DateAtHost( String host ) throws IOException { 12 | this( host, timePort ); 13 | } 14 | 15 | public DateAtHost( String host, int port ) throws IOException { 16 | Socket server = new Socket( host, port ); 17 | DataInputStream din = 18 | new DataInputStream( server.getInputStream( ) ); 19 | int time = din.readInt( ); 20 | server.close( ); 21 | 22 | setTime( (((1L << 32) + time) - offset) * 1000 ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch13/examples/IconLabel.java: -------------------------------------------------------------------------------- 1 | package ch13.examples; 2 | 3 | import javax.swing.*; 4 | import java.net.*; 5 | 6 | public class IconLabel extends JFrame { 7 | public IconLabel() { 8 | super("Web Icon Demo"); 9 | setSize(400,220); 10 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 11 | 12 | try { 13 | URL favUrl = new URL("https://www.oracle.com/asset/web/favicons/favicon-192.png"); 14 | ImageIcon image1 = new ImageIcon(favUrl); 15 | JLabel iconLabel = new JLabel(image1); 16 | add(iconLabel); 17 | } catch (MalformedURLException mfe) { 18 | add(new JLabel("Error: " + mfe)); 19 | } 20 | } 21 | 22 | public static void main(String args[]) { 23 | IconLabel demo = new IconLabel(); 24 | SwingUtilities.invokeLater(() -> demo.setVisible(true)); 25 | } 26 | } -------------------------------------------------------------------------------- /ch13/examples/ReadUrl.java: -------------------------------------------------------------------------------- 1 | package ch13.examples; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | 6 | /** 7 | * A simple command line demonstration of reading from a URL. 8 | * The URL to read must be passed as the only argument on the command line. 9 | */ 10 | public class ReadUrl { 11 | public static void main(String args[]) { 12 | // Did we get an argument to use as the URL? 13 | if (args.length != 1) { 14 | System.err.println("Must specify URL on command line. Exiting."); 15 | System.exit(1); 16 | } 17 | // Great! Let's try to read it and dump the contents to the terminal. 18 | try { 19 | URL url = new URL(args[0]); 20 | 21 | BufferedReader bin = new BufferedReader ( 22 | new InputStreamReader( url.openStream() )); 23 | String line; 24 | while ( (line = bin.readLine()) != null ) { 25 | System.out.println( line ); 26 | } 27 | bin.close(); 28 | } catch (Exception e) { 29 | System.err.println("Error occurred while reading:" + e); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch13/examples/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch13.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch13/examples/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch13.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color hedgeColor = Color.GREEN.darker(); 15 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 16 | private int hedgeHeight = (int) (hedgeWidth / 2); 17 | 18 | // Boundary helpers 19 | private Rectangle boundingBox; 20 | 21 | @Override 22 | public void setPosition(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 26 | } 27 | 28 | @Override 29 | public int getPositionX() { 30 | return x; 31 | } 32 | 33 | @Override 34 | public int getPositionY() { 35 | return y; 36 | } 37 | 38 | @Override 39 | public Rectangle getBoundingBox() { 40 | return boundingBox; 41 | } 42 | 43 | @Override 44 | public void draw(Graphics g) { 45 | g.setColor(hedgeColor); 46 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 47 | } 48 | 49 | @Override 50 | public boolean isTouching(GamePiece otherPiece) { 51 | if (this == otherPiece) { 52 | // By definition we don't collide with ourselves 53 | return false; 54 | } 55 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ch13/examples/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch13.examples.game; 2 | 3 | import java.awt.*; 4 | 5 | public class Tree implements GamePiece { 6 | int x, y; 7 | 8 | // Drawing helpers 9 | private Color leafColor = Color.GREEN.darker(); 10 | private Color trunkColor = new Color(101, 67, 33); 11 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 12 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 13 | private int trunkX, trunkY; 14 | 15 | // Boundary helpers 16 | private Rectangle boundingBox; 17 | 18 | @Override 19 | public void setPosition(int x, int y) { 20 | this.x = x; 21 | this.y = y; 22 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 23 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 24 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(trunkColor); 45 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 46 | g.setColor(leafColor); 47 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 48 | } 49 | 50 | @Override 51 | public boolean isTouching(GamePiece otherPiece) { 52 | if (this == otherPiece) { 53 | // By definition we don't collide with ourselves 54 | return false; 55 | } 56 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ch13/exercises/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch13.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch13/exercises/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch13.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color hedgeColor = Color.GREEN.darker(); 15 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 16 | private int hedgeHeight = (int) (hedgeWidth / 2); 17 | 18 | // Boundary helpers 19 | private Rectangle boundingBox; 20 | 21 | @Override 22 | public void setPosition(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 26 | } 27 | 28 | @Override 29 | public int getPositionX() { 30 | return x; 31 | } 32 | 33 | @Override 34 | public int getPositionY() { 35 | return y; 36 | } 37 | 38 | @Override 39 | public Rectangle getBoundingBox() { 40 | return boundingBox; 41 | } 42 | 43 | @Override 44 | public void draw(Graphics g) { 45 | g.setColor(hedgeColor); 46 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 47 | } 48 | 49 | @Override 50 | public boolean isTouching(GamePiece otherPiece) { 51 | if (this == otherPiece) { 52 | // By definition we don't collide with ourselves 53 | return false; 54 | } 55 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ch13/exercises/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch13.exercises.game; 2 | 3 | import java.awt.*; 4 | 5 | public class Tree implements GamePiece { 6 | int x, y; 7 | 8 | // Drawing helpers 9 | private Color leafColor = Color.GREEN.darker(); 10 | private Color trunkColor = new Color(101, 67, 33); 11 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 12 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 13 | private int trunkX, trunkY; 14 | 15 | // Boundary helpers 16 | private Rectangle boundingBox; 17 | 18 | @Override 19 | public void setPosition(int x, int y) { 20 | this.x = x; 21 | this.y = y; 22 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 23 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 24 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(trunkColor); 45 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 46 | g.setColor(leafColor); 47 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 48 | } 49 | 50 | @Override 51 | public boolean isTouching(GamePiece otherPiece) { 52 | if (this == otherPiece) { 53 | // By definition we don't collide with ourselves 54 | return false; 55 | } 56 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ch13/solutions/FDClient.java: -------------------------------------------------------------------------------- 1 | package ch13.solutions; 2 | 3 | import java.net.Socket; 4 | import java.io.*; 5 | 6 | public class FDClient { 7 | static int fdPort = 3283; // D-A-T-E on a phonepad :) 8 | 9 | public static void printDateAndTime(String host) { 10 | try (Socket fdSocket = new Socket(host, fdPort)) { 11 | InputStreamReader isr = 12 | new InputStreamReader(fdSocket.getInputStream()); 13 | BufferedReader br = new BufferedReader(isr); 14 | String dt = br.readLine(); 15 | System.out.println(host + ": " + dt); 16 | br.close(); 17 | } catch(IOException ioe) { 18 | System.err.println("Failed to retrieve date and time: " + ioe); 19 | } 20 | } 21 | 22 | public static void main(String args[]) { 23 | if (args.length != 1) { 24 | System.err.println("Please provide a host to contact."); 25 | System.exit(1); 26 | } 27 | printDateAndTime(args[0]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ch13/solutions/FDServer.java: -------------------------------------------------------------------------------- 1 | package ch13.solutions; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.time.LocalDateTime; 6 | import java.time.format.DateTimeFormatter; 7 | 8 | public class FDServer { 9 | static int fdPort = 3283; // D-A-T-E on a phonepad :) 10 | static DateTimeFormatter shortish = DateTimeFormatter.ofPattern("MM/dd/yy hh:mm a"); 11 | public static void serveDateAndTime() { 12 | for (;;) { // this is sometimes called the "forever" loop 13 | System.out.println("Waiting ..."); 14 | try (ServerSocket listener = new ServerSocket(fdPort)) { 15 | Socket fdClient = listener.accept(); 16 | System.out.println("Incoming request from " + fdClient.getInetAddress()); 17 | OutputStreamWriter osw = new OutputStreamWriter(fdClient.getOutputStream()); 18 | PrintWriter pw = new PrintWriter(osw); 19 | pw.println(shortish.format(LocalDateTime.now())); 20 | pw.close(); 21 | } catch(Exception e) { 22 | // We're being a bit lazy here, but this server is so 23 | // simple, there's not much else to do. 24 | System.err.println("Oh no! Server error: " + e); 25 | } 26 | } 27 | } 28 | 29 | public static void main(String args[]) { 30 | serveDateAndTime(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch13/solutions/FDServer2.java.preview: -------------------------------------------------------------------------------- 1 | package ch13.solutions; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.time.LocalDateTime; 6 | import java.time.format.DateTimeFormatter; 7 | 8 | public class FDServer2 { 9 | static int fdPort = 3283; // D-A-T-E on a phonepad :) 10 | static DateTimeFormatter shortish = DateTimeFormatter.ofPattern("MM/dd/yy hh:mm a"); 11 | public static void serveDateAndTime() { 12 | for (;;) { // this is sometimes called a "forever" loop 13 | System.out.println("Waiting ..."); 14 | try (ServerSocket listener = new ServerSocket(fdPort)) { 15 | Socket fdClient = listener.accept(); 16 | System.out.println("Incoming request from " + fdClient.getInetAddress()); 17 | Thread.startVirtualThread(() -> { 18 | try { 19 | OutputStreamWriter osw = new OutputStreamWriter(fdClient.getOutputStream()); 20 | PrintWriter pw = new PrintWriter(osw); 21 | pw.println(shortish.format(LocalDateTime.now())); 22 | pw.close(); 23 | fdClient.close(); 24 | } catch(Exception e) { 25 | System.err.println("Problem handling client: " + e); 26 | } 27 | }); 28 | } catch(Exception e) { 29 | // We're being a bit lazy here, but this server is so 30 | // simple, there's not much else to do. 31 | System.err.println("Oh no! Server error: " + e); 32 | } 33 | } 34 | } 35 | 36 | public static void main(String args[]) { 37 | serveDateAndTime(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ch13/solutions/game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package ch13.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /ch13/solutions/game/Hedge.java: -------------------------------------------------------------------------------- 1 | package ch13.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color hedgeColor = Color.GREEN.darker(); 15 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 16 | private int hedgeHeight = (int) (hedgeWidth / 2); 17 | 18 | // Boundary helpers 19 | private Rectangle boundingBox; 20 | 21 | @Override 22 | public void setPosition(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 26 | } 27 | 28 | @Override 29 | public int getPositionX() { 30 | return x; 31 | } 32 | 33 | @Override 34 | public int getPositionY() { 35 | return y; 36 | } 37 | 38 | @Override 39 | public Rectangle getBoundingBox() { 40 | return boundingBox; 41 | } 42 | 43 | @Override 44 | public void draw(Graphics g) { 45 | g.setColor(hedgeColor); 46 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 47 | } 48 | 49 | @Override 50 | public boolean isTouching(GamePiece otherPiece) { 51 | if (this == otherPiece) { 52 | // By definition we don't collide with ourselves 53 | return false; 54 | } 55 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ch13/solutions/game/Tree.java: -------------------------------------------------------------------------------- 1 | package ch13.solutions.game; 2 | 3 | import java.awt.*; 4 | 5 | public class Tree implements GamePiece { 6 | int x, y; 7 | 8 | // Drawing helpers 9 | private Color leafColor = Color.GREEN.darker(); 10 | private Color trunkColor = new Color(101, 67, 33); 11 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 12 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 13 | private int trunkX, trunkY; 14 | 15 | // Boundary helpers 16 | private Rectangle boundingBox; 17 | 18 | @Override 19 | public void setPosition(int x, int y) { 20 | this.x = x; 21 | this.y = y; 22 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 23 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 24 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(trunkColor); 45 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 46 | g.setColor(leafColor); 47 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 48 | } 49 | 50 | @Override 51 | public boolean isTouching(GamePiece otherPiece) { 52 | if (this == otherPiece) { 53 | // By definition we don't collide with ourselves 54 | return false; 55 | } 56 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /game/GamePiece.java: -------------------------------------------------------------------------------- 1 | package game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Interface to hold common elements for our apples, trees, and physicists 7 | * From the README: 8 | * GamePiece 9 | * - methods for positioning on a PlayingField 10 | * - methods for Drawing 11 | * - methods for detecting a collision with other GamePieces 12 | */ 13 | 14 | public interface GamePiece { 15 | /** 16 | * Sets the position of the piece on the playing field. 17 | * (0,0) is the upper left per standard Java drawing methods. 18 | * 19 | * @param x 20 | * @param y 21 | */ 22 | void setPosition(int x, int y); 23 | 24 | /** 25 | * Gets the current horizontal position of the piece on the field. 26 | * 27 | * @return current X position of the piece 28 | */ 29 | int getPositionX(); 30 | 31 | /** 32 | * Gets the current vertical position of the piece on the field. 33 | * 34 | * @return current Y position of the piece 35 | */ 36 | int getPositionY(); 37 | 38 | /** 39 | * Gets the bounding box of this piece. 40 | * 41 | * @return a Rectangle encompassing the visual elements of the piece 42 | */ 43 | Rectangle getBoundingBox(); 44 | 45 | /** 46 | * Draws the piece inside the given graphics context. 47 | * Do not assume anything about the state of the context. 48 | * 49 | * @param g 50 | */ 51 | void draw(Graphics g); 52 | 53 | /** 54 | * Detect a collision with another piece on the field. 55 | * By definition, a piece does NOT touch itself (i.e. it won't collide with itself). 56 | * 57 | * @param otherPiece 58 | * @return 59 | */ 60 | boolean isTouching(GamePiece otherPiece); 61 | } 62 | -------------------------------------------------------------------------------- /game/Hedge.java: -------------------------------------------------------------------------------- 1 | package game; 2 | 3 | import java.awt.*; 4 | 5 | /** 6 | * Another obstacle for our game. Hedges are simple boxes. 7 | * We'll reuse the tree size constants for our hedges. 8 | */ 9 | public class Hedge implements GamePiece { 10 | 11 | int x, y; 12 | 13 | // Drawing helpers 14 | private Color hedgeColor = Color.GREEN.darker(); 15 | private int hedgeWidth = Field.TREE_WIDTH_IN_PIXELS; 16 | private int hedgeHeight = (int) (hedgeWidth / 2); 17 | 18 | // Boundary helpers 19 | private Rectangle boundingBox; 20 | 21 | @Override 22 | public void setPosition(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | boundingBox = new Rectangle(x, y, hedgeWidth, hedgeHeight); 26 | } 27 | 28 | @Override 29 | public int getPositionX() { 30 | return x; 31 | } 32 | 33 | @Override 34 | public int getPositionY() { 35 | return y; 36 | } 37 | 38 | @Override 39 | public Rectangle getBoundingBox() { 40 | return boundingBox; 41 | } 42 | 43 | @Override 44 | public void draw(Graphics g) { 45 | g.setColor(hedgeColor); 46 | g.fillRect(x, y, hedgeWidth, hedgeHeight); 47 | } 48 | 49 | @Override 50 | public boolean isTouching(GamePiece otherPiece) { 51 | if (this == otherPiece) { 52 | // By definition we don't collide with ourselves 53 | return false; 54 | } 55 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /game/Tree.java: -------------------------------------------------------------------------------- 1 | package game; 2 | 3 | import java.awt.*; 4 | 5 | public class Tree implements GamePiece { 6 | int x, y; 7 | 8 | // Drawing helpers 9 | private Color leafColor = Color.GREEN.darker(); 10 | private Color trunkColor = new Color(101, 67, 33); 11 | private int trunkWidth = (int)(Field.TREE_WIDTH_IN_PIXELS * 0.2); 12 | private int trunkHeight = (int)(Field.TREE_WIDTH_IN_PIXELS * 1.1); 13 | private int trunkX, trunkY; 14 | 15 | // Boundary helpers 16 | private Rectangle boundingBox; 17 | 18 | @Override 19 | public void setPosition(int x, int y) { 20 | this.x = x; 21 | this.y = y; 22 | trunkX = x + (Field.TREE_WIDTH_IN_PIXELS - trunkWidth) / 2; 23 | trunkY = y + 2 * Field.TREE_WIDTH_IN_PIXELS - trunkHeight; 24 | boundingBox = new Rectangle(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_HEIGHT_IN_PIXELS); 25 | } 26 | 27 | @Override 28 | public int getPositionX() { 29 | return x; 30 | } 31 | 32 | @Override 33 | public int getPositionY() { 34 | return y; 35 | } 36 | 37 | @Override 38 | public Rectangle getBoundingBox() { 39 | return boundingBox; 40 | } 41 | 42 | @Override 43 | public void draw(Graphics g) { 44 | g.setColor(trunkColor); 45 | g.fillRect(trunkX, trunkY, trunkWidth, trunkHeight); 46 | g.setColor(leafColor); 47 | g.fillOval(x, y, Field.TREE_WIDTH_IN_PIXELS, Field.TREE_WIDTH_IN_PIXELS); 48 | } 49 | 50 | @Override 51 | public boolean isTouching(GamePiece otherPiece) { 52 | if (this == otherPiece) { 53 | // By definition we don't collide with ourselves 54 | return false; 55 | } 56 | return GameUtilities.doBoxesIntersect(boundingBox, otherPiece.getBoundingBox()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /quiz/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | -------------------------------------------------------------------------------- /quiz/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm lj6review.jar 4 | cd src 5 | javac com/loyinc/*/*.java 6 | if [ $? -eq 0 ] 7 | then 8 | jar cvmf ../manifest.mf ../lj6review.jar res com/loyinc/*/*.class 9 | else 10 | echo "Compilation failed. Packaging skipped." 11 | fi 12 | -------------------------------------------------------------------------------- /quiz/lj6review.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/lj6review.jar -------------------------------------------------------------------------------- /quiz/manifest.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: com.loyinc.quiz.Review 3 | 4 | -------------------------------------------------------------------------------- /quiz/quizgen.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # 4 | # Usage is: $0 chapnum qcount 5 | # 6 | if ($#ARGV != 1) { 7 | die "Usage is: $0 chNum quCount\n"; 8 | } 9 | 10 | $chNum = $ARGV[0]; 11 | $quCount = $ARGV[1]; 12 | 13 | print "###\n# Chapter $chNum\n###\n"; 14 | 15 | printf "%X0-ti Chapter %d Title\n", $chNum, $chNum; 16 | printf "%X0-in Chapter %d Intro\n\n", $chNum, $chNum; 17 | 18 | for ($q = 1; $q <= $quCount; $q++) { 19 | printf "%X%X-tx Question %d text\n", $chNum, $q, $q; 20 | printf "%X%X-se (Select one)\n", $chNum, $q; 21 | for ($a = 65; $a <= 68; $a++) { 22 | printf "%X%X%ctw Answer %c\n", $chNum, $q, $a, $a; 23 | printf "%X%X%cex Explanation %c\n", $chNum, $q, $a, $a; 24 | } 25 | printf "\n"; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /quiz/src/com/loyinc/quiz/Answer.java: -------------------------------------------------------------------------------- 1 | package com.loyinc.quiz; 2 | 3 | public class Answer { 4 | String answer; 5 | String explanation; 6 | boolean correct; 7 | boolean selected; 8 | 9 | public Answer(String answer) { 10 | this(answer, "", false); 11 | } 12 | 13 | public Answer(String answer, boolean correct) { 14 | this(answer, "", correct); 15 | } 16 | 17 | public Answer(String answer, String explanation, boolean correct) { 18 | this.answer = answer; 19 | this.explanation = explanation; 20 | this.correct = correct; 21 | this.selected = false; 22 | } 23 | 24 | public boolean matches() { 25 | return correct == selected; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /quiz/src/com/loyinc/quiz/Review.java: -------------------------------------------------------------------------------- 1 | package com.loyinc.quiz; 2 | 3 | import java.util.*; 4 | 5 | import javax.swing.SwingUtilities; 6 | 7 | public class Review { 8 | QuizFrame quiz; 9 | List chapterList = new ArrayList<>(); 10 | 11 | // Hard-coded options for now. Could certainly move these to command-line 12 | // arguments if more quizzes get built. 13 | // Production, use the bundled quiz content 14 | String buildMode = Quizzes.JAR; 15 | String quizFile = "res/quiz-data.txt"; 16 | 17 | // Late-stage development, use a file from the local filesystem 18 | //String buildMode = Quizzes.FILE; 19 | //String quizFile = "/Users/marc/work/books/examples/learnjava6e/quiz/rez/quiz-data.txt"; 20 | 21 | // Early development, use mock data 22 | //String buildMode = Quizzes.MOCKUP; 23 | //String quizFile = null; 24 | 25 | public Review() { 26 | // Follow global switch to pick either mockup data or the real thing 27 | chapterList = Quizzes.buildList(buildMode, quizFile); 28 | if (chapterList == null || chapterList.size() == 0) { 29 | // No errors, but no chapters either; must be in test mode 30 | quiz = new QuizFrame(null); 31 | } else { 32 | quiz = new QuizFrame(chapterList); 33 | } 34 | } 35 | 36 | public boolean loadChapters(String quizFile) { 37 | // Return true on successful load 38 | 39 | return chapterList != null; 40 | } 41 | 42 | public void start() { 43 | if (quiz != null) { 44 | quiz.setVisible(true); 45 | } else { 46 | System.err.println("Review quizzes are not yet initialized."); 47 | } 48 | } 49 | 50 | public static void main(String[] args) { 51 | System.setProperty("awt.useSystemAAFontSettings","on"); 52 | System.setProperty("swing.aatext", "true"); 53 | Review r = new Review(); 54 | SwingUtilities.invokeLater(() -> r.start()); 55 | } 56 | } -------------------------------------------------------------------------------- /quiz/src/com/loyinc/util/CWButton.java: -------------------------------------------------------------------------------- 1 | package com.loyinc.util; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | 6 | /** 7 | * A constant-width label for use in layout managers that query 8 | * their components to determine sizes. 9 | */ 10 | public class CWButton extends JButton { 11 | protected int width; 12 | 13 | public CWButton(int width) { 14 | this(width, null, null); 15 | } 16 | 17 | public CWButton(int width, String text) { 18 | this(width, text, null); 19 | } 20 | 21 | public CWButton(int width, Icon icon) { 22 | this(width, null, icon); 23 | } 24 | 25 | public CWButton(int width, String text, Icon icon) { 26 | super(text, icon); 27 | this.width = width; 28 | tailor(); 29 | } 30 | 31 | public CWButton(int width, Action action) { 32 | super(action); 33 | this.width = width; 34 | tailor(); 35 | } 36 | 37 | /** 38 | * Use this method to apply any app-wide adjustments to instances 39 | * of this constant-width button, regardless of how it was constructed. 40 | */ 41 | protected void tailor() { 42 | Config.applyPrefs(this); 43 | } 44 | 45 | public Dimension getPreferredSize() { 46 | return new Dimension(width, this.getHeight()); 47 | } 48 | public Dimension getMinimumSize() { return getPreferredSize(); } 49 | public Dimension getMaximumSize() { return getPreferredSize(); } 50 | } 51 | -------------------------------------------------------------------------------- /quiz/src/com/loyinc/util/CWLabel.java: -------------------------------------------------------------------------------- 1 | package com.loyinc.util; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | 6 | /** 7 | * A constant-width label for use in layout managers that query 8 | * their components to determine sizes. 9 | */ 10 | public class CWLabel extends JLabel { 11 | protected int width; 12 | 13 | public CWLabel(int width) { 14 | this(width, null, null, SwingConstants.LEADING); 15 | } 16 | 17 | public CWLabel(int width, String text) { 18 | this(width, text, null, SwingConstants.LEADING); 19 | } 20 | 21 | public CWLabel(int width, String text, int horizontalAlignment) { 22 | this(width, text, null, horizontalAlignment); 23 | } 24 | 25 | public CWLabel(int width, Icon icon) { 26 | this(width, null, icon, SwingConstants.CENTER); 27 | } 28 | 29 | public CWLabel(int width, Icon icon, int horizontalAlignment) { 30 | this(width, null, icon, horizontalAlignment); 31 | } 32 | 33 | public CWLabel(int width, String text, Icon icon, int horizontalAlignment) { 34 | super(text, icon, horizontalAlignment); 35 | this.width = width; 36 | Config.applyPrefs(this); 37 | } 38 | 39 | public Dimension getPreferredSize() { 40 | return new Dimension(width, this.getHeight()); 41 | } 42 | public Dimension getMinimumSize() { return getPreferredSize(); } 43 | public Dimension getMaximumSize() { return getPreferredSize(); } 44 | } 45 | -------------------------------------------------------------------------------- /quiz/src/com/loyinc/util/Config.java: -------------------------------------------------------------------------------- 1 | package com.loyinc.util; 2 | 3 | import com.loyinc.quiz.Review; 4 | 5 | import javax.swing.*; 6 | import java.awt.*; 7 | import java.util.prefs.Preferences; 8 | 9 | public class Config { 10 | // Internal Preference node and key names 11 | static final String PREFS_NODE = "/com/loyinc/util/Review"; 12 | static final String FONT_SIZE_ADJ_KEY = "font.size.adjustment"; 13 | 14 | static final String osName = System.getProperty("os.name"); 15 | 16 | // Public defaults for some common preferences 17 | public static final float DEFAUlT_ADJUSTMENT = 2.0f; 18 | 19 | public static void applyPrefs(JComponent uiComp) { 20 | Preferences prefs = Preferences.userRoot().node(PREFS_NODE); 21 | float adjustment = prefs.getFloat(FONT_SIZE_ADJ_KEY, DEFAUlT_ADJUSTMENT); 22 | Font f = uiComp.getFont(); 23 | uiComp.setFont(f.deriveFont(f.getSize() + adjustment)); 24 | } 25 | 26 | /** 27 | * Helper to get the font size adjustment value for use in manually 28 | * configuring a component. 29 | */ 30 | public float getFontSizeAdjustment() { 31 | Preferences prefs = Preferences.userRoot().node(PREFS_NODE); 32 | return prefs.getFloat(FONT_SIZE_ADJ_KEY, DEFAUlT_ADJUSTMENT); 33 | } 34 | 35 | public static boolean isMacOS() { 36 | return osName.startsWith("Mac"); 37 | } 38 | 39 | public static boolean isLinux() { 40 | return osName.equalsIgnoreCase("linux"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /quiz/src/com/loyinc/util/StateProvider.java: -------------------------------------------------------------------------------- 1 | package com.loyinc.util; 2 | 3 | public interface StateProvider { 4 | public int getState(); 5 | public String getStateText(); 6 | public String getStateIconName(boolean expanded); 7 | } 8 | -------------------------------------------------------------------------------- /quiz/src/res/ch_done_ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/ch_done_ok.png -------------------------------------------------------------------------------- /quiz/src/res/ch_filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/ch_filled.png -------------------------------------------------------------------------------- /quiz/src/res/ch_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/ch_list.png -------------------------------------------------------------------------------- /quiz/src/res/ch_list_inv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/ch_list_inv.png -------------------------------------------------------------------------------- /quiz/src/res/ch_not_ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/ch_not_ok.png -------------------------------------------------------------------------------- /quiz/src/res/ch_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/ch_open.png -------------------------------------------------------------------------------- /quiz/src/res/correct01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/correct01.png -------------------------------------------------------------------------------- /quiz/src/res/cover-480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/cover-480.png -------------------------------------------------------------------------------- /quiz/src/res/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/cover.png -------------------------------------------------------------------------------- /quiz/src/res/notquite01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/notquite01.png -------------------------------------------------------------------------------- /quiz/src/res/unknown01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l0y/learnjava6e/0493242cdd822c00470a5ff14dbcb45aea0b2a41/quiz/src/res/unknown01.png --------------------------------------------------------------------------------