Show Your Code Solutions

Show Your Code #1

1. Make the person walk randomly around the screen as part of the act method. Look in the API at the Greenfoot class for methods that will allow you to generate random numbers. Note that when you call a static method the syntax is ClassName.methodName(args).

public class Person extends Actor { /** * Act - do whatever the Person wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { setLocation(getX()+Greenfoot.getRandomNumber(3)-1,getY()+Greenfoot.getRandomNumber(3)-1); } }

2. Make the person walk in circles. You will do this by having the move based on the rotation of the person and by changing the rotation with each call to act. To get the move from the rotation will require using the trig functions sine and cosine. These can be called with Math.sin(angle) and Math.cos(angle). One catch is that the sine and cosine functions want radians and rotation is in degrees.

public class Person extends Actor { /** * Act - do whatever the Person wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { double angle=getRotation()*Math.PI/180; // You could use 3.14159 instead of Math.PI double dx=1.5*Math.cos(angle); double dy=1.5*Math.sin(angle); setLocation(getX()+(int)dx,getY()+(int)dy); setRotation(getRotation()+10); } }

Putting this into the normal city makes the person go in something of a square. To get a smooth circle you can change the a line in the City class so that insteadof reading super(15,15,50) it reads something like super(150,150,5) then change the two places above that say 1.5 to 15.

3. Have the city start off with ten houses at random locations. See 1. for how to get random numbers.

public class City extends World { /** * Constructor for objects of class City. * */ public City() { super(15, 15, 50); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); addObject(new Building(),Greenfoot.getRandomNumber(getWidth()),Greenfoot.getRandomNumber(getHeight())); } }

4. Make the person reproduce. Each time act is called have a new person appear at a random location on the screen. See 1. for how to get random numbers. (Hint: if you do this, don't do Run. Hit Act multiple time instead.)

public class Person extends Actor { /** * Act - do whatever the Person wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { getWorld().addObject(new Person(),Greenfoot.getRandomNumber(15),Greenfoot.getRandomNumber(15)); } }

This code can be made a bit more robust with the following change so that we aren't hard coding in the size of the screen. A variable is used to remember the word so that we don't have to type getWorld() over and over.

public class Person extends Actor { /** * Act - do whatever the Person wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { World w=getWorld(); w.addObject(new Person(),Greenfoot.getRandomNumber(w.getWidth()),Greenfoot.getRandomNumber(w.getHeight())); } }

Show Your Code #2

1. Endless sidewalk (wrap around) - Generate 5 people, and have them randomly walk around. Write code that moves a person from one end of a row or column to the other if the person tries to walk off-screen. Use getWidth() and getHeight() to determine the size of the screen.

public void act() { World w=getWorld(); int x=getX()+Greenfoot.getRandomNumber(3)-1; int y=getY()+Greenfoot.getRandomNumber(3)-1; if(x<0) { x=w.getWidth()-1; } if(x>=w.getWidth()) { x=0; } if(y<0) { y=w.getHeight()-1; } if(y>=w.getHeight()) { y=0; } setLocation(x,y); }

2. Making an entrance - Generate 5 people and 3 buildings. Have the people randomly walk around and detect whether or not a person has encountered a building. If so, enter the building (remove the Person from the board).

public void act() { int x=getX()+Greenfoot.getRandomNumber(3)-1; int y=getY()+Greenfoot.getRandomNumber(3)-1; setLocation(x,y); if(isBuildingAt(x,y)) { getWorld().removeObject(this); } }

3. Under construction - Generate 6 people and have them walk around randomly. Whenever two or more people enter the same location, a building is constructed there, provided one doesn't exist at that location.

public void act() { if(isAnotherPersonAt(getX(),getY()) && !isBuildingAt(getX(),getY())) { getWorld().addObject(new Building(),getX(),getY()); } int x=getX()+Greenfoot.getRandomNumber(3)-1; int y=getY()+Greenfoot.getRandomNumber(3)-1; setLocation(x,y); }

4. Avoidance detection - Randomly generate 5 people and 5 buildings on the map. Have the people randomly move, but never into the same cell as buildings or other people.

public void act() { int x=getX()+Greenfoot.getRandomNumber(3)-1; int y=getY()+Greenfoot.getRandomNumber(3)-1; if(!isPersonAt(x,y) && !isBuildingAt(x,y)) { setLocation(x,y); } }

If you play with this code long enough you will find that it doesn't always work for buildings or people at the edge. Can you explain why?

Options 2-4 all require that you have the ability to tell if something is at a particular location in the city. We haven't learned how to do this yet so I'm providing the code for it here. These two methods could be put in a class that inherits from Actor to get the type of functionality that you would expect based on their names. Because of the way that Greenfoot works, you won't get the results you expect unless you either use a smaller image of the building or make the cell size in City 80 or larger. I change the first line of the construtor in City to be super(10,10,80); and get the right behavior in my testing.

public boolean isPersonAt(int x,int y) { return !getWorld().getObjectsAt(x,y,Person.class).isEmpty(); } public boolean isAnotherPersonAt(int x,int y) { return getWorld().getObjectsAt(x,y,Person.class).size()>1; } public boolean isBuildingAt(int x,int y) { return !getWorld().getObjectsAt(x,y,Building.class).isEmpty(); }

Show Your Code #3

1. Monochrome Filter - In the Dot scenario, call the populateRandom() method. Write a method that when called on a Dot, all Dots with that color will be removed from the board. You should not worry about having this happen while running the scenario.

public void removeSameColor() { World w=getWorld(); List<Dot> dots=w.getObjects(Dot.class); for(int i=0; i<dots.size(); i++) { Dot d=dots.get(i); if(d.color.equals(color)) { w.removeObject(d); } } }

2. Ripple Effect - In the Dot scenario, call the populateBlue() method. Using this grid of blue Dots, write a method that makes all Dots around the one this method is called on change colors (if blue, make it red and vice versa). This method should take an integer argument for the radius of this effect. You should not worry about having this happen while running the scenario.

public void ripple(int radius) { World w=getWorld(); List<Dot> dots=w.getObjects(Dot.class); for(int i=0; i<dots.size(); i++) { Dot d=dots.get(i); int dx=getX()-d.getX(); int dy=getY()-d.getY(); if(dx*dx+dy*dy<=radius*radius) { if(d.color.equals("blue")) { d.color="red"; d.setImage("button-red.png"); } else { d.color="blue"; d.setImage("button-blue.png"); } } } }

3. Random Rat Race - In the Maze scenario, create a Mouse that starts at coordinates (1,0) and walks around randomly until it finds the Cheese, at which point it stops. The trick is that it isn't allowed to move diagonally or step on walls. Also include a method, int getSteps(), that reports how many steps were taken.

public void act() { if(getWorld().getObjectsAt(getX(),getY(),Cheese.class).size()>0) { return; } int dir=Greenfoot.getRandomNumber(4); if(dir==0) { move(0,-1); } if(dir==1) { move(1,0); } if(dir==2) { move(0,1); } if(dir==3) { move(-1,0); } } public void move(int dx,int dy) { int x=getX()+dx; int y=getY()+dy; if(getWorld().getObjectsAt(x,y,Wall.class).size()==0 && x>=0 && x<getWorld().getWidth() && y>=0 && y<getWorld().getHeight()) { setLocation(x,y); numSteps++; } } public int getNumSteps() { return numSteps; } private int numSteps=0;

4. Controlled Rat Race - This is the same as option 3, but instead of having the mouse roam randomly, have its motion controlled by the user with the arrow keys.

public void act() { if(getWorld().getObjectsAt(getX(),getY(),Cheese.class).size()>0) { return; } if(Greenfoot.isKeyDown("up")) { move(0,-1); } if(Greenfoot.isKeyDown("right")) { move(1,0); } if(Greenfoot.isKeyDown("down")) { move(0,1); } if(Greenfoot.isKeyDown("left")) { move(-1,0); } } public void move(int dx,int dy) { int x=getX()+dx; int y=getY()+dy; if(getWorld().getObjectsAt(x,y,Wall.class).size()==0 && x>=0 && x<getWorld().getWidth() && y>=0 && y<getWorld().getHeight()) { setLocation(x,y); numSteps++; } } public int getNumSteps() { return numSteps; } private int numSteps=0;

Show Your Code #4

1. Checker Board - Using the dots scenario from the last interclass problem, add a method to the board called checkerboard. It should be called after you call either populateRandom() or populateBlue(). It should remove dots so as to make them form a checker board pattern.

public void checkerBoard() { List<Dot> dots=getObjects(Dot.class); for(int i=0; i<dots.size(); i++) { Dot d=dots.get(i); if((d.getX()+d.getY())%2==0) { removeObject(d); } } }

2. Path Walk - For this problem you will use the FoodGrab scenario. The Lemur class in this scenario has an integer array in it called pathDir. This gives a series of numbers between 0 and 3 inclusive. These are meant to be directions with zero being up, one being right, two being down, and three being left. Make your lemur so that is it takes steps in the direction specified, in the order specified. When it runs out of numbers in the array it should start back at the beginning. (So the first time act is called you have it take a step in the direction of the first number in the array. The second time act is called you step in the direction of the second number and so on.)

public void act() { int[] xoff={0,1,0,-1}; int[] yoff={-1,0,1,0}; setLocation(getX()+xoff[pathDir[step]],getY()+yoff[pathDir[step]]); step=(step+1)%pathDir.length; } private int step=0;

3. Collecting Food - For this problem you will use the FoodGrab scenario. This scenario has a lemur, food, and a tree that the lemur calls home. Each food object has a method called getAmout() that tells you how much food is there. Make the lemur go to each food starting with the one with the largest amount and ending with the one with the smallest amount. Each time the lemur gets to a food, remove that food from the world.

public void act() { stepTowardMostFood(); } public void stepTowardMostFood() { List<Food> allFood=getWorld().getObjects(Food.class); Food bigFood=null; for(int i=0; i<allFood.size(); i++) { Food f=allFood.get(i); if(bigFood==null || f.getAmount()>bigFood.getAmount()) { bigFood=f; } } if(bigFood!=null) { stepToward(bigFood.getX(),bigFood.getY()); if(getX()==bigFood.getX() && getY()==bigFood.getY()) { getWorld().removeObject(bigFood); } } } public void move(int dx,int dy) { setLocation(getX()+dx,getY()+dy); } public void stepToward(int px,int py) { int dx=px-getX(); int dy=py-getY(); if(dx!=0) { dx=dx/Math.abs(dx); } if(dy!=0) { dy=dy/Math.abs(dy); } move(dx,dy); }

4. Bring Home the Bacon - This is for people looking for a bit more of a challenge. You do #3, but with an added twist. After the Lemur picks up a food item has it walk back to its home before going to get the next food item.

public void act() { if(hasFood) { stepTowardHome(); } else { stepTowardMostFood(); } } public void stepTowardHome() { List<Home> homes=getWorld().getObjects(Home.class); Home h=homes.get(0); stepToward(h.getX(),h.getY()); if(getX()==h.getX() && getY()==h.getY()) { hasFood=false; } } public void stepTowardMostFood() { List<Food> allFood=getWorld().getObjects(Food.class); Food bigFood=null; for(int i=0; i<allFood.size(); i++) { Food f=allFood.get(i); if(bigFood==null || f.getAmount()>bigFood.getAmount()) { bigFood=f; } } if(bigFood!=null) { stepToward(bigFood.getX(),bigFood.getY()); if(getX()==bigFood.getX() && getY()==bigFood.getY()) { getWorld().removeObject(bigFood); hasFood=true; } } } public void move(int dx,int dy) { setLocation(getX()+dx,getY()+dy); } public void stepToward(int px,int py) { int dx=px-getX(); int dy=py-getY(); if(dx!=0) { dx=dx/Math.abs(dx); } if(dy!=0) { dy=dy/Math.abs(dy); } move(dx,dy); } private boolean hasFood=false;

5. Mouse Chase - Modify the act method of an actor so that it will chase the mouse around. The actor shouldn't move more than one square at a time. If it if on the same square as the mouse is should just sit there.

public void act() { MouseInfo mi=Greenfoot.getMouseInfo(); int mx=mi.getX(); int my=mi.getY(); if(mx>getX()) { setLocation(getX()+1,getY()); } else if(mx<getX()) { setLocation(getX()-1,getY()); } if(my>getY()) { setLocation(getX(),getY()+1); } else if(my<getY()) { setLocation(getX(),getY()-1); } }

Show Your Code #5

1. Shape Drawing - Using your new found skills with GreenfootImage, I want you to draw something interesting. It needs to involve several shapes and different colors. Have your drawing as the image for an actor so that it can be moved around the world.

/** * The code for this can vary depending on what you draw. What all * solutions will have in common is the calls to getImage, setColor, * and then some fill or draw methods. */ public void changeImage() { GreenfootImage img=getImage(); img.setColor(Color.white); img.fillRect(0,0,img.getWidth(),img.getHeight()); img.setColor(Color.red); img.fillOval(0,0,20,20); }

2. Polygons - Write a method called drawRegularPolygon(int n) in a World class. It should draw an n-sided regular polygon. So if you pass it 4 you get a square. If you pass 8 you will get a regular octagon. (Note that you will probably want to use Math.sin() and Math.cos() to do this.)

public void drawRegularPolygon(int n) { GreenfootImage img=getBackground(); int[] x=new int[n]; int[] y=new int[n]; for(int i=0; i<n; i++) { x[i]=100+(int)(100*Math.cos(i*2*Math.PI/n)); y[i]=100+(int)(100*Math.sin(i*2*Math.PI/n)); } img.setColor(Color.black); img.fillPolygon(x,y,n); setBackground(img); }

3. Making Change - Write a method called makeChange(int cents). When you call this method you pass how many cents you want to make change for. It should print out how many quarters, dimes, nickels, and pennies are needed to make change. The trick is that you want as few coins as possible. Assume you have unlimited change for doing this.

public void makeChange(int cents) { int q=cents/25; cents=cents%25; int d=cents/10; cents=cents%10; int n=cents/5; cents=cents%5; int p=cents; System.out.println(q+" "+d+" "+n+" "+p); }

4. Mouse Drawing - Write code in the act method of a world class to make it so that the user can draw something with the mouse. I leave it up to you to decide what gets drawn. To do the drawing you should modify the GreenfootImage for the world class. Note that you can get and set that image with getBackground and setBackground.

public class DrawWorld extends World { private int lx; private int ly; /** * Constructor for objects of class DrawWorld. * */ public DrawWorld() { super(600, 600, 1); setBackground(new GreenfootImage(600,600)); } public void act() { MouseInfo mi=Greenfoot.getMouseInfo(); if(mi!=null) { GreenfootImage img=getBackground(); img.drawLine(lx,ly,mi.getX(),mi.getY()); lx=mi.getX(); ly=mi.getY(); } } }

Show Your Code #6

1. Text Counting - For the spreadsheet we learned how to read text files. In that case we wanted to bring in a CSV file because they are good for spreadsheet type data. For this I want you to add two methods to the Spreadsheet class. Both are simpler than reading a CSV file but will test your ability to read files. The two methods are int countLines(String fileName) and int countWords(String fileName). They shoud pretty much do what their names imply. The string that gets passed in is the name of the file you want to read.

public int countLines(String fileName) { int ret=0; try { Scanner sc=new Scanner(new File(fileName)); while(sc.hasNextLine()) { sc.nextLine(); ret=ret+1; } sc.close(); } catch(FileNotFoundException e) { e.printStackTrace(); } return ret; } public int countWords(String fileName) { int ret=0; try { Scanner sc=new Scanner(new File(fileName)); while(sc.hasNext()) { sc.next(); ret=ret+1; } sc.close(); } catch(FileNotFoundException e) { e.printStackTrace(); } return ret; }

2. Business Decisions - This problem has you working with this CSV file. This is for a spreadsheet with five columns and each one has 15 rows. The first four columns are numbers of items sold of each of four different types. The last column is total sales. I want you to write a method that returns the average of total sales for those entries where the value in one column is larger than another. The method will take two parameters that are column numbers. You only average costs where the first column has a larger value than the second column.

public double averageWhenLarger(int c1,int c2) { double sum=0,cnt=0; for(int i=0; i<table.maxRows(); i++) { if(table.get(i,c1)<table.get(i,c2)) { sum=sum+table.get(i,4); cnt++; } } return sum/cnt; }

3. Standard Deviation - Put in a method that will calculate the standard deviation of the values in a column. The standard deviation, also called the root-mean square, is the square root of the means of the squares of the deviations of the values from the average. To find it you first find the average, then run back through the values and add up the squares of the deviations. If the average is ave, the deviation of x is (x-ave) and you want to add up (x-ave)*(x-ave) for all the x values in the column. Once you have that sum you divide by the number of elements and take the square root of that using Math.sqrt(). Your code for this can be written so that it doesn't allow blanks in the column.

public double average(int col) { double sum=0; double cnt=0; for(int i=0; i<table.maxRows(); i++) { if(table.hasData(i,col)) { sum=sum+table.get(i,col); cnt=cnt+1; } } return sum/cnt; } public double standardDeviation(int col) { double sum=0; double cnt=0; double avg=average(col); for(int i=0; i<table.maxRows(); i++) { if(table.hasData(i,col)) { double diff=table.get(i,col)-avg; sum=sum+diff*diff; cnt=cnt+1; } } return Math.sqrt(sum/cnt); }

4. Median - Write a method that will return the median of the values in a column. You can write it so that it doesn't allow blanks. The easiest way to do this is to sort the values and then pick the one in the middle. If you get all the values into an array you can sort them using java.util.Arrays.sort. (Call Arrays.sort after you have imported java.util.*.) So this method should make an array of doubles (double[]) and put values in it, then pass that to Arrays.sort and return the middle value in the array.

public double median(int col) { double[] vals=new double[table.maxRows()]; for(int i=0; i<vals.length; i++) { vals[i]=table.get(i,col); } Arrays.sort(vals); return vals[vals.length/2]; }

5. Ascending Order - For this I want you to write a method that will sort the values in a column and put them back in ascending order. This code does not have to work with blank elements. Use the sort method described above to sort an array of values, then use the set method to put them back into the table. After you have done that call renderTable() so that the new numbers show up.

public void ascendingOrder(int col) { double[] vals=new double[table.maxRows()]; for(int i=0; i<vals.length; i++) { vals[i]=table.get(i,col); } Arrays.sort(vals); for(int i=0; i<vals.length; i++) { table.set(i,col,vals[i]); } renderTable(); }

Show Your Code #7

1. Drawing - Using JavaFX and classes in the javafx.scene.shapes package, draw something interesting. Remember that there is a directory called CSCI1311-S17 in the in class code that has what we did in class using JavaFX.

import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.shape.Arc; import javafx.scene.shape.ArcType; import javafx.scene.shape.Circle; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class Drawing extends Application { public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); Rectangle face = new Rectangle(100,100,400,400); face.setFill(Color.YELLOW); Circle lEye = new Circle(200,200,50); lEye.setFill(Color.BLACK); Circle rEye = new Circle(400,200,50); rEye.setFill(Color.BLACK); Rectangle mouth = new Rectangle(200,300,200,100); mouth.setFill(Color.BLACK); Arc wink = new Arc(400, 200, 75, 40, 225, 90); wink.setType(ArcType.OPEN); wink.setStroke(Color.BLACK); wink.setFill(null); wink.setStrokeWidth(3); scene.setOnMousePressed(event -> { group.getChildren().remove(rEye); group.getChildren().add(wink); }); scene.setOnMouseReleased(event -> { group.getChildren().remove(wink); group.getChildren().add(rEye); }); group.getChildren().addAll(face,lEye,rEye,mouth); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

2. Business Decisions - This problem has you working with this CSV file. This is for a spreadsheet with five columns and each one has 15 rows. The first four columns are numbers of items sold of each of four different types. The last column is total sales. I want you to write a method that returns the average of total sales for those entries where the value in one column is larger than another. The method will take two parameters that are column numbers. You only average costs where the first column has a larger value than the second column.

public double businessDecisions(int c1,int c2) { int sales = 0; int count = 0; for(int r=0; r<15; r++) { if(table.get(r,c1)>table.get(r,c2)) { sales = sales + table.get(r,4); count++; } } return salesCount/count; }

3. Temps By Year - For this problem you will deal with a weather CSV file. I want to know the average year for the ten warmest days and the ten days months. To help you figure out how to do this I would note that it is rare for there to be ties in the temperature of these extreme months.

public int tempsByYear() { List years = new ArrayList<>(); List temps = new ArrayList<>(); for(int i=0; i tempsByMonth() { List months = new ArrayList<>(); List temps = new ArrayList<>(); for(int i=0; i

4. Excel Style Indexing - In excel you can specify cells with things like b5 and ranges of cells with a1:d4. Write code that will do a sum and takes a string argument in the Excel style. To help with this I will note that the expression c-'a' where c is a char type will give you the numeric position of a lowercase letter in the alphabet.

public double excelSyleIndexing(String s) { String fst = s.substring(0,s.indexOf(':')); String snd = s.substring(s.indexOf(':')+1,s.length()); double sum = 0; for(int i=Integer.parseInt(fst.substring(1,fst.length())); i < Integer.parseInt(snd.substring(1,snd.length())); i++) { for(int j=(fst.charAt(0)-'a'); j <= (snd.charAt(0)-'a'); j++) { sum = sum + table.get(i,j); } } return sum; }

Show Your Code #8

1. Follow the Mouse - Make a JavaFX application where a simple geometric shape follows the mouse around. Note that I don't want it to be at the location of the mouse for this as we did that in class. Instead, I want it to move from where it is toward the location of the mouse. This works best with an AnimationTimer.

import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; public class FollowTheMouse extends Application { double mx = 300; double my = 300; int circleSpeed = 30; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); Circle circle = new Circle(); circle.setTranslateX(290); circle.setTranslateY(290); circle.setRadius(20); circle.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(circle); scene.setOnMouseMoved(event -> { mx = event.getX(); my = event.getY(); }); AnimationTimer timer = new AnimationTimer() { long then = 0L; public void handle(long now) { double delay = (now - then) / 1e9; if (delay < 1) { if(mx < circle.getTranslateX()) { circle.setTranslateX(circle.getTranslateX()-circleSpeed*delay); } else if(mx>circle.getTranslateX()) { circle.setTranslateX(circle.getTranslateX()+circleSpeed*delay); } if(mycircle.getTranslateY()){ circle.setTranslateY(circle.getTranslateY()+circleSpeed*delay); } } then = now; } }; timer.start(); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

2. Keyboard Control - Make a JavaFX application that has a simple geometric shape that moves around when you press keys. We did this in a basic way in class, but that didn't allow diagonal motion. To enable diagonal motion, you make four boolean variables that tell you if a key is being held down. In setKeyPressed you would set the appropriate boolean to true (something like upPressed = true; if you named your variable upPressed). In setKeyReleased you would set it back to false. In the AnimationTimer, you have if statements that check those boolean variables and actually move the shape around.

import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.input.KeyCode; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; public class KeyboardControl extends Application { boolean upPressed = false; boolean downPressed = false; boolean rightPressed = false; boolean leftPressed = false; int circleSpeed = 100; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); Circle circle = new Circle(); circle.setTranslateX(290); circle.setTranslateY(290); circle.setRadius(20); circle.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(circle); scene.setOnKeyPressed(event -> { if(event.getCode()==KeyCode.UP) upPressed = true; if(event.getCode()==KeyCode.RIGHT) rightPressed = true; if(event.getCode()==KeyCode.DOWN) downPressed = true; if(event.getCode()==KeyCode.LEFT) leftPressed = true; }); scene.setOnKeyReleased(event -> { if(event.getCode()==KeyCode.UP) upPressed = false; if(event.getCode()==KeyCode.RIGHT) rightPressed = false; if(event.getCode()==KeyCode.DOWN) downPressed = false; if(event.getCode()==KeyCode.LEFT) leftPressed = false; }); AnimationTimer timer = new AnimationTimer() { long then = 0L; public void handle(long now) { double delay = (now - then) / 1e9; if (delay < 1) { if(upPressed) circle.setTranslateY(circle.getTranslateY()-circleSpeed*delay); if(downPressed) circle.setTranslateY(circle.getTranslateY()+circleSpeed*delay); if(rightPressed) circle.setTranslateX(circle.getTranslateX()+circleSpeed*delay); if(leftPressed) circle.setTranslateX(circle.getTranslateX()-circleSpeed*delay); } then = now; } }; timer.start(); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

3. Drawing Lines - Make an applet that allows the user to draw lines using the mouse. How exactly you do this up to you.

import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.shape.Line; import javafx.stage.Stage; public class DrawingLines extends Application { double mx = 300; double my = 300; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); scene.setOnMousePressed(event -> { mx = event.getX(); my = event.getY(); }); scene.setOnMouseReleased(event -> { Line line = new Line(mx,my,event.getX(),event.getY()); line.setStroke(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(line); }); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

Show Your Code #9

1. Bouncing Ball - Make an application that shows a ball bouncing. Use an AnimationTimer to perform the animation.

import javafx.scene.paint.Color; import javafx.scene.shape.Circle; public class BouncingBallCircle { private double vy = 0; private Circle circle; public BouncingBallCircle(double x_0,double y_0,int r) { circle = new Circle(); circle.setTranslateX(x_0); circle.setTranslateY(y_0); circle.setRadius(r); circle.setStroke(new Color(Math.random(),Math.random(),Math.random(),1.0)); circle.setFill(Color.WHITE); circle.setStrokeWidth(r/10); } public void move(double delay) { vy = vy + 10*delay; circle.setTranslateY(circle.getTranslateY()+vy*delay); if(circle.getTranslateY()<0 || circle.getTranslateY()>(600-circle.getRadius()*2)) { vy = vy*(-0.75); } } public Circle getCircle() { return circle; } } import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.stage.Stage; public class BouncingBall extends Application { public void start(Stage stage) { Group group = new Group(); BouncingBallCircle circle = new BouncingBallCircle(300, 300, 15); group.getChildren().add(circle.getCircle()); Scene scene = new Scene(group, 600, 600); AnimationTimer timer = new AnimationTimer() { long then = 0L; public void handle(long now) { double delay = (now - then) / 1e9; if (delay < 1) { circle.move(delay); } then = now; } }; timer.start(); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

2. Scrolling Text - Make an application that will scroll a line of text across from right to left. Once it gets off the edge on the left it should repeat. Use an AnimationTimer to perform the animation.

import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.stage.Stage; public class ScrollingText extends Application { int curr = 0; int scrollSpeed = 100; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); String textFill = "package ShowYourCode9; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.stage.Stage; public class ScrollingText extends Application { int curr = 0; int scrollSpeed = 100; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); String textFill = test text ; Text text = new Text(10, 50, textFill); text.setFont(new Font(scene.getHeight()/2)); text.setTranslateY(text.getTranslateY()+text.getLayoutBounds().getHeight()); group.getChildren().add(text); AnimationTimer timer = new AnimationTimer() { long then = 0L; public void handle(long now) { double delay = (now - then) / 1e9; if (delay < 1) { //text.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); if(text.getTranslateX()+text.getLayoutBounds().getWidth()<0) { text.setTranslateX(scene.getWidth()+1); } else { text.setTranslateX(text.getTranslateX()-delay*scrollSpeed); } } then = now; } }; timer.start(); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } } "; Text text = new Text(10, 50, textFill); text.setFont(new Font(scene.getHeight()/2)); text.setTranslateY(text.getTranslateY()+text.getLayoutBounds().getHeight()); group.getChildren().add(text); AnimationTimer timer = new AnimationTimer() { long then = 0L; public void handle(long now) { double delay = (now - then) / 1e9; if (delay < 1) { //text.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); if(text.getTranslateX()+text.getLayoutBounds().getWidth()<0) { text.setTranslateX(scene.getWidth()+1); } else { text.setTranslateX(text.getTranslateX()-delay*scrollSpeed); } } then = now; } }; timer.start(); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

3. Color Paint (keys) - For this I want you to write an application that "paints" when the mouse is clicked (if you want you can make it happen for dragging to). It can just draw a small rectangle or circle each time at the location of the mouse. The color it paints with will vary based on keys the user hits. You can decide what keys give what colors. For example, if the user hits the R key then it should start drawing in red.

import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.input.KeyCode; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.stage.Stage; public class ColorPaint extends Application { Color color = Color.BLACK; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); scene.setOnMouseClicked(event -> { Circle circle = new Circle(event.getX(),event.getY(), 5, color); circle.setFill(color); group.getChildren().add(circle); }); scene.setOnMouseDragged(event -> { Circle circle = new Circle(event.getX(),event.getY(), 5, color); circle.setFill(color); group.getChildren().add(circle); }); scene.setOnKeyPressed(event -> { if(event.getCode()==KeyCode.R) { color = Color.RED; } else if(event.getCode()==KeyCode.O) { color = Color.ORANGE; } else if(event.getCode()==KeyCode.Y) { color = Color.YELLOW; } else if(event.getCode()==KeyCode.G) { color = Color.GREEN; } else if(event.getCode()==KeyCode.B) { color = Color.BLUE; } else if(event.getCode()==KeyCode.V) { color = Color.VIOLET; } else { color = new Color(Math.random(),Math.random(),Math.random(),1.0); } }); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

4. Shape Painting (keys) - This is just like the previous problem except that instead of varying what color is painted, the user can change what shape is painted. At the very least you should have a square and a circle as options. So if the user hits S then the clicks draw squares. If they hit C it draws circles. Rectangles and ovals would be simple to implement as well, but aren't required.

import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.input.KeyCode; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.shape.Ellipse; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; public class ShapePainting extends Application { String shape = "S"; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); scene.setOnMouseClicked(event -> { if(shape=="S") { double rand = Math.random()*10+10; Rectangle rect = new Rectangle(event.getX()-rand/2,event.getY()-rand/2,rand,rand); rect.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(rect); } else if(shape=="O") { Ellipse el = new Ellipse(event.getX(),event.getY(),Math.random()*10+10,Math.random()*10+10); el.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(el); } else if(shape=="C") { Circle circle = new Circle(event.getX(),event.getY(),Math.random()*10+10); circle.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(circle); } else { double randWidth = Math.random()*10+10; double randHeight = Math.random()*10+10; Rectangle rect = new Rectangle(event.getX()-randWidth/2,event.getY()-randHeight/2,randWidth,randHeight); rect.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(rect); } }); scene.setOnMouseDragged(event -> { if(shape=="S") { double rand = Math.random()*10+10; Rectangle rect = new Rectangle(event.getX()-rand/2,event.getY()-rand/2,rand,rand); rect.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(rect); } else if(shape=="O") { Ellipse el = new Ellipse(event.getX(),event.getY(),Math.random()*10+10,Math.random()*10+10); el.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(el); } else if(shape=="C") { Circle circle = new Circle(event.getX(),event.getY(),Math.random()*10+10); circle.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(circle); } else { double randWidth = Math.random()*10+10; double randHeight = Math.random()*10+10; Rectangle rect = new Rectangle(event.getX()-randWidth/2,event.getY()-randHeight/2,randWidth,randHeight); rect.setFill(new Color(Math.random(),Math.random(),Math.random(),1.0)); group.getChildren().add(rect); } }); scene.setOnKeyPressed(event -> { if(event.getCode()==KeyCode.S) { shape = "S"; } else if(event.getCode()==KeyCode.O) { shape = "O"; } else if(event.getCode()==KeyCode.C) { shape = "C"; } else if(event.getCode()==KeyCode.R) { shape = "R"; } }); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

Show Your Code #10

1. Plotting Data - Find a data file with data that you find interesting (not what we did in class). Make a JavaFX chart that displays the data from that file.

import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class PlottingData extends Application { public int totalPaintsBySeason(List lst,int n) { int retSeason = 0; for(int i=0; i data = new ArrayList<>(); try { Scanner sc = new Scanner(new File("elements-by-episode.csv")); sc.nextLine(); while(sc.hasNext()) { data.add(new PlottingDataInfo(sc.nextLine())); } sc.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } NumberAxis xAxis = new NumberAxis(1,31,1); xAxis.setLabel("Season"); NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Number of Paints"); LineChart lineChart = new LineChart(xAxis,yAxis); lineChart.setTitle("Number of Paints Used by Season"); XYChart.Series series = new XYChart.Series(); series.setName("Number of Paints Used"); for(int i=1; i<32; i++) { series.getData().add(new XYChart.Data(i, totalPaintsBySeason(data,i))); } Scene scene = new Scene(lineChart,800,600); lineChart.getData().add(series); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } } import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class PlottingData extends Application { public int totalPaintsBySeason(List lst,int n) { int retSeason = 0; for(int i=0; i data = new ArrayList<>(); try { Scanner sc = new Scanner(new File("elements-by-episode.csv")); sc.nextLine(); while(sc.hasNext()) { data.add(new PlottingDataInfo(sc.nextLine())); } sc.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } NumberAxis xAxis = new NumberAxis(1,31,1); xAxis.setLabel("Season"); NumberAxis yAxis = new NumberAxis(); yAxis.setLabel("Number of Paints"); LineChart lineChart = new LineChart(xAxis,yAxis); lineChart.setTitle("Number of Paints Used by Season"); XYChart.Series series = new XYChart.Series(); series.setName("Number of Paints Used"); for(int i=1; i<32; i++) { series.getData().add(new XYChart.Data(i, totalPaintsBySeason(data,i))); } Scene scene = new Scene(lineChart,800,600); lineChart.getData().add(series); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

2. Moon Lander - There is a simple game called Moon Lander where a lander is falling toward a surface, accelerating with gravity. The user can fire thrusters with a key that push against gravity. If the lander hits the surface moving too fast, player loses. If it hits slowly enough, they win. Write this game using JavaFX.

import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.input.KeyCode; import javafx.stage.Stage; public class MoonLander extends Application { boolean falling = true; double threshold = 15.0; public void start(Stage stage) { Group group = new Group(); Scene scene = new Scene(group, 600, 600); MoonLanderLander lander = new MoonLanderLander(300,-20); group.getChildren().add(lander.getImageView()); scene.setOnKeyPressed(event -> { if(event.getCode() == KeyCode.SPACE) { falling = false; } }); scene.setOnKeyReleased(event -> { if(event.getCode() == KeyCode.SPACE) { falling = true; } }); AnimationTimer timer = new AnimationTimer() { long then = 0L; public void handle(long now) { double delay = (now - then) / 1e9; if (delay < 1) { if(falling) { lander.moveDown(delay); } else { lander.moveUp(delay); } if(lander.getY()+lander.getHeight() >= scene.getHeight()) { stop(); if(lander.getVY() < threshold) { System.out.println("Success!"); } else { System.out.println("Failure."); } } } then = now; } }; timer.start(); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } } import javafx.scene.image.Image; import javafx.scene.image.ImageView; public class MoonLanderLander { private Image landerImg; private ImageView lander; private double vy = 0; public MoonLanderLander(double x_0,double y_0) { landerImg = new Image("/lander.png",40,50,false,false); lander = new ImageView(landerImg); lander.setTranslateX(x_0-(landerImg.getWidth()/2)); lander.setTranslateY(y_0-(landerImg.getHeight()/2)); } public void moveUp(double delay) { vy = vy - 10*delay; lander.setTranslateY(lander.getTranslateY() + vy*delay); } public void moveDown(double delay) { vy = vy + 10*delay; lander.setTranslateY(lander.getTranslateY() + vy*delay); } public ImageView getImageView() { return lander; } public double getY() { return lander.getTranslateY(); } public double getVY() { return vy; } public double getHeight() { return landerImg.getHeight(); } }

3. Bouncing Balls - Write a program where you have two or more balls (2D or 3D) that bounce off of one another.

import javafx.scene.paint.Color; import javafx.scene.shape.Circle; public class BouncingBallsCircle { private double vx = Math.random()*40-20; private double vy = Math.random()*40-20; private Circle circle; public BouncingBallsCircle(double x_0,double y_0,int r) { circle = new Circle(); circle.setTranslateX(x_0); circle.setTranslateY(y_0); circle.setRadius(r); circle.setStroke(new Color(Math.random(),Math.random(),Math.random(),1.0)); circle.setFill(Color.WHITE); circle.setStrokeWidth(r/10); } public void move(double delay) { circle.setTranslateX(circle.getTranslateX()+vx*delay); circle.setTranslateY(circle.getTranslateY()+vy*delay); if(circle.getTranslateX()<0 || circle.getTranslateX()>(600-circle.getRadius()*2)) { vx = vx*(-1); } if(circle.getTranslateY()<0 || circle.getTranslateY()>(600-circle.getRadius()*2)) { vy = vy*(-1); } } public double distanceTo(BouncingBallsCircle other) { double dx = circle.getTranslateX() - other.circle.getTranslateX(); double dy = circle.getTranslateY() - other.circle.getTranslateY(); return Math.sqrt(dx * dx + dy * dy); } public void rebound(double delay) { vx = vx*(-1); vy = vy*(-1); move(delay); move(delay); move(delay); } public Circle getCircle() { return circle; } public double getRadius() { return circle.getRadius(); } } import java.util.ArrayList; import java.util.List; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.PerspectiveCamera; import javafx.scene.PointLight; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.stage.Stage; public class BouncingBalls extends Application { public void start(Stage stage) { Group group = new Group(); List circles = new ArrayList<>(); List circlesToAdd = new ArrayList<>(); BouncingBallsCircle circle2 = new BouncingBallsCircle(300, 300, 15); circles.add(circle2); group.getChildren().add(circle2.getCircle()); PointLight light1 = new PointLight(Color.BISQUE); light1.setTranslateX(500); light1.setTranslateY(50); PointLight light2 = new PointLight(Color.RED); light2.setTranslateX(50); light2.setTranslateY(500); light2.setTranslateZ(-120); PerspectiveCamera camera = new PerspectiveCamera(); group.getChildren().add(camera); group.getChildren().add(light1); group.getChildren().add(light2); Scene scene = new Scene(group, 600, 600); scene.setOnMouseMoved(event -> { light2.setTranslateX(event.getX()); light2.setTranslateY(event.getY()); }); scene.setOnMouseClicked(event -> { int rand = (int) (Math.random() * 10 + 10); BouncingBallsCircle circle = new BouncingBallsCircle(event.getX() - (rand / 2), event.getY() - (rand / 2), rand); circlesToAdd.add(circle); group.getChildren().add(circle.getCircle()); }); AnimationTimer timer = new AnimationTimer() { long then = 0L; public void handle(long now) { double delay = (now - then) / 1e9; if (delay < 1) { circles.addAll(circlesToAdd); circlesToAdd.clear(); for (BouncingBallsCircle circle : circles) { circle.move(delay); } for (int i = 0; i < circles.size(); i++) { for (int j = i+1; j < circles.size(); j++) { BouncingBallsCircle ci = circles.get(i); BouncingBallsCircle cj = circles.get(j); if(ci.distanceTo(cj) < (ci.getRadius() + cj.getRadius())) { ci.rebound(delay); cj.rebound(delay); } } } } then = now; } }; timer.start(); scene.setCamera(camera); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }

4. Tic-Tac-Toe - Write a game of tic-tac-toe using JavaFX graphics.

import java.util.ArrayList; import java.util.List; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.stage.Stage; public class TicTacToe extends Application { String currPlayer = "X"; int numClicked = 0; public void start(Stage stage) { Group group = new Group(); List> buttons = new ArrayList<>(); for(int i=0; i<3; i++) { List tmp = new ArrayList<>(); for(int j=0; j<3; j++) { Button button = new Button(); button.setOnAction(event -> { if(button.getText()=="") { button.setText(currPlayer); if(currPlayer=="X") { currPlayer="O"; } else { currPlayer="X"; } numClicked++; } }); button.setTranslateX(100*i); button.setTranslateY(100*j); button.setPrefSize(100, 100); group.getChildren().add(button); tmp.add(button); } buttons.add(tmp); } Scene scene = new Scene(group, 300, 300); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }