Introduction to Simulations CS 1316 Representing Structure and

  • Slides: 85
Download presentation
Introduction to Simulations CS 1316: Representing Structure and Behavior

Introduction to Simulations CS 1316: Representing Structure and Behavior

Story What’s a simulation? Why do we simulate? • • Discrete vs. Continuous Resources

Story What’s a simulation? Why do we simulate? • • Discrete vs. Continuous Resources Building software to be modifiable: Software Engineering • Building models out of objects: aggregation, generalizing and specializing Continuous Simulations • • Predatory-prey: Wolves and Deer Changing our simulation Creating hungry wolves Other options: Hungry deer? Deer sex? Wolf sex? • Creating text files How do we compare simulations?

Simulations “A simulation is a representation of a system of objects in a real

Simulations “A simulation is a representation of a system of objects in a real or fantasy world. The purpose of creating a computer simulation is to provide a framework in which to understand the simulated situation, for example, to understand the behavior of a waiting line, the workload of clerks, or the timeliness of service to customers. A computer simulation makes it possible to collect statistics about these situations, and to test out new ideas about their organization. ” • Adele Goldberg & David Robson, Smalltalk-80: The Language and Its Implementation (Addison-Wesley, 1989)

Simulations and Objects Object-oriented programming was invented, in part, to make simulations easier to

Simulations and Objects Object-oriented programming was invented, in part, to make simulations easier to build! The characteristics of objects make them more like real world objects, e. g. , • • • Each thing knows some stuff and knows how to do some stuff. Objects get things done by asking each other to do things. Your internals are private, unless you want to make them otherwise.

Continuous vs. Discrete Simulations Two main kinds of simulations in the world. Continuous: Each

Continuous vs. Discrete Simulations Two main kinds of simulations in the world. Continuous: Each moment of time is simulated. • When every moment counts. Discrete: Skip to the important moments. • Want to simulate 100 years?

Resources are points of coordination in a simulation. • Examples: A cashier, a library

Resources are points of coordination in a simulation. • Examples: A cashier, a library book, a parking space on a ferry, a jelly bean. Some resources are fixed and others are produced and consumed. Some resources are renewable and shared. Others are coordinated. • Example: For a surgeon to do a surgery, the patient must meet the surgeon at the operating table (the resource)

When an object has to wait… What happens if you (or your proxy object)

When an object has to wait… What happens if you (or your proxy object) need a resource and it’s not available? • You wait in a queue • A list that is first-in-first-out (FIFO)

A simulation is an executed model Setting up a simulation is a process of

A simulation is an executed model Setting up a simulation is a process of modeling the world (real or fantasy) to be simulated. That model is realized in terms of objects. We want our model to: • • Reflect the world. Be easy to extend and change. Some of our modeling techniques: • • Aggregation Generalization and specialization

Aggregation Some objects are made up of other objects. • Cars have engines •

Aggregation Some objects are made up of other objects. • Cars have engines • People have livers and lungs • These internal things are objects, too! • Livers don’t directly mess with the innards of lungs! We call this aggregation • Putting references to some objects inside of other objects.

Generalization and Specialization There are general and specialized forms of real world objects. •

Generalization and Specialization There are general and specialized forms of real world objects. • • Cells are biological objects that have membranes and a nucleus and mitochondria and… Blood, lung, and liver cells are all cells but have specialized functions. The superclass-subclass relationship is a way of modeling general forms of objects and specialized forms of objects

Making it concrete: Wolves eating deer

Making it concrete: Wolves eating deer

Running the simulation Welcome to Dr. Java. > Wolf. Deer. Simulation wds = new

Running the simulation Welcome to Dr. Java. > Wolf. Deer. Simulation wds = new Wolf. Deer. Simulation() > wds. run() >>> Timestep: 0 Wolves left: 5 Deer left: 20 >>> Timestep: 1 Wolves left: 5 Deer left: 20 <SIGH!> A deer died. . . >>> Timestep: 2 Wolves left: 5 Deer left: 19 >>> Timestep: 3 Wolves left: 5 Deer left: 19 <SIGH!> A deer died. . . >>> Timestep: 4 Wolves left: 5 Deer left: 18

An Example Simulation The Wolf. Deer. Simulation is a continuous simulation. • Each moment

An Example Simulation The Wolf. Deer. Simulation is a continuous simulation. • Each moment in time is simulated. It has no resources. It is a predator-prey simulation • A common real world (ecological) situation. • There are parameters to change to explore under what conditions predators and prey survive and in what numbers.

The Model of this Simulation Wolf. Deer. Simulation Turtle Knows the list of wolves

The Model of this Simulation Wolf. Deer. Simulation Turtle Knows the list of wolves and deer LLNode Knows. How to run() each moment in time Wolf Deer Knows. How to act(), and to find the closest deer. Knows. How to act() and die Agent. Node Knows its turtle (agent) Knows. How to get/set agent, to remove an agent

Complicated Set of Relationships in this Model Wolf and Deer are kinds of Turtle

Complicated Set of Relationships in this Model Wolf and Deer are kinds of Turtle • Specializations of Turtle Agent. Node is a kind of LLNode Agent. Nodes each have one Turtle (Wolf or Deer) inside it. Wolf. Deer. Simulation has two Agent. Nodes for the lists of live wolves and deer. Each Wolf and Deer knows what simulation its in.

A UML Class Diagram

A UML Class Diagram

Unified Modeling Language (UML) This is a UML class diagram. • A graphical notation

Unified Modeling Language (UML) This is a UML class diagram. • A graphical notation for describing the relationships between classes in a model. UML is a standard that describes several different kinds of diagrams. • Collaboration diagrams: How objects work • together and how they call on one another. Sequence diagrams: What the order of events are in an object system.

A class in a UML class diagram Name of the class Operations or methods:

A class in a UML class diagram Name of the class Operations or methods: What the instances know how Instance variables or fields: What the class instances know

Generalization-specialization relationships A Deer is a subclass of Turtle: It’s a specialization of Turtle

Generalization-specialization relationships A Deer is a subclass of Turtle: It’s a specialization of Turtle

Associations Wolf. Deer. Simulation has two Agent. Nodes in it: One to represent wolves

Associations Wolf. Deer. Simulation has two Agent. Nodes in it: One to represent wolves and one to represent deer. Agent. Nodes don’t know their simulation

A Class Diagram describes the Model, without the Code

A Class Diagram describes the Model, without the Code

Wolf. Deer. Simulation public class Wolf. Deer. Simulation { /* Linked lists for tracking

Wolf. Deer. Simulation public class Wolf. Deer. Simulation { /* Linked lists for tracking wolves and deer */ Why private? private Agent. Node wolves; Only the private Agent. Node deer; simulation should know its wolves and deer. /** Accessors for wolves and deer */ public Agent. Node get. Wolves(){return wolves; } public Agent. Node get. Deer(){return deer; }

The main run() method public void run() { World w = new World(); w.

The main run() method public void run() { World w = new World(); w. set. Auto. Repaint(false); // Start the lists wolves = new Agent. Node(); deer = new Agent. Node(); // create some deer int num. Deer = 20; for (int i = 0; i < num. Deer; i++) { deer. add(new Agent. Node(new Deer(w, this))); } We want to control when the world updates itself. Agent. Nodes contain the Deer

Head and Rest Wolves and deer are Agent. Nodes…but the real content starts at

Head and Rest Wolves and deer are Agent. Nodes…but the real content starts at get. Next(). We call this the head of the list. • It’s a placeholder. We call the rest or body of the list. • This makes it possible to remove a node, even if it’s the first one in the list. wolves Head Rest get. Next:

Make some wolves // create some wolves int num. Wolves = 5; for (int

Make some wolves // create some wolves int num. Wolves = 5; for (int i = 0; i < num. Wolves; i++) { wolves. add(new Agent. Node(new Wolf(w, this))); }

Start our simulation loop // declare a wolf and deer Wolf current. Wolf =

Start our simulation loop // declare a wolf and deer Wolf current. Wolf = null; Deer current. Deer = null; Agent. Node current. Node = null; // loop for a set number of timesteps (50 here) for (int t = 0; t < 50; t++) { // loop through all the wolves current. Node = (Agent. Node) wolves. get. Next(); while (current. Node != null) { current. Wolf = (Wolf) current. Node. get. Agent(); current. Wolf. act(); current. Node = (Agent. Node) current. Node. get. Next(); } What’s going on here? It’s our Agent. Nodes that are in a linked list. Each one of them contains (aggregation!) a Wolf. Have to pull the Wolf out to get it to act()

Give the deer a chance to act // loop through all the deer current.

Give the deer a chance to act // loop through all the deer current. Node = (Agent. Node) deer. get. Next(); while (current. Node != null) { current. Deer = (Deer) current. Node. get. Agent(); current. Deer. act(); current. Node = (Agent. Node) current. Node. get. Next(); } Same unpackaging going on here.

Show us what happened // repaint the world to show the movement w. repaint();

Show us what happened // repaint the world to show the movement w. repaint(); // Let's figure out where we stand. . . System. out. println(">>> Timestep: "+t); System. out. println("Wolves left: "+wolves. get. Next(). count()); System. out. println("Deer left: "+deer. get. Next(). count()); // Wait for one second //Thread. sleep(1000); } } Does the simulation go too fast? Make thread of execution sleep for 1000 milliseconds

Implementing a Wolf import java. awt. Color; import java. util. Random; import java. util.

Implementing a Wolf import java. awt. Color; import java. util. Random; import java. util. Iterator; /** * Class that represents a wolf. The wolf class * tracks all the living wolves with a linked list. * * @author Barb Ericson ericson@cc. gatech. edu */ public class Wolf extends Turtle { //////// fields /////////// /** class constant for the color */ private static final Color grey = new Color(153, 153); A final is something that won’t change: A constant. It’s used to make code more readable yet easyto-change. Private vs. Protected? Use Protected if your subclasses will need to access (new kinds of wolves? ) /** class constant for probability of NOT turning */ protected static final double PROB_OF_STAY = 1/10; Constants are typically all-caps

More Wolf fields /** class constant for top speed (max num steps can move

More Wolf fields /** class constant for top speed (max num steps can move in a timestep) */ protected static final int max. Speed = 60; max. Speed should /** My simulation */ protected Wolf. Deer. Simulation my. Sim; probably be all-caps (or did you want to make it variable? Do wolves get slower as they get hungry? /** random number generator */ protected static Random rand. Num. Gen = new Random(); There is more than one kind of random. Treating it as an object makes it easier to have different kinds later.

/////////////// Constructors Remember that a constructor must match its superclass, if you want to

/////////////// Constructors Remember that a constructor must match its superclass, if you want to use super(). These are like the ones in Turtle. What’s a Model. Display? The abstract superclass of the World. /** * Constructor that takes the model display (the original * position will be randomly assigned) * @param model. Displayer thing that displays the model * @param my. Sim my simulation */ public Wolf (Model. Display model. Displayer, Wolf. Deer. Simulation this. Sim) { super(rand. Num. Gen. next. Int(model. Displayer. get. Width()), rand. Num. Gen. next. Int(model. Displayer. get. Height()), model. Displayer); init(this. Sim); } /** Constructor that takes the x and y and a model * display to draw it on * @param x the starting x position * @param y the starting y position * @param model. Displayer the thing that displays the model * @param my. Sim my simulation */ public Wolf (int x, int y, Model. Display model. Displayer, Wolf. Deer. Simulation this. Sim) { // let the parent constructor handle it super(x, y, model. Displayer); init(this. Sim); }

Using a Random: Pseudo. Random Number Generator

Using a Random: Pseudo. Random Number Generator

Initialize a Wolf ///////// methods //////////////////// /** * Method to initialize the new wolf

Initialize a Wolf ///////// methods //////////////////// /** * Method to initialize the new wolf object */ public void init(Wolf. Deer. Simulation this. Sim) { // set the color of this wolf set. Color(grey); // turn some random direction this. turn(rand. Num. Gen. next. Int(360)); // set my simulation my. Sim = this. Sim; } Get an integer at most 360

Is there a Deer to eat? public Agent. Node get. Closest(double distance, Agent. Node

Is there a Deer to eat? public Agent. Node get. Closest(double distance, Agent. Node list) { // get the head of the deer linked list Agent. Node head = list; Agent. Node curr = head; Agent. Node closest = null; Deer this. Deer; double closest. Distance = 0; double curr. Distance = 0; Walk this through in English to see that it’s doing what you think it should. // loop through the linked list looking for the closest deer while (curr != null) { this. Deer = (Deer) curr. get. Agent(); curr. Distance = this. Deer. get. Distance( this. get. XPos(), this. get. YPos()); if (curr. Distance < distance) { if (closest == null || curr. Distance < closest. Distance) { closest = curr; closest. Distance = curr. Distance; } } curr = (Agent. Node) curr. get. Next(); } return closest; || is “OR” }

Modeling what a Wolf does /** * Method to act during a time step

Modeling what a Wolf does /** * Method to act during a time step * pick a random direction and move some random amount up to top speed */ public void act() { // get the closest deer within some specified distance Agent. Node close. Deer = get. Closest(30, (Agent. Node) my. Sim. get. Deer(). get. Next()); if (close. Deer != null) { Deer this. Deer = (Deer) close. Deer. get. Agent(); this. move. To(this. Deer. get. XPos(), this. Deer. get. YPos()); this. Deer. die(); } Why get. Next()? Because we need the body of the list, and that’s after the head. get. Closest returns an Agent. Node, so we have to get the Deer out of it with get. Agent()

If can’t eat, then move else { // if the random number is >

If can’t eat, then move else { // if the random number is > prob of NOT turning then turn if (rand. Num. Gen. next. Float() > PROB_OF_STAY) { Get an integer this. turn(rand. Num. Gen. next. Int(360)); at most 360, or } // go forward some random amount forward(rand. Num. Gen. next. Int(max. Speed)); } } at most max. Speed

Deer import java. awt. Color; import java. util. Random; /** * Class that represents

Deer import java. awt. Color; import java. util. Random; /** * Class that represents a deer. The deer class * tracks all living deer with a linked list. * * @author Barb Ericson ericson@cc. gatech. edu */ public class Deer extends Turtle { //////// fields /////////// /** class constant for the color */ private static final Color brown = new Color(116, 64, 35); /** class constant for probability of NOT turning */ private static final double PROB_OF_STAY = 1/5;

Deer fields (instance variables) /** class constant for top speed (max num steps can

Deer fields (instance variables) /** class constant for top speed (max num steps can move in a timestep) */ private static final int max. Speed = 50; /** random number generator */ private static Random rand. Num. Gen = new Random(); /** the simulation I'm in */ private Wolf. Deer. Simulation my. Sim;

/////////////// Constructors //////////// Deer Constructors Nothing new here… /** * Constructor that takes the

/////////////// Constructors //////////// Deer Constructors Nothing new here… /** * Constructor that takes the model display (the original * position will be randomally assigned * @param model. Displayer thing which will display the model */ public Deer (Model. Display model. Displayer, Wolf. Deer. Simulation this. Sim) { super(rand. Num. Gen. next. Int(model. Displayer. get. Width()), rand. Num. Gen. next. Int(model. Displayer. get. Height()), model. Displayer); init(this. Sim); } /** Constructor that takes the x and y and a model * display to draw it on * @param x the starting x position * @param y the starting y position * @param model. Displayer the thing that displays the model */ public Deer (int x, int y, Model. Display model. Displayer, Wolf. Deer. Simulation this. Sim) { // let the parent constructor handle it super(x, y, model. Displayer); init(this. Sim); }

Initializing a Deer /** * Method to initialize the new deer object */ public

Initializing a Deer /** * Method to initialize the new deer object */ public void init(Wolf. Deer. Simulation this. Sim) { // set the color of this deer set. Color(brown); // turn some random direction this. turn(rand. Num. Gen. next. Int(360)); // know my simulation my. Sim = this. Sim; } Nothing new here…

What Deer Do /** * Method to act during a time step * pick

What Deer Do /** * Method to act during a time step * pick a random direction and move some random amount up to top speed */ public void act() { // if the random number is > prob of NOT turning then turn if (rand. Num. Gen. next. Float() > PROB_OF_STAY) { this. turn(rand. Num. Gen. next. Int(360)); Nothing new } here… // go forward some random amount forward(rand. Num. Gen. next. Int(max. Speed)); }

When Deer Die /** * Method that handles when a deer dies */ public

When Deer Die /** * Method that handles when a deer dies */ public void die() { // Leave a mark on the world where I died. . . this. set. Body. Color(Color. red); // Remove me from the "live" list my. Sim. get. Deer(). remove(this); Why don’t we have to say get. Next() before the remove()? // ask the model display to remove this // Think of this as "ask the viewable world to remove this turtle" //get. Model. Display(). remove(this); If you want the System. out. println("<SIGH!> A deer died. . . "); } body and its trail to disappear…

Agent. Nodes contain Turtles It’s a subclass of LLNode • That’s aggregation • It’s

Agent. Nodes contain Turtles It’s a subclass of LLNode • That’s aggregation • It’s a specialization of LLNode

Agent. Node implementation /** * Class to implement a linked list of Turtle-like characters.

Agent. Node implementation /** * Class to implement a linked list of Turtle-like characters. * (Maybe "agents"? ) **/ public class Agent. Node extends LLNode { /** * The Turtle being held **/ private Turtle my. Turtle;

Agent. Node constructors /** Two constructors: One for creating the head of the list

Agent. Node constructors /** Two constructors: One for creating the head of the list * , with no agent **/ public Agent. Node() {super(); } /** * One constructor for creating a node with an agent **/ public Agent. Node(Turtle agent){ super(); this. set. Agent(agent); }

Agent. Node getter/setter /** * Setter for the turtle **/ public void set. Agent(Turtle

Agent. Node getter/setter /** * Setter for the turtle **/ public void set. Agent(Turtle agent){ my. Turtle = agent; } /** * Getter for the turtle **/ public Turtle get. Agent(){return my. Turtle; }

Agent. Node: Remove node where Turtle is found /** * Remove the node where

Agent. Node: Remove node where Turtle is found /** * Remove the node where this turtle is found. **/ public void remove(Turtle my. Turtle) { // Assume we're calling on the head Agent. Node head = this; Agent. Node current = (Agent. Node) this. get. Next(); while (current != null) { if (current. get. Agent() == my. Turtle) {// If found the turtle, remove that node head. remove(current); } current = (Agent. Node) current. get. Next(); } } It’s just like other linked list removes, but now we’re looking for the node that contains the input turtle.

Think about it… What if Agent. Nodes contained Objects? • Object is a class

Think about it… What if Agent. Nodes contained Objects? • Object is a class that is the superclass of all • classes (even if not explicitly extended). Agent. Nodes that contain Objects could be general linked lists that contain anything • Just cast things as you need them as you pull them out.

Back to the simulation: What might we change? Wolves that aren’t always hungry? Having

Back to the simulation: What might we change? Wolves that aren’t always hungry? Having wolves that chase deer? Have deer run from wolves? And how do we look at the results? We’ll deal with hunger first, then with comparing, then with running towards/away.

Creating a Hungry Wolf /** * A class that extends the Wolf to have

Creating a Hungry Wolf /** * A class that extends the Wolf to have a Hunger level. * Wolves only eat when they're hungry **/ public class Hungry. Wolf extends Wolf { /** * Number of cycles before I'll eat again **/ private int satisfied; /** class constant for number of turns before hungry */ private static final int MAX_SATISFIED = 3;

Need to match /** * Constructor that takes the model display (the original *

Need to match /** * Constructor that takes the model display (the original * position will be randomly assigned) * @param model. Displayer thing that displays the model * @param my. Sim my simulation */ public Hungry. Wolf (Model. Display model. Displayer, Wolf. Deer. Simulation this. Sim) { super(model. Displayer, this. Sim); } /** Constructor that takes the x and y and a model * display to draw it on * @param x the starting x position * @param y the starting y position * @param model. Displayer the thing that displays the model * @param my. Sim my simulation */ public Hungry. Wolf (int x, int y, Model. Display model. Displayer, Wolf. Deer. Simulation this. Sim) { // let the parent constructor handle it super(x, y, model. Displayer, this. Sim); }

Initializing a Hungry. Wolf /** * Method to initialize the hungry wolf object */

Initializing a Hungry. Wolf /** * Method to initialize the hungry wolf object */ public void init(Wolf. Deer. Simulation this. Sim) { super. init(this. Sim); satisfied = MAX_SATISFIED; }

What a Hungry. Wolf does /** * Method to act during a time step

What a Hungry. Wolf does /** * Method to act during a time step * pick a random direction and move some random amount up to top speed */ public void act() { // Decrease satisfied time, until hungry again satisfied--; // get the closest deer within some specified distance Agent. Node close. Deer = get. Closest(30, (Agent. Node) my. Sim. get. Deer(). get. Next()); if (close. Deer != null) { // Even if deer close, only eat it if you're hungry. if (satisfied <= 0) {Deer this. Deer = (Deer) close. Deer. get. Agent(); this. move. To(this. Deer. get. XPos(), this. Deer. get. YPos()); this. Deer. die(); satisfied = MAX_SATISFIED; }} If there is a Deer near, then check if you’re hungry, and only then—eat and get “full”

And if no Deer are near… else { // if the randome number is

And if no Deer are near… else { // if the randome number is > prob of turning then turn if (rand. Num. Gen. next. Float() > PROB_OF_TURN) { this. turn(rand. Num. Gen. next. Int(360)); } Nothing new here… // go forward some random amount forward(rand. Num. Gen. next. Int(max. Speed)); } }

Changing the Simulation to make Hungry. Wolves (in run()) // create some wolves int

Changing the Simulation to make Hungry. Wolves (in run()) // create some wolves int num. Wolves = 5; for (int i = 0; i < num. Wolves; i++) { wolves. add(new Agent. Node(new Hungry. Wolf(w, this))); Everything else just works, because } Hungry. Wolf is a kind of Wolf

Writing to a Text File We have to create a stream that allows us

Writing to a Text File We have to create a stream that allows us access to a file. We’re going to want to write strings to it. We’re going to have to handle things going wrong—exceptional events like the filename being wrong or the disk failing. Here’s how…

Input and Output Streams java. io Java handles input and output through sequential streams

Input and Output Streams java. io Java handles input and output through sequential streams of bits Programs can read from a stream or write to a stream Source or Destination Byte Data Character Data File String 100110 Array Program

Standard Input and Output We have been using System. out. println to print output

Standard Input and Output We have been using System. out. println to print output to a Print. Stream (standard output). System. out. println(“First Name: “ + first. Name); There is also a System. err Print. Stream that can be used to write to the standard error output. System. err. println(“Error: no file name given”); You can use System. in to read a byte or bytes from an Input. Stream (standard input). int num. Grades = System. in. read();

Chaining Input and Output Classes Often input or output classes are chained • Passing

Chaining Input and Output Classes Often input or output classes are chained • Passing one type of input/output class to the constructor for another One common thing is to chain a processing class with a data sink class • Like a Buffered. Reader or Buffered. Writer and a File. Reader or File. Writer new Buffered. Reader(new File. Reader(file. Name));

Exceptions are disruptions in the normal flow of a program. Exception is short for

Exceptions are disruptions in the normal flow of a program. Exception is short for exceptional event. The programmer is required to handle checked exceptions in Java • like trying to read from a file that doesn’t exist Run-time exceptions do not have to be handled by the programmer • • like trying to invoke a method on a object reference that is null Children of Runtime. Exception

Try and Catch Use a try & catch clause to catch an exception try

Try and Catch Use a try & catch clause to catch an exception try { code that can cause exceptions } catch (Exception. Class. Name var. Name) { code to handle the exception } You can catch several exceptions • • Make the most general one last All exceptions are children of the class Exception

Try and Catch: If the file isn’t there… What if you want to know

Try and Catch: If the file isn’t there… What if you want to know if a file isn’t found • • That you are trying to read from If this occurs you might want to use a JFile. Chooser to let the user pick the file You also want to handle any other error try { code that can cause the exception } catch (File. Not. Found. Exception ex) { code to handle when the file isn’t found } catch (Exception ex) { code to handle the exception }

Catching Exceptions A catch clause will catch the given Exception class and any subclasses

Catching Exceptions A catch clause will catch the given Exception class and any subclasses of it. So to catch all exceptions use: You can print the error message code that can throw the exception and the stack } catch (Exception e) { trace (the list of all System. err. println(“Exception: “ + e. get. Message()); currently running System. err. println(“Stack Trace is: ”); methods) try { e. print. Stack. Trace(); } You can create your own exceptions by subclassing Exception or a child of Exception.

The optional finally clause A try and catch statement can have a finally clause

The optional finally clause A try and catch statement can have a finally clause • Which will always be executed • Will happen if no exceptions • Will happen even if exceptions occur try { code that can cause the exception } catch (File. Not. Found. Exception ex) { code to handle when the file isn’t found } finally { code to always be executed }

Writing to a File Use a try-catch clause to catch exceptions • Create a

Writing to a File Use a try-catch clause to catch exceptions • Create a buffered writer from a file writer = new Buffered. Writer(new File. Writer(file. Name)); • Write the data writer. write(data); • Close the buffered writer • writer. close();

Reading Lines of Character Data Enclose the code in a try and catch clause

Reading Lines of Character Data Enclose the code in a try and catch clause • • And you may want to give the user a chance to specify a new file Catch Exception to handle all other errors File names are relative to the current directory Loop reading lines from the buffered reader until the line is null • • Create a buffered reader from a file reader for more efficient reading • Catch File. Not. Found. Exception if the file doesn’t exist Do something with the data Close the buffered reader

Reading from File Example Buffered. Reader reader = null; String line = null; //

Reading from File Example Buffered. Reader reader = null; String line = null; // try to read the file try { // create the buffered reader = new Buffered. Reader(new File. Reader(file. Name)); // loop reading lines till the line is null (end of file) while ((line = reader. read. Line()) != null) { // do something with the line } // close the buffered reader. close(); } catch (Exception ex) { // handle exception }

Adding an Output File to Wolf. Deer. Simulation /* A Buffered. Writer for writing

Adding an Output File to Wolf. Deer. Simulation /* A Buffered. Writer for writing to */ public Buffered. Writer output; /** * Constructor to set output to null **/ public Wolf. Deer. Simulation() { output = null; }

Opening the File /** * Open the input file and set the Buffered. Writer

Opening the File /** * Open the input file and set the Buffered. Writer to speak to it. **/ public void open. File(String filename){ // Try to open the file try { // create a writer output = new Buffered. Writer(new File. Writer(filename)); } catch (Exception ex) { System. out. println("Trouble opening the file " + filename); // If any problem, make it null again output = null; } }

Changing the time loop // Let's figure out where we stand. . . System.

Changing the time loop // Let's figure out where we stand. . . System. out. println(">>> Timestep: "+t); System. out. println("Wolves left: "+wolves. get. Next(). count()); System. out. println("Deer left: "+deer. get. Next(). count()); // If we have an open file, write the counts to it if (output != null) { // Try it try{ output. write(wolves. get. Next(). count()+"t"+deer. get. Next(). count()); output. new. Line(); } catch (Exception ex) { System. out. println("Couldn't write the data!"); System. out. println(ex. get. Message()); // Make output null so that we don't keep trying output = null; } }

After the timing loop // If we have an open file, close it and

After the timing loop // If we have an open file, close it and null the variable if (output != null){ try{ output. close(); } catch (Exception ex) {System. out. println("Something went wrong closing the file"); } finally { // No matter what, mark the file as not-there output = null; } }

Running the Simulation with a File Welcome to Dr. Java. > Wolf. Deer. Simulation

Running the Simulation with a File Welcome to Dr. Java. > Wolf. Deer. Simulation wds = new Wolf. Deer. Simulation(); > wds. open. File("D: /cs 1316/wds-run 1. txt") > wds. run();

Finding the file in Excel

Finding the file in Excel

Adding Labels for the Chart

Adding Labels for the Chart

Making Wolves and Deer Run What we do: • • In Deer, if there

Making Wolves and Deer Run What we do: • • In Deer, if there is a Wolf within our smelling range, run in the opposite direction (turn towards, turn 180, move) In Wolf, if there is a Deer within our smelling range, run towards it. (Stays the same) If the Wolf gets close enough, gobble up the Deer. (Stays the same) For both, otherwise, wander aimlessly.

New constants for Deer /** class constant for probability of NOT turning */ private

New constants for Deer /** class constant for probability of NOT turning */ private static final double PROB_OF_STAY = 1/5; /** class constant for how far deer can smell */ private static final double SMELL_RANGE = 50; /** class constant for top speed (max num steps can move in a timestep) */ private static final int max. Speed = 30;

Deer-finding closest Wolf Strikingly similar to Wolf’s for find Deer, no? /** * Method

Deer-finding closest Wolf Strikingly similar to Wolf’s for find Deer, no? /** * Method to get the closest wolf within the passed distance * to this deer. We'll search the input list of the kind * of objects to compare to. */ public Agent. Node get. Closest(double distance, Agent. Node list) { // get the head of the deer linked list Agent. Node head = list; Agent. Node curr = head; Agent. Node closest = null; Wolf this. Wolf; double closest. Distance = 0; double curr. Distance = 0; // loop through the linked list looking for the closest deer while (curr != null) { this. Wolf = (Wolf) curr. get. Agent(); curr. Distance = this. Wolf. get. Distance(this. get. XPos(), this. get. YPos()); if (curr. Distance < distance) { if (closest == null || curr. Distance < closest. Distance) { closest = curr; closest. Distance = curr. Distance; } } curr = (Agent. Node) curr. get. Next(); } return closest; }

Deer new act() /** * Method to act during a time step * pick

Deer new act() /** * Method to act during a time step * pick a random direction and move some random amount up to top speed */ public void act() { // get the closest wolf within the smell range Agent. Node close. Wolf = get. Closest(SMELL_RANGE, (Agent. Node) my. Sim. get. Wolves(). get. Next()); Does this match the English description we had a few slides back? if (close. Wolf != null) { Wolf this. Wolf = (Wolf) close. Wolf. get. Agent(); // Turn to face the wolf this. turn. To. Face(this. Wolf); // Now directly in the opposite direction this. turn(180); // How far to run? How about half of max speed? ? this. forward((int) (max. Speed/2)); } else { // if the random number is > prob of NOT turning then turn if (rand. Num. Gen. next. Float() > PROB_OF_STAY) { this. turn(rand. Num. Gen. next. Int(360)); } Think about this in terms of the values that can be changed and their relative values. // go forward some random amount forward(rand. Num. Gen. next. Int(max. Speed)); } }

Wolf Constants /** class constant for probability of NOT turning */ protected static final

Wolf Constants /** class constant for probability of NOT turning */ protected static final double PROB_OF_STAY = 1/10; /** class constant for top speed (max num steps can move in a timestep) */ protected static final int max. Speed = 40; /** class constant for how far wolf can smell */ private static final double SMELL_RANGE = 50; /** class constant for how close before wolf can attack */ private static final double ATTACK_RANGE = 30;

How Wolf’s smell deer /** * Method to act during a time step *

How Wolf’s smell deer /** * Method to act during a time step * pick a random direction and move some random amount up to top speed */ public void act() { // get the closest deer within smelling range Agent. Node close. Deer = get. Closest(SMELL_RANGE, (Agent. Node) my. Sim. get. Deer(). get. Next()); if (close. Deer != null) { Deer this. Deer = (Deer) close. Deer. get. Agent(); // Turn torward deer this. turn. To. Face(this. Deer); // How much to move? How about minimum of max. Speed // or distance to deer? this. forward((int) Math. min(max. Speed, this. Deer. get. Distance(this. get. XPos(), this. get. YPos()))); }

The rest of normal Wolf actions // get the closest deer within the attack

The rest of normal Wolf actions // get the closest deer within the attack distance close. Deer = get. Closest(ATTACK_RANGE, (Agent. Node) my. Sim. get. Deer(). get. Next()); if (close. Deer != null) { Deer this. Deer = (Deer) close. Deer. get. Agent(); this. move. To(this. Deer. get. XPos(), this. Deer. get. YPos()); this. Deer. die(); } else // Otherwise, wander aimlessly { // if the randome number is > prob of NOT turning then turn if (rand. Num. Gen. next. Float() > PROB_OF_STAY) { this. turn(rand. Num. Gen. next. Int(360)); } // go forward some random amount forward(rand. Num. Gen. next. Int(max. Speed)); } // end else } // end act()

Changes to Wolf. Deer. Simulation…NOTHING! We have the same interface as we used to

Changes to Wolf. Deer. Simulation…NOTHING! We have the same interface as we used to have, so nothing changes in Wolf. Deer. Simulation. Very powerful idea: • If changes to a class keep the interface the same, then all users of the class don’t have to change at all.

Running the new simulation Welcome to Dr. Java. > Wolf. Deer. Simulation wds =

Running the new simulation Welcome to Dr. Java. > Wolf. Deer. Simulation wds = new Wolf. Deer. Simulation(); > wds. open. File("D: /cs 1316/wdschase. txt") > wds. run();

Explorations What does the relative speed of Deer and Wolves matter? • What if

Explorations What does the relative speed of Deer and Wolves matter? • What if Deer and Wolves can smell farther away? • Does it matter if Deer go faster? Wolves? What if one can smell better than the other? What’s the effect of having more Deer or more Wolves? What if Hungry. Wolves could starve (say at -10 satisfaction)? Do more deer live?

Doing More Simulations How much code would be in common in every simulation we’d

Doing More Simulations How much code would be in common in every simulation we’d build? • We already have lots of duplication, e. g. , get. Closest. Goal: Can we make an Agent/Actor class and Simulation class that we’d subclass with very little additional code to create new simulations?