Iteration Looping in Java Tedious A better way

Iteration Looping in Java

Tedious…

A better way • public void lines(int how. Many) { for(int count. So. Far = 0; count. So. Far < how. Many; count. So. Far++) { System. out. println(“I will not mock Mrs. Dumbface”); } } • public void lines(int how. Many) { int count. So. Far = 0; while(count. So. Far < how. Many) { System. out. println(“I will not mock Mrs. Dumbface”); count. So. Far++; } }

for • for-loops are a good starting point for new programmers • They have a place holder for all 3 necessary pieces of any loop ▫ for(initial condition; continue condition; update condition) { //code to repeat }

while • while-loops are another common syntax we will use but they only require a condition to continue looping ▫ You must initialize and update the values elsewhere ▫ while(condition) { //code to repeat }

for vs. while • They are equivalent with a little bit of rearranging ▫ I will not force you to use one kind of loop but you must try using both in this first unit ▫ ▫ for(initial condition; continue condition; update condition) { //code to repeat } initial condition; while(continue condition) { //code to repeat update condition; }

Task #1 – Initializing the world Enemy one = new Enemy(); int random. X = (int)(Math. random()*get. Width()); int random. Y = (int)(Math. random()*get. Height()); add. Object(one, random. X, random. Y); Enemy two = new Enemy(); random. X = (int)(Math. random()*get. Width()); random. Y = (int)(Math. random()*get. Height()); add. Object(two, random. X, random. Y); Enemy three = new Enemy(); random. X = (int)(Math. random()*get. Width()); random. Y = (int)(Math. random()*get. Height()); add. Object(three, random. X, random. Y); …

Copy/Paste • • Remember, this is your first clue that there is a better way to write your code. In this case the repetition should be looped public void add. Enemies() { for(int added = 0; added < 3; added++) { Enemy e = new Enemy(); int random. X = (int)(Math. random()*get. Width()); int random. Y = (int)(Math. random()*get. Height()); add. Object(e, random. X, random. Y); } } public void add. Enemies() { int added = 0; while(added < 3) { Enemy e = new Enemy(); int random. X = (int)(Math. random()*get. Width()); int random. Y = (int)(Math. random()*get. Height()); add. Object(e, random. X, random. Y); added++; } }

add. Enemies • We can do better… • In particular we should at least make this method: ▫ public void add. Enemies(int n) • I’ve done that in my project. • I’ll show you what the finished product looks like

Task #2 – super weapon • I would like Mario to fire many rounds with one key stroke ▫ A loop • I’ll call this the “panic” weapon ▫ When I push the “w” key Mario will shoot fireballs in a wall protect him.

Task #2 – super weapon

Fireball no - loop public void panic. Wall() { //shoot 5 Fireballs int x = get. X(); int y = get. Y(); int fb. X= x + 30; World level = get. World(); int spacing = 10; int fb. Y = y – 4*spacing; //top Fireball level. add. Object(new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_), fb. X, fb. Y); fb. Y += 2*spacing; }

We can do better with a loop • The same method could be made (with a fixed number of Fireballs) • Or we could make a better one: ▫ public void panic. Wall(int n) • There is no “right” answer about where the Fireballs should be placed when the number is arbitrary. ▫ If you write good code it will be easy to change if you want to later on • I’ll show you my finished example… but not my code

Task #2 – super weapon • Instead of a wall, I could also enclose Mario in a ring of (protective) fire

Fireball no - loop public void panic. Circle() { //shoot 8 Fireballs int x = get. X(); int y = get. Y(); int change = 360/8; //angle between adjacent Fireballs int current. Angle = 0; World level = get. World(); Fireball fb 4 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); fb 4. set. Rotation(current. Angle); level. add. Object(fb 4, x, y); current. Angle += change; Fireball fb 5 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); fb 5. set. Rotation(current. Angle); level. add. Object(fb 5, x, y); Fireball fb 1 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); current. Angle += change; fb 1. set. Rotation(current. Angle); Fireball fb 6 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); level. add. Object(fb 1, x, y); fb 6. set. Rotation(current. Angle); level. add. Object(fb 6, x, y); current. Angle += change; Fireball fb 2 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); Fireball fb 7 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); fb 2. set. Rotation(current. Angle); fb 7. set. Rotation(current. Angle); level. add. Object(fb 7, x, y); level. add. Object(fb 2, x, y); current. Angle += change; Fireball fb 3 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); fb 3. set. Rotation(current. Angle); level. add. Object(fb 3, x, y); current. Angle += change; Fireball fb 8 = new Fireball(fb. Strength_, speed_ + 1, shooting. Dist_); fb 8. set. Rotation(current. Angle); level. add. Object(fb 8, x, y); current. Angle += change; }

We can do better with a loop • The same method could be made (with a fixed number of Fireballs) • Or we could make a better one: ▫ public void panic. Circle(int n) • In this case the rotation can be adjusted from 45 degrees in my example by using n in the parameters • I’ll show you my finished example… but not my code

Precision • Something strange will happen when you try things like: ▫ public void panic. Circle(30) • To help exaggerate the problem, I’m going to demo a new method ▫ slow. Panic. Circle ▫ The only difference is the speed of the Fireballs is 1

Precision • Pixels are integers (int) but movement into locations is with decimal numbers • With a speed of 1, that means the movement of an Actor is limited to the adjacent cells: A • That means no matter what the angle, only 8 moves are possible ▫ If speed = 2 there would be 16 locations to choose

Real. Actor • I’ve made a helper class that behaves just like its parent, the Actor class but keeps track of its movement and rotation using decimal (double) values. • The values are stored as decimal numbers but every time the Actor is displayed on screen, it is an approximation to its actual location ▫ (2. 1, 3. 4) (2, 3) • I accomplish this by casting (as was done with Random numbers) • The source code is posted for you to review or use where you like

Other ideas • public void rain. Bomb(int n) ▫ rain. Bomb(10) would place 10 bombs across the top of the screen (evenly spaced) • public void rapid. Fire(int n) ▫ rapid. Fire(3) fires 3 rounds in a single instant. You can decide if they are on top of one another or have some spacing between them

The List Class • When we want to keep track of more than one item we use a container ▫ A container has a single location in memory but keeps track of many things for us • So far an array is the only container we’ve worked with. • Another common container is a List ▫ Like arrays, they are used in many languages • Lists don’t need to be a fixed size, they will manage their size at run time ▫ If more space is needed it will “grow”

Java Lists • There are many types of lists in Java ▫ All have advantages and disadvantages that experienced programmers use to improve their programs • There is one interface though that ALL of them implement List

Interfaces • An interface is not an Object you can create but instead gives you a way to interact with many Objects in a common way

List • Phones • • ▫ Keypad dial = new Keypad(); //? ▫ Keypad dial = new i. Phone(); ▫ Keypad dial = new Galaxy(); List my. List = new List(); //Error List my. List = new Array. List(); //OK List my. List = new Linked. List(); //OK These lists hold Objects ▫ You will have to cast the objects you get from them ▫ Enemy bad. Guy = (Enemy)my. List. get(0); • List<Enemy> my. List = new Array. List(); • List<Enemy> my. List = new Linked. List(); • These lists store Enemies ▫ No need to cast them ▫ Enemy bad. Guy = my. List. get(0);

Helpful List<TYPE> methods • In Greenfoot we will mostly use: ▫ size() ▫ is. Empty() ▫ get(int n) �Zero based like an array �First element is zero ▫ list. Iterator() �The most efficient way to traverse (look through) the List • In general, these are also used frequently with Lists: ▫ ▫ ▫ add(TYPE data) add(TYPE data, int index) remove(TYPE data) set(int index, TYPE data) to. Array()

List. Iterator • The List interface provides access to its items with a simple method called get ▫ for(int index = 0; index < my. List. size(); index++) { Enemy e = my. List. get(index); //do something with each Enemy } • Though on the surface its convenient, it can be horribly inefficient depending on the list implementation ▫ Linked. List vs Array. List

List. Iterator • A List. Iterator is another interface that “knows” how to traverse a List. • The reason it gets a whole other interface is because the best way to traverse depends on the type of List • The good news: ▫ You don’t need to worry about the implementation details of Lists or List. Iterators ▫ Knowing how to use the interface is good enough (for now)

List. Iterator • The most common methods we’ll use are: ▫ has. Next() �boolean to see if the traversal can find another item or is finished ▫ next() �gets the next item in the list and updates the iterator

Typical List Iteration import java. util. List; import java. util. List. Iterator; List<Enemy> bad. Guys = get. World(). get. Objects(Enemy. class); List. Iterator<Enemy> iter = bad. Guys. list. Iterator(); while( iter. has. Next() ) { Enemy next = iter. next(); //do something with this Enemy }

Why Lists? • Greenfoot’s World class has a mechanism to access all objects in a class ▫ World my. Level = get. World(); ▫ List<Enemy> all. Enemies = my. Level. get. Objects( Enemy. class ); • Greenfoot Actors can also look for Lists of other Actors ▫ ▫ get. Intersecting. Objects get. Neighbours get. Objects. At. Offset get. Objects. In. Range

Ideas - demo • bump. All(double strength) • forcefield(int radius) • freeze. All(int time) ▫ I added a method to the Paratroopa called freeze ▫ It uses a counter that won`t allow the Paratroopa to act until the counter has expired (<= 0) • magnet(int time) ▫ Pull up the Paratroopas close by �get. Objects. In. Range �turn. Towards magnet �move

The ever popular Platform… • Platform World can be made but they require loops • Until now we didn’t have this option. • Like our world, your World needs to enforce the law of gravity ▫ public static final int GRAVITY • The act() method of your World must call up all Actors and apply gravity to them ▫ There a few issues with this

Issue – Gravity vs None • We don’t want to move everything ▫ Ground or Objects like platforms are immune

Exploiting OOP in Java’s • OOP = Object Oriented Programming • I could program every Platform class separately and but that seems awfully tedious… ▫ Bad design • Instead I’ll make one class (parent) to describe what ALL platforms can do • Similarly I’ll make another class, Real. Mover, that describes all the Actors that gravity will effect

Setup in Greenfoot

Level act() apply. Gravity() public void apply. Gravity() { List<Real. Mover> movers = get. Objects(Real. Mover. class); List. Iterator<Real. Mover> iter = movers. list. Iterator(); while(iter. has. Next()) { Real. Mover next = iter. next(); next. apply. Force(0, GRAVITY); } }

Real. Mover • I’ve uploaded the source code for a Real. Mover to the website ▫ Adds a horizontal and vertical velocity (vector) ▫ Adds access to apply forces ▫ Checks for Platforms to see what movement is possible �Can’t go through ground �Can’t walk through blocks �. . . �All Platforms are simple a picture no code

Issue #3 • We aren’t going to apply the kind of sophistication to our code that professional enterprises like Microsoft, EA, etc. would ▫ There will be bugs but we may not see them • For example, if an Actor is falling too fast it may pass through a platform (we are only going to check for collisions after a move, not during)

Falling Through

Good Enough • Most of the time the issue won’t happen • One other solution is to have a TERMINAL_VELOCITY in your World • If you set the terminal velocity to be less than your thinnest platform this won’t happen

Another - Issue Stacking • We may wish to consider what happens when Actors are stacked that would normally fall • Here’s another place you could choose to write a loop

Gravity - Demo • First, I have to change a couple quick things: ▫ public class Mario extends Actor ▫ public class Mario extends Real. Mover • public void move() ▫ Movement is now dependent on physical forces �Can’t move horizontally unless touching ground �Can’t jump unless touching ground ▫ Mario, and any Actor that wants to be a Real. Mover will likely want to invoke the parent class �super. move()

Scrolling. World - Demo • I’ve uploaded another file for you to look at that can now scroll a background image larger than the window you display • To use it you’ll need to subclass the Scrolling. World with your own

How to. . . • Start by making the World the same size as the image itself ▫ In my case 1920 x 1080 • Place your Actors in the World • Shrink the window size to show a portion of the full image ▫ For the demo I’ll use 600 x 400 • In your World’s constructor you MUST set the main character so the Scrolling. World knows who to track • You can also set the buffer space which makes the world scroll

Your Turn • MINIMUM expectation is to become familiar with for/while loops • You must implement at least 5 new features (at least two must use a List/List. Iterator) to show you can now use this skill in your code ▫ I have given lots of example loops that you could choose from… that’s why I didn’t show you the finished code
- Slides: 45