Solutions are
marked in blue.
For each one of the exercises below part of the code for a solution is given. This code is meant to clarify the statement of the problem and at the same time give you a jumpstart on the exercise. You may if you want come up with an entirely different solution, that doesn't use the sample code that is made available to you but that would have similar I/O behaviour.
1. Object-Oriented Olympics
Write a program Olympics.java that simulates an Olympic
track and field event, a race between Carl Lewis and Ben Johnson.
In this simulation we take a snapshot every second. The program reports the
distance each athlete has managed to cover. Your simulation should run for 8
seconds. With each second the player will have moved a number of yards which
should be determined by rolling a fair dice (use the Math.random()
routine as discussed in class and as presented in lecture notes 4).
Here's a sample run of the program (one of many, the simulation is random):
It only resembles a backgammon game, but it's an athletic race.tucotuco.cs.indiana.edu% java Olympics Seconds elapsed: 1 Carl Lewis: advances 5 yards, reaches 5 yards. Ben Johnson: advances 3 yards, reaches 3 yards. Seconds elapsed: 2 Carl Lewis: advances 6 yards, reaches 11 yards. Ben Johnson: advances 6 yards, reaches 9 yards. Seconds elapsed: 3 Carl Lewis: advances 5 yards, reaches 16 yards. Ben Johnson: advances 3 yards, reaches 12 yards. Seconds elapsed: 4 Carl Lewis: advances 4 yards, reaches 20 yards. Ben Johnson: advances 2 yards, reaches 14 yards. Seconds elapsed: 5 Carl Lewis: advances 5 yards, reaches 25 yards. Ben Johnson: advances 5 yards, reaches 19 yards. Seconds elapsed: 6 Carl Lewis: advances 2 yards, reaches 27 yards. Ben Johnson: advances 6 yards, reaches 25 yards. Seconds elapsed: 7 Carl Lewis: advances 6 yards, reaches 33 yards. Ben Johnson: advances 2 yards, reaches 27 yards. Seconds elapsed: 8 Carl Lewis: advances 4 yards, reaches 37 yards. Ben Johnson: advances 6 yards, reaches 33 yards. tucotuco.cs.indiana.edu%
Here's part of the program to get you started.
Your job is to come up with a complete definition for the classtucotuco.cs.indiana.edu% cat Olympics.java
public class Olympics { public static void main(String[] args) { Runner a = new Runner(" Carl Lewis"); Runner b = new Runner("Ben Johnson"); for (int i = 1; i <= 8; i++) { System.out.println("Seconds elapsed: " + i); a.run(); b.run(); } } } class Runner { private String name; private int yards; Runner(String givenName) { name = givenName; yards = 0; } void run() { int leap; leap = (int)(Math.random() * 6 + 1); yards += leap; System.out.println(" " + name + ": advances " + leap + " yards, " + "reaches " + yards + " yards."); } }
Runner. Things to keep in mind:
Runner such as Carl Lewis or Ben Johnson, in our
abstract view here, has a name and has always covered
a certain number of yards (initially 0).
run method simulates a quantic way of running, more
like jumping. A dice is rolled and the jump is made. But this is only
because we look at the race only once every second, as if we were a radar
or stroboscope of some sort.
ints 2.1 Generating arrays.
Using the BreezyGUI package initialize an array of 8 elements
with random integers between -4 and 4. Show the array in a TextArea
window element. Print the sum of the elements in the array as well. Feel free
to modify the program below which does not do what the problem asks you to do
but that does have the required framework:
import java.awt.*;
import BreezyGUI.*;
public class Generate extends GBFrame {
Button button = addButton ("Click for new array!", 1, 1, 4, 1);
TextArea display = addTextArea( "", 2, 1, 3, 4);
int[] array = new int[8];
String output;
public void buttonClicked(Button buttonObj) {
output = "";
for (int i = 0; i < array.length; i++) {
// array[i] += i;
array[i] = (int)(Math.random() * 9) - 4;
output += array[i] + " ";
}
display.setText(output + "\nSum is: " + sum());
}
int sum () {
int runningSum;
for (int i = 0; i < array.length; i++) {
runningSum += array[i];
}
// return 0;
return runningSum;
}
public static void main(String[] args) {
Frame frm = new Generate();
frm.setSize(400, 200);
frm.setVisible(true);
}
}
You will need to change a few things before you make it work, but not many. Here are
a few questions to help you focus on what needs to be changed:
Every time you click button
button a new array is generated.
The values are initially equal to the indices because the array starts at
zero but with each push on the button the elements are changed. They are
changed by adding to each element the value of the index for it.
output
and how does the TextArea display the arrays?
This is explained in the text on pages 77-79
Each element changes, the value of its index in the array being added to its current value.
sum() supposed to return (as a value)?
An integer value.
Finding min and max
Use the program that you wrote above to calculate the largest and the smallest of the numbers in the arrays: instead of printing the sum of the elements in the array, report the largest, and the smallest, numbers in the array.
Here's the framework and part of it to get you started. (Be careful! Some parts of the program may look almost correct. Check the code carefully before using it.)
import java.awt.*;
import BreezyGUI.*;
public class Extremes extends GBFrame {
Button button = addButton ("Click for new array!", 1, 1, 4, 1);
TextArea display = addTextArea("" , 2, 1, 3, 4);
int[] array = new int[8];
String output;
public void buttonClicked(Button buttonObj) {
output = "";
for (int i = 0; i < array.length; i++) {
array[i] = (int)(Math.random() * 9) - 4;
// integers in [-4, 4] are generated this way...
output += array[i] + " ";
}
display.setText(output + "\nMin is: " + min()
+ "\nMax is: " + max());
}
int min () {
int aux = array[0];
for (int i = 0; i < array.length; i++) {
if (aux > array[i]) {
aux = array[i];
}
}
return aux;
}
int max () {
int aux = 0; // for the framework to compile
// ...
aux = array[0];
for (int i = 0; i < array.length; i++)
if (aux < array[i])
aux = array[i];
return aux;
}
public static void main(String[] args) {
Frame frm = new Extremes();
frm.setSize(400, 200);
frm.setVisible(true);
}
}
There was no mistake in the code per se, just an
encouragement to look at the code carefully anyway. Processing each element
Start from the same program that initializes an array to eight random integers between -4 and 4 (program 2.1) and make it print the array immediately after initialization and then again on the next line with all the negative integers replaced with their absolute value (or surrounded by square brackets, your pick).
for (int i = 0; i < array.length; i++) {
output = "";
array[i] = (int)(Math.random() * 9) - 4;
output += array[i] + " ";
}
output += "\n";
for (int i = 0; i < array.length; i++) {
if (array[i] > 0)
output += array[i] + " ";
else
output += "[" + ( -array[i] ) + "] ";
}
Summing only some of the elements
Combine the programs that you have developed so far to produce the sum of those numbers
in the array that are both positive and divisible with 3. Increase the range of the values
that the elements in the array can have from [-4, 4] to [-10, 10]. Use the modulus operator
(%) to resolve divisibility questions.
for (int i = 0; i < array.length; i++) {
output = "";
array[i] = (int)(Math.random() * 21) - 10;
output += array[i] + " ";
}
int sum = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] > 0 && array[i] % 3 == 0)
sum += array[i];
}
output += "Sum = " + sum + "\n";
Summing every other element
Rewrite the program at 2.1 (8-element array of ints) such
that the sum computed adds the numbers in the array starting with the
first (at index 0) and skipping every other element. Use a for
loop.
int sum = 0;
for (int i = 0; i < array.length; i+=2) {
sum += array[i];
}
3. Arrays of Runners
Modify the Runner class a little and write an application that would maintain
an array of Runners that keep advancing each time the "Advance" button is pressed.
The results are shown in a TextArea field. There is also a "Start" button, that
initializes a race to an array of athletes starting at 0, the number of athletes in the race
being specified by the user in an IntegerField.
If the "Advance" button is pressed before the "Start" button initialize the array first and
the race, otherwise pressing "Advance" ignores the value in the IntegerField.
You may find the following framework useful:
import java.awt.*;
import BreezyGUI.*;
public class Racing extends GBFrame {
Button b = addButton( "Start", 1, 1, 1, 1);
Button c = addButton( "Advance", 1, 2, 1, 1);
Label m = addLabel ("No. athletes", 1, 3, 1, 1);
IntegerField i = addIntegerField( 2, 1, 4, 1, 1);
TextArea t = addTextArea( "", 2, 1, 4, 4);
Runner[] athlete;
boolean initialized = false;
public void buttonClicked (Button buttonObj) {
int n = i.getNumber(); String output = "";
if (buttonObj == b) {
// initialize the race
athlete = new Runner[n];
for (int i = 0; i < athlete.length; i++) {
athlete[i] = new Runner("Runner " + i);
output += athlete[i].name + ": " +
athlete[i].distance + " yards\n";
}
initialized = true;
} else {
// advance one step in the race
// if the race has not been initialized yet
if (initialized == false) {
// initialize it now
athlete = new Runner[n];
for (int i = 0; i < athlete.length; i++) {
athlete[i] = new Runner("Runner " + i);
}
initialized = true;
// then advance one step
for (int i = 0; i < athlete.length; i++) {
athlete[i].advance();
output += athlete[i].name + ": " +
athlete[i].distance + " yards\n";
}
} else {
// for each athlete make them advance
for (int i = 0; i < athlete.length; i++) {
athlete[i].advance();
output += athlete[i].name + ": " +
athlete[i].distance + " yards\n";
}
}
}
// by now output should display the current situation
// in the race, formatted for display, one athlete per line
t.setText(output);
}
public static void main(String[] args) {
Frame f = new Racing();
f.setSize(400, 200);
f.setVisible(true);
}
}
class Runner {
String name;
int distance;
Runner (String givenName) {
// write this constructor
name = givenName;
distance = 0;
}
void advance() {
// write this method
int leap;
leap = (int)(Math.random() * 6 + 1);
distance += leap;
}
}
For the ambitious: knowing that the following snippet of code can be used to sort an array of integers in descending order
boolean done = false;
while (! done) {
int aux;
done = true;
for (int i = 0; i < array.length - 1; i++) {
if (array[i] < array[i+1]) {
aux = array[i];
array[i] = array[i + 1];
array[i + 1] = aux;
done = false;
}
}
}
modify the program to see the current status in the race such that the athletes are
sorted in descending order based on the distance covered so far. Here's another sorting
program based on the approach discussed in class on Thursday.
public class Sort {
public static void main(String[] args) {
int[] a = { 8, 7, 6, 5, 4, 3, 2, 1};
boolean sorted; // sorted needs to be declared here to
// be available in the condition for while. The scope
// of the do-while block does not include the condition!
do { int aux;
sorted = true;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i+1]) { sorted = false;
aux = a[i]; a[i] = a[i+1]; a[i+1] = aux;
}
}
} while (! sorted);
for (int i = 0; i < a.length; i++) {
System.out.println(i);
}
}
}
Here's the solution for the ambitious, with not many comments.
It uses the first method of sorting,
BubbleSort.
import java.awt.*;
import BreezyGUI.*;
public class SortedRacing extends GBFrame {
Button b = addButton( "Start", 1, 1, 1, 1);
Button c = addButton( "Advance", 1, 2, 1, 1);
Label m = addLabel ("No. athletes", 1, 3, 1, 1);
IntegerField i = addIntegerField( 2, 1, 4, 1, 1);
TextArea t = addTextArea( "", 2, 1, 4, 4);
Runner[] athlete;
void sort() {
boolean done = false;
while (! done) {
Runner aux;
done = true;
for (int i = 0; i < athlete.length - 1; i++) {
if (athlete[i].distance < athlete[i+1].distance) {
aux = athlete[i];
athlete[i] = athlete[i + 1];
athlete[i + 1] = aux;
done = false;
}
}
}
}
boolean initialized = false;
public void buttonClicked (Button buttonObj) {
int n = i.getNumber(); String output = "";
if (buttonObj == b) {
athlete = new Runner[n];
for (int i = 0; i < athlete.length; i++) {
athlete[i] = new Runner("Runner " + i);
output += athlete[i].name + ": " +
athlete[i].distance + " yards\n";
}
initialized = true;
} else {
if (initialized == false) {
athlete = new Runner[n];
for (int i = 0; i < athlete.length; i++)
athlete[i] = new Runner("Runner " + i);
initialized = true;
for (int i = 0; i < athlete.length; i++)
athlete[i].advance();
sort();
// notice this splits the original for loop in two loops
// one for the advance step and the other one for output
for (int i = 0; i < athlete.length; i++)
output += athlete[i].name + ": " +
athlete[i].distance + " yards\n";
} else {
for (int i = 0; i < athlete.length; i++)
athlete[i].advance();
sort(); // same comment as above
for (int i = 0; i < athlete.length; i++)
output += athlete[i].name + ": " +
athlete[i].distance + " yards\n";
}
}
// by now output should display the current situation
// in the race, formatted for display, one athlete per line
t.setText(output);
}
public static void main(String[] args) {
Frame f = new SortedRacing();
f.setSize(400, 200);
f.setVisible(true);
}
}
class Runner {
String name;
int distance;
// if we make distance private we need an accessor
// method to do the sorting by the distance covered
Runner (String givenName) {
name = givenName;
distance = 0;
}
void advance() {
int leap;
leap = (int)(Math.random() * 6 + 1);
distance += leap;
}
}
4. Experimental probabilities
Write a program that simulates throwing a dice for a number of times. The integer values that you obtain should be 1, 2, 3, 4, 5, and 6. Each occurrence for each of these integers should be counted in a corresponding element of an array with 6 elements. At the end of each simulation write down (output) the number of times each of the six integers has come out. For example throwing the dice 600 times could produce the following distribution of frequencies:
If you're making several simulations in a row be sure to start with the array of frequencies fresh (that is, initialized at 0). Here's part of the program to get you started. Of course, the most important part is missing:[1]: 91 [2]: 97 [3]: 102 [4]: 99 [5]: 109 [6]: 102
import java.awt.*;
import BreezyGUI.*;
public class Probabilities extends GBFrame {
Button b = addButton( "Start", 1, 1, 1, 1);
IntegerField i = addIntegerField( 0, 1, 2, 1, 1);
TextArea t = addTextArea( "", 2, 1, 3, 4);
int[] bins = new int[6];
public void buttonClicked (Button buttonObj) {
int n = i.getNumber(); String output = "";
for (int i = 0; i < bins.length; i++) bins[i] = 0;
for (int i = 0; i < n; i++) {
bins[(int)(Math.random() * 6)] += 1;
}
for (int i=0; i < 6; i++) {
output += "[" + (i + 1) + "]: " + bins[i] + "\n";
}
t.setText(output);
}
public static void main(String[] args) {
Frame f = new Probabilities();
f.setSize(400, 200);
f.setVisible(true);
}
}
The part that you need to write goes into buttonClicked.
Try both approaches discussed in class: try rounding the values that you
obtain from Math.random() and try flooring them. See how the
distributions change shape accordingly.