Looping FileReader - java

I have to read a text file line by line, except after 7 lines I want to use what's read by assigning the 7 lines to 7 different variables. Once I've assigned them, I want to use the variables. That is the easy part, which I know how to do, what has me stuck is that after I have used the 7 variables, I want to be able to assign the next 7 lines of my text file to the same variables, and use them again. I know I have to use loop(s), but ,
how do I make it stop after 7 lines instead of just re-assigning the lines to the variables?
Should I use 2 loops?
Or is there something similar to a break or maybe some sort of "pause" I can apply?
Or is there a some sort of counter that can be used with the FileReader class?
Or should I create one?
Here is what our teacher wants.
Parking Tickets
What to Do:
This assignment is based on Programming Challenge problem-8 on page 574 with some revisions so read this handout carefully. You are allowed to work in teams of 2 people if you desire. The collaboration and discussion would be helpful. Note: This is the longest and likely the most difficult program of the course so work carefully and follow the instructions.
For this assignment you will design a set of classes that work together to simulate a parking officer issuing parking tickets to some cars parked at meters. The problem may be a little artificial when compared to how real meters and tickets work.
You will design four separate classes and a demo program to run everything. Read this whole assignment to the end before starting to write Java code. You need to understand the structure of several classes and understand how the data file is organized.
The basic setting is a group of parking meters with cars parked at them for different amounts of time.
Each car will have purchased some parking time recorded in minutes. And each car will have parked for a certain length of time also recorded in minutes. Some will have parked for more time than they purchased and some for less time than purchased.
Here are the four classes you are required to develop.
• The ParkedCar Class: This class should simulate a parked car. The class’s responsibilities are as follows:
- To know the car’s make, model, color, license number
- To know the identity number of its parking meter.
- Has a toString() method to report its identifying information
• The ParkingMeter Class: This class will simulate a parking meter. The class’s responsibility is as follows:
- to know its own meter identity number
- To know the number of minutes that have been purchased
- To know the number of minutes parked
- has a toString() method to report its information
• The ParkingOfficer Class: This class should simulate a parking officer inspecting parked cars. The class’s responsibilities are as follows:
- Has two instance variables: one for name and one for badge number of the officer
- Has a constructor with two parameters for the parking officer’s name and badge number
- Has a toString() method
- Has an examine() method which receives a ParkedCar object, and a ParkingMeter object as parameters. This method determines whether the time has expired or not
 If time has expired it creates a parking ticket object which is returned as the return value from examine().
 If time has not expired it returns null.
• The ParkingTicket Class: This class will simulate a parking ticket. The class’s responsibility is as follows:
- Has a constructor which receives as parameters a ParkedCar object, a ParkingMeter object and a ParkingOfficer object which are used to initialize corresponding instance variables in the class. Be sure to use copy constructors for each of these parameter objects.
- This class also has an instance variable for the amount of fine.
- The fine is calculated by the ParkingTicket constructor:
 The fine is $25 for the first hour or part of an hour that the car is illegally parked, plus $10 for every additional hour or part of an hour that the car is illegally parked.
 If time has not expired the fine is set to zero.
- Has a toString() method which prepares the ticket in a useful format of your design (try to match the sample output shown below or make your own improvements. It must report the make, model, color, and license number of an illegally parked car. It also reports the amount of the fine and the name and badge number of the police officer issuing the ticket. In this toString() method you must make effective use of the toString() methods for the other classes in parking ticket (i.e. the ParkedCar, the ParkingMeter, and the ParkingOfficer)
Testing Class
Write a testing class, TicketDemo, with main() to run the simulation using the above classes as follows:
• Create a PoliceOfficer object. Make up your own name and badge number. You may hard-wire this into your test program or ask the user for input data (your choice).
• In a loop read data from the data file Asg-5_in.txt. (Note: the file Asg-5_inExplain.txt describes how to interpret the file content.)
o Read one block of data for a car and a meter and create a ParkedCar object and a ParkingMeter object
o Call the parking officer examine() method using your ParkedCar and Parking meter objects as arguments. The examine method will return a ticket or null.
o If a ticket is returned, call the toString() method to print the ticket on the screen.
o If no ticket is issued print identification information about the car (use its toString() method.
o Let the loop repeat until there is no more data available from the input file.
Here is what I have so far, although I'm nowhere near being done.
ParkedCar class:
public class ParkedCar{
private String make;
private String model;
private String color;
private String license;
private String meterID;
public String getMake(String make)
{
this.make = make;
return make;
}
public String getModel(String model)
{
this.model = model;
return model;
}
public String getColor(String color)
{
this.color = color;
return color;
}
public String getLicense(String license)
{
this.license = license;
return license;
}
public String getMeterID(String meterID)
{
this.meterID = meterID;
return meterID;
}
public String toString()
{
String str = "\nMake: " + make + "\nModel: " + model + "\nColor: " + color +
"\nLicense: " + license + "\nMeter ID: " + meterID;
return str;
}
}
ParkingMeter class:
public class ParkingMeter{
private String meterID;
private int minsPurchased;
private int minsParked;
public String getMeterID(String meterID)
{
this.meterID = meterID;
return meterID;
}
public int getMinsPurchased(int minsPurchased)
{
this.minsPurchased = minsPurchased;
return minsPurchased;
}
public int getColor(int minsParked)
{
this.minsParked = minsParked;
return minsParked;
}
public String toString()
{
String str = "\nMeter ID: " + meterID + "\nMinutes Purchased: " + minsPurchased +
"\nMinutes Parked: " + minsParked;
return str;
}
}
ParkingOfficer class:
public class ParkingOfficer{
private String officerName;
private String badgeNumber;
public ParkingOfficer(String officerName, String badgeNumber)
{
this.officerName = officerName;
this.badgeNumber = badgeNumber;
}
public ParkingOfficer(ParkingOfficer object2)
{
officerName = object2.officerName;
badgeNumber = object2.badgeNumber;
}
public void setParkingOfficer(String officerName, String badgeNumber)
{
this.officerName = officerName;
this.badgeNumber = badgeNumber;
}
public String toString()
{
String str = "\nOfficer's Name: " + officerName + "\nOfficer's Badge Number: " + badgeNumber;
return str;
}
}

int lineCounter = 0;
int variableCounter = 7;
BufferedReader br = new BufferedReader(new FileReader(new File("your-file-here.txt")));
String line = "";
List<String> lineSavers = new ArrayList<String>();
while ((line = br.readLine()) != null) {
lineSavers.add(line);
++lineCounter;
if (lineCounter == variableCounter) {
// do something with the lineSaver
lineSavers.clear();
linteCounter = 0;
// start the cycle again.
}
}
There's a lot of stuff that I didn't consider here:
Cleaning up resources - I didn't close the reader.
What happens if you read a file whose line count isn't evenly divided by 7. You'll never get those last lines the way I wrote it.
Hard coded variable counter. I'd make that a variable to be passed in.
Not very modular; I'd pass in that file name and encapsulate the whole thing in a method.
I'd try a more functional approach where I'd pass back what I wanted and then operate on it rather than mingle reading and processing together.
Why seven lines? What are you doing with them? Are they really related in a way that'd be better expressed as an object? You're probably not thinking about the problem in the best way.

You could use commons-io to read the file in one go, and then loop over the list. A bit of example code:
public static void main(String[] args) {
// Read the content of the file in one go
InputStream input = null;
// This is where the file content is stored
List<String> lines = null;
try {
input = new FileInputStream("input.txt");
lines = IOUtils.readLines(new BufferedInputStream(input));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// Always (try to) close the file
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (lines != null) {
String[] params = null; // per 7 lines
for (int i = 0; i < lines.size(); i++) {
int fromZeroToSixCounter = i % 7;
if ( fromZeroToSixCounter == 0 ) {
if (params != null) {
// the first time (i == 0) params is null and this will not execute
doSomethingWithParams(params);
}
// new batch of 7 lines
params = new String[7];
}
params[fromZeroToSixCounter] = lines.get(i);
}
if (params != null) {
// the last batch
doSomethingWithParams(params);
}
}
}
public static void doSomethingWithParams(String[] params) {
System.out.println("New batch");
for (int i=0; i < params.length; i++) {
System.out.println(params[i]);
}
}

A basic structure would be something like this:
while (true) {
String v1 = reader.readLine();
if (v1 == null)
break;
String v2 = reader.readLine();
...
String v7 = reader.readLine();
/* Do what ever you want with v1 through v7. */
...
}
/* End of loop. */

Related

Java return multiple strings in one method

I am attempting to write a program which asks users what their pet name is, species, finds out thirst level and gives a response accordingly.
I would appreciate if someone could help me with a problem im having, in each of the 2 methods askpetname and thirstlevel there are 2 strings i want accessible throughout the entire class without using global variables.
Can someone tell me what it is i am doing incorrectly or point me in the right direction.
Also, i understand that my excess use of methods for tedious tasks is bad practice but it helps with memorising syntax.
Thanks.
class dinoo
{
public static void main(String[] p)
{
explain();
output();
System.exit(0);
}
public static void explain()
{
print("The following program demonstrates use of user input by asking for pet name.");
return;
}
public static String askpetname()
{
Scanner scanner = new Scanner(System.in);
print("Name your dinosaur pet!");
String petname = scanner.nextLine();
print("Awesome, cool dinosaur name, what species is " + petname+ " ?");
String petspecies = scanner.nextLine();
return petname, petspecies;
}
public static int thirstlevel()
{
Random ran = new Random();
int thirst = ran.nextInt(11);
int hunger = ran.nextInt(11);
return thirst,hunger;
}
public static String anger(int thirst, int hunger)
{
double angerscore = (thirst+hunger)/2;
String temper;
if(angerscore<=2)
{
temper = "Serene";
}
else if(3<=angerscore<=6)
{
temper= "Grouchy";
}
else if(6<angerscore)
{
temper = "DANGEROUS";
}
return temper;
}
public static String warning()
{
if (temper.equals("Serene"))
{
print("He's looking happy!");
}
else if(temper.equals("Grouchy"))
{
print("Ahhh hes a bit "+temper+", you better start feeding him before he gets mad!");
}
else if(temper.equals("DANGEROUS"))
{
print("GET OUT OF THERE, HES " + temper+"!!!. He will have to be put down for everyones safety.");
}
}
public static void output()
{
print(askpetname() + "'s, thirst level is "+thirstlevel()+"/10");
return;
}
public static String print(String message)
{
System.out.println(message);
return message;
}
}
That code won't compile since you can't have:
return string1, string2;
or
else if(3<=angerscore<=6)
Instead of trying to return multiple Strings, your best bet is to create a class, say called Pet, one that holds String fields for the pet's name, a Species field for its species, as well as any other fields for hunger, thirst ... that would best encapsulate all the data that makes up one logical "pet" as well as a methods such as getAnger() that returns a value for anger depending on the Pet's state. Then you can create and return a viable Pet object from your creational method.
Also, your code has lots of compilation errors, suggesting that you could improve the way that you create your code. Never try to add new code to "bad" code, to code that won't compile. If possible, use an IDE such as NetBeans, Eclipse, or IntelliJ to help you create your programs. The IDE's will flag you if any of your code contains compilation errors, and then the key is: don't add new code until you've first fixed the existing compilation error. If you can't use an IDE, then you must compile early and often, and do the same thing -- fix all errors before adding new.
First, I would recommend shooting through a tutorial first before attempting this, do all the hello worlds covering scope, objects, arrays and functions. Get familiar with Object Oriented Style, although thats not even procedural programming ... nothing returns 2 objects ... always 1 (it could be an array containing many objects, but an array is a single object)
Moving on,although this is terrible coding practice, but its ok for a beginner,since your functions are all static, create a private static variable inside each function and create getter functions
//convert
String petname = scanner.nextLine();
// To this
private static String petname = scanner.nextLine();
// Then add this below it
public static String getPetName()
{
return petname;
}
and same for every piece of data you need.
Now remove the return statement from all of your functions and declare return type as void
Then call all functions from Main,
askpetname();
thirstlevel();
then print final output (after you have called the functions) as such
System.out.println("Petname: " + getPetname + " ThirstLevel: " + getThirstLevel() + " HungerLevel: " + getHungerLevel);

Java target/select class/object - confused (sorry for bad title)

What I have below is producing the desired results by print some employee details along with weekly / monthly wages as appropriate.
However I understand that I should not be inputting data in the constructor as I've done.
I need to prompt for a hours worked value only for "PartTimeEmployees", just not the way I've done it.
I've tested with For-Each loops, Enhanced For loops and using the instanceOf operator.
If I could get some guidance/hints or examples of how to accomplish what is currently being done in the constructor, but in the TestEmployee class instead that would be great.
Mostly I'm not sure how to even describe what I'm trying to achieve. This hinders Googling somewhat. (Help with a better title would also be great)
Thanks in advance.
public class TestEmployee
{
public static void main(String[] args)
{
int size;
Employee[] employees = new Employee[4];
employees[0] = new FullTimeEmployee("Jane", 26000);
employees[1] = new PartTimeEmployee("Jack");
employees[2] = new FullTimeEmployee("Lucy", 52000);
employees[3] = new PartTimeEmployee("Lenny");
for(int i = 0; i < employees.length; i++)
{
employees[i].print();
}
}
}
Class: PartTimeEmployee - Constructor:
public PartTimeEmployee(String thisName)
{
super(thisName);
System.out.println("Please enter the number of hours worked by " + thisName + ": ");
numHours = keyboard.nextInt();
setHours(numHours);
}
If I get your question, below might fit with your need -
First of all create generic Employee class -
class Employee {
private String name;
private int workingHours;
private final boolean IS_PART_TIME_EMP;
public Employee(String name, int workingHours) {
this.name = name;
this.workingHours = workingHours;
this.IS_PART_TIME_EMP = false;
}
public Employee(String name) {
this.name = name;
this.IS_PART_TIME_EMP = true;
}
public String getName() {
return name;
}
public int getWorkingHours() {
return workingHours;
}
public void setWorkingHours(int workingHours) {
this.workingHours = workingHours;
}
public boolean isPartTimeEmployee() {
return IS_PART_TIME_EMP;
}
}
Now you can use it as per your requirement.
Employee[] employees = new Employee[4];
employees[0] = new Employee("Jane", 26000);
employees[1] = new Employee("Jack");
employees[2] = new Employee("Lucy", 52000);
employees[3] = new Employee("Lenny");
Scanner sc = new Scanner(System.in);
for (Employee employee : employees) {
if(employee.isPartTimeEmployee()) {
System.out.println("Please enter working hours by " + employee.getName() + ": ");
int numHours = sc.nextInt();
employee.setWorkingHours(numHours);
}
}
Constructor is not meant for user input.Its main intention is to initialize object of that class.
Instead of doing that in constructor,you can try something like this
employees[1] = new PartTimeEmployee("Jack");
System.out.println("Please enter the number of hours worked by " + employees[1].getName()+ ": ");
numHours = keyboard.nextInt();
employees[1].setHours(numHours);
You most likely will have some logical main loop in your program, like
while(!quit) {
// 1. ask if you want to add part time or full time employee
// 2. ask proper questions
// 3. call correct constructor
}
Writing such small pseudo code algorithm should be self explanatory and get you going.
Step one: presentation of options available for user and reading user input.
Step two: performing actions depending on user input from step 1
Step three: final call to proper constructor depending on results from steps 1 and 2
If I understood your question correctly (which I'm really not sure of) you want to prompt for the employee data in the main method.
In that case I'd use a loop and query the following things:
name of the employee
does the employee work full time? (y/n)
if yes: what is the wage? (assume hours = whatever a full time employee works a day)
if no: how many hours? (and probably the hourly wage as well)
Then use that information to construct an Employee object (I don't see any need for the subclasses here).

Error: Constructor Room in class Room cannot be applied to given types

I am completely new to java. I have searched for hours upon hours for the solution to this problem but every answer involves passing args or using a void which I do not do in this situation.
I have two java files, one for Room class, and one for TourHouse class. I am trying to create a new Room in the TourHouse class. Here is my error, it's driving me nuts, I've tried everything I am capable of understanding. Thank you in advance.
HouseTour.java:15: error: constructor Room in class Room cannot be applied to given
types;
{
^
required: String, String
found: no arguments
reason: actual and formal arguments differ in length
Here is the Room class, will have 7 rooms total once I can figure this out
// Room.java
import java.util.*;
public class Room
{
// Define Instance Variables
private String name;
private String description;
// Define Constructor
public Room(String theName, String theDescription)
{
name = theName;
description = theDescription;
}
public String toString( )
{
return "The " + name + "\n" + description + "\n";
}
}
Here is the HouseTour class
import java.util.*;
public class HouseTour extends Room
{
// Define Variables
public Room[ ] rooms = new Room[7];
//Define Constructor
public HouseTour( )
{
rooms[0] = new Room("Living Room", "Mayonnaise and Brill Grates, Michaelsoft");
rooms[1] = new Room("Basement", "Hopefully no dead bodies down here...");
}
// this is horrible and not right
public String rooms( )
{
for (int i = 0; i <=7; i++)
{
String output = "House Rooms included in tour\n";
String output2 = output + rooms.toString() + "\n";
return output2;
}
}
}
EDIT: Solved but still need help here because I am complete n00b, :(
// this is horrible and not right
public String rooms( )
{
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
output += rooms[i]; // I can't do this but how do i?
}
return output.toString(); // do I do this?
}
}
What I am doing is trying to learn java by converting the ruby projects I have created. So in ruby you say:
def rooms
output = "House Rooms included in tour\n"
#rooms.each do |r|
output += r.to_s + "\n"
end
return output
end
Edit: Still trying, any ideas?
added public String s; and public String output; to declarations
// this is horrible and not right
public String rooms( )
{
s = ""
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
s += rooms[i];
}
s.toString() // I don't know
return output + s; // do I do this?
}
}
Edit: Solved thanks to Hovercraft Full Of Eels
Ah, I see your problem: HouseTour extends Room. Don't do this! HouseTour is not a more specific case of a Room type and so should not extend this class. It does not fulfill the "is-a" rule, and would be similar to trying to define Bus as a child class of SchoolKid. Just like a Bus isn't a type of SchoolKid but rather contains SchoolKids, a HouseTour isn't a Room but rather contains Rooms. It fulfills the has-a relationship, not the is-a relationship.
If the inheritance were proper in this situation, your HouseTour constructor would need to call the Room super constructor and pass in two String parameters:
// Don't do this!!!
public class HouseTour extends Room {
public HouseTour() {
super("foo", "bar");
....
}
But having said that, again inheritance is not proper here -- just get rid of extends Room, and you're home free.
e.g.,
public class HouseTour { // no extends!
private Room[] rooms; // has-a not is-a
public HouseTour() {
// don't call super here
}
Also, as per my comment, this will give you ugly output: rooms.toString()
Instead iterate through the Array and get the toString() result from each Room item in the array.
Edit
Suggestions on your rooms() method:
Create a String or StringBuilder before the loop.
Build up the String or StringBuilder inside the loop.
Return the String or StringBuilder#toString after the loop.
Inside of the loop get the toString() from the current Room item in the list.
You will need to check that the rooms[i] item isn't null before calling a method on it.
Edit 2
You state that this:
public String rooms( )
{
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
output += rooms[i]; // I can't do this but how do i?
}
return output.toString(); // do I do this?
}
is causing problems, but you don't specify the problem.
Myself, I'd do something like:
public String rooms( ) {
// declare your String locally, not globally in the class
String output = "House Rooms included in tour\n";
// again, avoid using "magic" numbers like 7
for (int i = 0; i < rooms.length; i++) {
output += rooms[i].toString(); // **** you must extract Room's String
}
return output; // no need to call toString() on a String
}

Java: index in array exists, ArrayIndexOutOfBoundsException: 0

Sorry if this is answered somewhere due to me missing something obvious, but I've been googling this for days now and it just doesn't seem to make any sense. I've got 3 years of experience in Javascript and am getting into Java now, so I'm not behind on the basic concepts of anything and such.
I'm using IntelliJ for this, but it fails to point out the problem. The communication (access rights and instantiations) between my classes is fine, the code syntax and variable types are as well, etc, so I really can't tell what it is.
I have a Data class, which just holds "read-only" data for the other classes to use.
public class Data {
// snip
public static int[][] specs = {
{6,1,6,40},
{5,2,5,30},
{5,3,4,40},
{4,4,3,60}
};
}
There's another class that has to read this data when it's initialized.
public class Soldier {
// snip
public int range;
public Soldier() {
int x = ...; // user input
range = Data.specs[x][1];
}
}
The specs array itself contains its data as defined (ie the array is not empty), x is valid as an index of the specs array (ie 0 <= x <= 3), its type is int and Test has read access to the specs array (all confirmed with debug output statements). And yet, when it tries to set the value of range (then and only then, at that exact point), I get the "Index out of bounds" error.
Can someone please tell me what's going wrong when trying to read the array? Or am I right in saying that this is really weird and I need to post the entire code?
Note: a small new test also shows that, if I change the code to first output a manually chosen value from the array and then set the value of range, the console prints the error statement (and exits the program) and follows it up by printing the manually picked value, but assigning the value and then asking to output range only throws the error... That makes absolutely no sense at all!
Edit: I've edited the code above. The class called Test is called Soldier in my code (I'm making a text-based game...). Below's the stack trace, if it's any good without the full code (which is way long). The basic structure of my program is this:
1) Boot contains the main method and instantiates a new Game
2) Game instantiates x Teams
3) each Team instantiates an Army
4) each Army instantiates x Soldiers
Each instance of the classes is set as an attribute of the instantiating class (public Army army; and an Army instantiation in the Team constructor, for example). It's essentially a cascade of constructors instantiating subsequent classes and assigning them as their attributes.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Army.<init>(Army.java:13)
at Team.<init>(Team.java:19)
at Game.<init>(Game.java:22)
at Boot.main(Boot.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)5
Edit edit: here's the semi-full code (I'm leaving out the stuff that has absolutely nothing to do with it, including the imports). It's in no particular order and the classes are in separate .java files within the IntelliJ project. The game continues up to the point where a new Soldier asks for its type to be designated (the function performing the user input is working fine and validating the input as proven by a technically identical other part of the game).
public class Boot {
public static void main(String[] args) {
Object[] games = new Object[] {};
if (Lib.userConfirmPrompt("Start the game?") == true) {
do {
games[games.length] = new Game();
}
while (Lib.userConfirmPrompt("Do you want to play again?") == true);
}
System.exit(0);
}
}
public class Game {
public Object[] teams = new Object[] {};
public Game() {
for (int i = 0;i < settings.xbots + 1;i++) {
teams[teams.length] = new Team(this);
}
}
}
public class Team {
public Game game;
public Army army;
public Team(Game p) {
game = p;
army = new Army(this);
}
}
public class Army {
public Team team;
public static Object[] soldiers = new Object[] {};
public Army(Team p) {
team = p;
for (int i = 0;i < team.game.settings.xsoldiers;i++) {
soldiers[soldiers.length] = new Soldier(this);
}
}
}
public class Soldier {
private Army army;
public int sight;
public int range;
public int distance;
public int damage;
public Soldier(Army p) {
army = p;
int type = Lib.userTxtIntOptionsPrompt(Data.isoldiertypes);
// HERE is where it crashes, type is assigned and valid but the array access fails
sight = Data.isoldierspecs[type][0];
range = Data.isoldierspecs[type][1];
distance = Data.isoldierspecs[type][2];
damage = Data.isoldierspecs[type][3];
}
}
public class Data {
public static List isoldiertypes = Arrays.asList("Scout","Private","Machinegunner","Grenadier");
public static int[][] isoldierspecs = {
{6,1,6,40},
{5,2,5,30},
{5,3,4,40},
{4,4,3,60}
};
}
public class Lib {
private static Scanner input = new Scanner(System.in);
// output
// default: 1 query string to print
public static void outBase(String query) {
System.out.print(query);
}
public static void outStd(String query) {
outBase(query + "\n");
}
// end of output
// input
// default: 1 query string to print,
// query and input are in-line (exception: userConfirmPrompt prints query block-wise and default instruction in-line before input),
// keeps user hostage until valid input is given (exception: userPrompt returns blindly)
public static String userPrompt(String query) {
outBase(query);
return input.nextLine();
}
public static String userTxtPrompt(String query) {
String menuinput = null;
do {
if (menuinput != null) {
userHostage();
}
menuinput = userPrompt(query);
} while (menuinput.length() == 0);
return menuinput;
}
public static int userIntPrompt(String query) {
String menuinput = null;
do {
if (menuinput != null) {
userHostage();
}
menuinput = userTxtPrompt(query);
} while(menuinput.matches("^-?\\d+$") == false);
return new Integer(menuinput);
}
// end of input
// options input
// default: takes a List of options as argument,
// prints an enumerated list of these options string-wise,
// prompts for a numeral selection of the desired option and returns the number if valid
public static int userTxtIntOptionsPrompt(List options) {
int choice = 0;
Boolean chosen = false;
do {
if (chosen == true) {
userHostage();
} else {
chosen = true;
}
chosen = true;
for (int i = 0;i < options.size() - 2;i++) {
outStd((i + 1) + ") " + options.get(i) + ",");
}
outStd((options.size() - 1) + ") " + options.get(options.size() - 2) + "\nand " + options.size() + ") " + options.get(options.size() - 1) + ".");
choice = userIntPrompt("Enter the number of the option you'd like to select: ") - 1;
} while(choice < 0 || choice >= options.size());
return choice;
}
// end of options input
// miscellaneous
public static void userHostage() {
outStd("Invalid operation. Please try again.");
}
}
The problem is in your Army class:
public static Object[] soldiers = new Object[] {};
You initialize an empty (length == 0) array named soldiers, but later you access:
soldiers[soldiers.length] = new Soldier(this);
This causes the failure.
By definition, soldiers.length is out of the bound of the array (since the bound is from 0 to soldiers.length-1)
To overcome it - make sure you allocate enough space in the array soldiers or use a dynamic array (ArrayList) instead. You can append elements to an ArrayList using ArrayList.add(), and you don't need to know the expected size before filling it up.
The x should be greater than -1 and less than 4.
The stacktrace does not mention the Solder class, its in the conctructor of the Army class.
Any how, only knowing that the index should be within a range is not enough. As a programmer its your duty to validate the index before trying to access an element at that index.
if(index > 0 && index < array.length) {
//then only acess the element at index
Problem is the array soldiers is of size 0.
This line int x = ...; // user input implies that you are taking input in some fashion from the user and accessing the array with it. Are you checking this value to see that is in range (i.e., between 0 and 3)? If not, this may be why your testing works.
Edit: something like this might solve it for you:
public class Army {
public Team team;
public Vector<Soldier> soldiers;
public Army(Team p) {
soldiers = new Vector<Soldier>()
team = p;
for (int i = 0;i < team.game.settings.xsoldiers;i++) {
soldiers.add(new Soldier(this));
}
}
}
Judging by your other code, this sort of pattern will be useful in your Game object as well.

Need someone to check my Program, I think my equals method is wrong

I am done with this assignment think god, and was wondering if someone could please check it so I can make sure there are no errors, it seems like I work hard on these programs but always doing something wrong. I am doing this course online so I have a hard time communicating with the instructor. I think my equals to methods might be wrong but, they seem to have no error when running the program and the program is 100% done. Please take the time to look over it, and thank you so much for your time.
Assignment:
About the first class
Create a class named RoomDimension that has two fields: one for the length of the room and another for the width. The RoomDimension class should have two constructors: one with no parameters (a default) and one with two parameters. The class should have all of the appropriate get and set methods, a method that returns the area of the room, a toString method that will allow us to print the length, width and area of the room and an equals method to compare room dimensions.
About the second class
Create another class named RoomCarpet that has two fields: one is a RoomDimension object and the other is a field that holds the cost of carpet per square foot. The class should have two constructors: one with no parameters and one with the two field parameters (RoomDimension and double). The class should have a get and set method for each field, a method that returns the total cost of carpeting the room, a toString method that will print all of the room information (length, width, area) and cost of the carpet per square foot and the total cost to carpet the room. (Dollar amounts should be displayed with two decimal places.), and an equals method that compares room dimensions and carpet cost.
About the application program
Write an application program that contains one RoomDimension object and one RoomCarpet object. The program should allow the user to enter the length and width of the room and the cost of the carpet per square foot. The program should instantiate both objects and use a simple System.out.println statement to print all of the information about the RoomCarpet object.
MY code:
import java.text.DecimalFormat;
public class RoomCarpet {
private RoomDimension rmSize;
private double pricePerSqFt;
//default constructor
public RoomCarpet()
{
this.rmSize = new RoomDimension();
this.pricePerSqFt = 0.00;
}
//parameters constructor
public RoomCarpet(RoomDimension rmSize, double pricePerSqFt)
{
this.rmSize = new RoomDimension(rmSize.getRmLength(),rmSize.getRmWidth());
this.pricePerSqFt = pricePerSqFt;
}
//accessor methods
public RoomDimension getRmSize()
{
return new RoomDimension(rmSize.getRmLength(),rmSize.getRmWidth());
}
public double getPricePerSqFt()
{
return this.pricePerSqFt;
}
// mutator methods
public void setRmSize(RoomDimension rmSize)
{
this.rmSize = new RoomDimension(rmSize.getRmLength(), rmSize.getRmWidth());
}
public void setPricePerSqFt(double pricePerSqFt)
{
this.pricePerSqFt = pricePerSqFt;
}
// Or price for the room to be carpeted
public double rmTotalCost()
{
return rmSize.getAreaRoom() * pricePerSqFt;
}
//toString method
public String toString()
{
DecimalFormat dollar = new DecimalFormat("$#,##0.00");
String str = this.rmSize.toString() + " Price per sq. ft : " +dollar.format(pricePerSqFt) + " Price to carpet Room: " + dollar.format(rmTotalCost()) + '\n';
return str;
}
public boolean equals(RoomCarpet object2)
{
boolean status;
if ((this.equals(object2)==true)&&(this.pricePerSqFt==object2.pricePerSqFt))
status = true;
else
status = false;
return status;
}
}
public class RoomDimension {
private int rmLength;
private int rmWidth;
//Default constructor
public RoomDimension()
{
rmLength=0;
rmLength=0;
}
// constructor with parameters
public RoomDimension(int rmLength, int rmWidth)
{
this.rmLength=rmLength;
this.rmWidth=rmWidth;
}
// accessor methods
public int getRmLength()
{
return this.rmLength;
}
public int getRmWidth()
{
return this.rmWidth;
}
//mutator methods
public void setRmLength(int rmLength)
{
this.rmLength=rmLength;
}
public void setRmWidth(int rmWidth)
{
this.rmWidth =rmWidth;
}
//area of the room
public int getAreaRoom()
{
return this.rmLength * this.rmWidth;
}
//toString Method
public String toString()
{
String str = "Room Length: " + this.rmLength + " Room Width: " + this.rmWidth + " Area of Room: " + this.getAreaRoom();
return str;
}
public boolean equals(RoomDimension object2)
{
boolean status;
if (this.getAreaRoom() == object2.getAreaRoom())
status = true;
else
status = false;
return status;
}
}
import java.util.Scanner;
public class CarpetPrice {
public static void main(String[] args)
{
RoomDimension rmSize;
RoomCarpet rmCarpet;
Scanner keyboard = new Scanner(System.in);
rmSize=new RoomDimension();
System.out.println(" Please enter the length of the room: ");
int rmLength= keyboard.nextInt();
rmSize.setRmLength(rmLength);
System.out.println("Please enter the rooms width: ");
int rmWidth = keyboard.nextInt();
rmSize.setRmWidth(rmWidth);
System.out.println("Please enter the price per sq foot: ");
double pricePerSqFt = keyboard.nextDouble();
rmCarpet = new RoomCarpet(rmSize, pricePerSqFt);
System.out.println("\n"+rmCarpet.toString());
}
}
The equals method must have an Object argument and you have to override the hashCode method too.
#Override
public boolean equals(Object obj)
{
}
I would say that for RoomDimension, two objects are equal only if both length and width match. Especially if you're laying carpet, a 4x5 room would be much different from a 1x20 hallway, even though the total area is the same. For the RoomCarpet object, again equal only if both the dimensions are equal and the price is the same, I guess.
Also, I would write some tests because you may be surprised at what happens when you call RoomCarpet's .equals() method (as written above).
Finally, pay attention to your indenting because that's important for any reader of your code.

Categories

Resources