Download presentation
Presentation is loading. Please wait.
1
An Example of Interacting Classes
Lunar Lander An Example of Interacting Classes 19-Feb-19
2
LunarLanderGame This class contains the public static void main(String[] args) method. In this method, you should (1) create a LunarLander object, (2) create an IOFrame object, and (3) send messages to these two objects in order to get the burn rate from the user, tell the lander what to do, find out the lander status, and report the status back to the user. When the lander's altitude is less than or equal to zero, the game ends (one way or the other). When the game finishes, you should ask the user whether he/she would like to play again. Allow as many games as the user wants before quitting the program.
3
Additional constraints
At the time this program was assigned, we had: Classes and methods Declarations, with and without initialization Assignment statements while loops if and if-else statements System.out.print and System.out.println The first version of this program reflects these constraints
4
public static void main(String[] args)
Here’s the outline of the main method: public static void main(String[] args) { IOFrame frame = new IOFrame("Lunar Lander"); LunarLander lander; double safeLandingSpeed = 10.0; String again = "yes"; // Main loop—One game is once through the loop // Inner loop: Play until the Lander crashes or lands frame.exit(); }
5
Main loop Recall that we had a String again = "yes"; declaration
Here’s the main loop: while ("yes".equals(again)) { // setup lander = new LunarLander(100, 0, 15); frame.clear(); frame.displayLine("Altitude: " + lander.getAltitude()); frame.displayLine("Velocity: " + lander.getVelocity()); frame.displayLine("Fuel left: " + lander.getFuelRemaining()); // inner loop to play the game // tell user how game ended again = frame.getString("Would you like to play again?"); }
6
Inner loop to play game // inner loop to play one game while (lander.getAltitude() > 0) { double amount = frame.getDouble("How much fuel should I burn?"); lander.burn(amount); frame.displayLine(""); frame.displayLine("Altitude: " + lander.getAltitude()); frame.displayLine("Velocity: " + lander.getVelocity()); frame.displayLine("Fuel left: " + lander.getFuelRemaining()); } // tell user how game ended double finalVelocity = lander.getVelocity(); if (finalVelocity > safeLandingSpeed) { frame.display("CRASH!"); } else { frame.display("Congratulations! A safe landing!"); }
7
LunarLander instance variables
public class LunarLander { double altitude; double velocity; double fuel; final double acceleration = 1.64; final double fuelFactor = 1.0; final double fuelLimit = 2.0; Where: acceleration is the Moon’s gravity (meters/second/second) fuelFactor is how much to reduce the velocity per unit of fuel burned fuelLimit is the maximum amount of fuel that can be burned at once
8
The LunarLander constructor
LunarLander(double altitude, double velocity, double fuel) { this.altitude = altitude; this.velocity = velocity; this.fuel = fuel; }
9
The burn(double) method
This is the method that does all the work of the LunarLander—it recomputes velocity, altitude, and fuel remaining void burn(double amount) { if (amount > fuel) amount = fuel; if (amount > fuelLimit) amount = fuelLimit; velocity = velocity + acceleration - amount * fuelFactor; fuel = fuel - amount; altitude = altitude - velocity; }
10
The “getter” methods double getFuelRemaining() { return fuel; }
double getAltitude() { return altitude; } double getVelocity() { return velocity; } That’s all... ...but the program could be improved
11
Improving the Lunar Lander program
Part II Improving the Lunar Lander program
12
Refactoring Refactoring is the process of rearranging and modifying code to improve it (without changing what it does) The following lines occur twice in the code: frame.displayLine("Altitude: " + lander.getAltitude()); frame.displayLine("Velocity: " + lander.getVelocity()); frame.displayLine("Fuel left: " + lander.getFuelRemaining()) Duplicated code is bad because, if you have to change it, you have to change it everyplace it is used One way to avoid code repetition is to put the offending code into a method This particular refactoring is called “Extract Method” It isn’t necessarily a single-step method I’ll do it informally
13
Extract Method I—displayStatus()
I create the following method: void displayStatus() { frame.displayLine("Altitude: " + lander.getAltitude()); frame.displayLine("Velocity: " + lander.getVelocity()); frame.displayLine("Fuel left: " + lander.getFuelRemaining()); } I call our new method this way (in two places): displayStatus(); This gives me syntax errors, because both frame and lander are local variables in main I have three choices: Pass in frame and lander as parameters Make frame and lander instance variables of LunarLanderGame Make frame and lander class variables of LunarLanderGame
14
Extract Method II—frame
I only ever want one IOFrame, so it makes sense to make frame a static variable I move this line IOFrame frame = new IOFrame("Lunar Lander"); out of the main method, put the word static in front of it, and make it a field of the LunarLanderGame class public class LunarLanderGame { static IOFrame frame = new IOFrame("Lunar Lander"); This solves the syntax error for frame
15
Extract Method III--lander
It seemed to me that each LunarLanderGame should have its own LunarLander Besides, I have no easy way to “reset” LunarLander for a new game I therefore decided to make LunarLander an instance variable Hence, this code: public class LunarLanderGame { public static void main(String[] args) { LunarLander lander; Becomes this code: public class LunarLanderGame { LunarLander lander; public static void main(String[] args) { This does not fix the syntax error—I can’t access LunarLander (an instance variable) from within main (a static method)
16
Extract Method III--run
We have a syntax error because: Every LunarLanderGame has its own LunarLander We have no LunarLanderGame objects Solution: Make a LunarLanderGame object in the main method, and let it do the work public static void main(String[] args) { LunarLanderGame game = new LunarLanderGame(); game.run(); } void run() { ...use lander here... }
17
Minor improvements I It seems unnatural to set the variable again just so we can go through the loop the first time: String again = "yes"; while ("yes".equalsIgnoreCase(again)) { again = frame.getString("Would you like to play again?"); } With the do...while loop, we can revise this to: String again; do { again = frame.getString("Would you like to play again?"); } while ("yes".equals(again)); Note: It doesn’t work to define again within the loop
18
Minor improvements II As written, any response other than “yes” will be taken to mean “no” This is a real nuisance, especially if you make a typing error do { main body of loop do { again = frame.getString("Would you like to play again?"); } while (!"yes".equals(again) && !"no".equals(again)); } while ("yes".equals(again)); Instead of equals, we can use equalsIgnoreCase This allows responses such as YES as well as yes
19
How is this improved? We’ve moved our status display code into a method, so any corrections or improvements in it need only be done in one place This also made the main loop smaller, so it’s easier to read and understand We’ve used the “right” kind of loop to avoid a rather silly-looking initialization We’ve made the yes/no question much more robust Come to think of it, this would be a good candidate for a method—getYesOrNo("Would you like to play again?") The code ends up being eight lines longer (you can’t win them all!)
20
Summary: Refactoring Refactoring is the process of rearranging and modifying code to improve it (without changing what it does) You improve code by making it: Easier to read and understand Easier to debug Easier to modify “Real” programs are constantly being read and modified Hence, refactoring is important and useful Conventional wisdom says: “If it ain’t broke, don’t fix it!” This is because it’s easy to introduce errors Refactoring is best done if you have a suite of tests you can run to make sure you didn’t break anything JUnit is one of the best ways to develop a suite of tests
21
The End
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.