Im having an issue passing an enumerated value from my main to one of my classes. My program stores information about nerds: name, nerdfactor. It has a series of classes and subclasses. I have a super class which is extended to 2 other classes and a third class which extends to 1 of the before mentioned subclasses. what my program is supost to do is take filled arguments such as name, nerdfactor, and wether the nerd prefers WII, XBOX or PS3. Bellow is a clip from my main and the beginings of my subclass. If anyone can help me figure out how to pass the enumerated argument i'd be very grateful.
public static void main(String[] args) {
// List to keep a few nerds in
ArrayList<GenericNerd> nerdList = new ArrayList(10);
GenericNerd nerd = new GenericNerd("Bugger McNosePicker", 9);
nerdList.add(nerd);
nerd = new ConsoleGeek("Freddy where's my mommy", 9, WII); // the WII should be an enum value
nerdList.add(nerd);
}
Subclass ConsoleGeek
public class ConsoleGeek extends GenericNerd {
enum ConsoleType {
WII, PS3, XBOX
};
private ConsoleType console;
public void setConsoleType(ConsoleType console) {
this.console = console;
}
public ConsoleType getConsoleType(){
return console;
}
public ConsoleGeek(String name, int nerdFactor, ConsoleType console) {
super(name, nerdFactor);
if (name == null) {
System.out.println("Error: GenericNerd constructor - name is null!");
System.exit(1);
}
// the setNerdFactor method handles parameter range checking
setNerdFactor(nerdFactor);
this.name = name;
if (console == ConsoleType.WII) {
// make sure WII players nerd factor is less than 6!
if (nerdFactor > 5) {
System.out.println("Warning: " + name
+ " Prefers WII! (setting nerdFactor to 5).");
setNerdFactor(5);
}
// Make sure XBOX players nerd factor is between 3 and 8
} else if (console == ConsoleType.XBOX) {
if (nerdFactor < 3 || nerdFactor > 8) {
System.out.println("Warning: " + name
+ " Prefers XBOX! (setting nerdFactor to 8).");
setNerdFactor(8);
}
}
}
I thought about the idea of making a new type of nerd like
ConsoleGeek supergeek = new ConsoleGeek(arguments)
but I'm pretty sure its supposed to stay in the other format.
nerd = new ConsoleGeek("Freddy where's my mommy", 9, ConsoleGeek.ConsoleType.WII);
Related
I am trying to make an erase function to delete the teams of the tournament using the team code (value c in the constructor). Firstly I want to check if that team exists in the objects I made in the main method. Is that possible to do that using an if statement?
Exercise:
Create a java application that stores data for various football teams. Each team has a name, a code and the current points in the championship. In your class create methods for registering new teams, erasing existing teams using their code and showing a list for all the teams currently active in the championship
package assignment.exercise4;
public class Data {
private String name = "";
private int code = 0;
private static int register;
private int erase;
private int currentpoints = 0;
public Data(int c, int points, String n) { //constructor
code = c;
this.currentpoints = points;
name = n;
}
public void Erase(int c)
{
code = c;
if(code != 0)
System.out.println("Team with Code: "+code+" has been erased" );
else
System.out.print("Team with code "+code+" does not exist!");
}
public void Register(String newTeam,int code)
{
name = newTeam;
this.code = code;
System.out.println("New Team " + name + " registered with code " + code);
}
public void print()
{
System.out.println("Team name: " + name + "\nTeam code: " + code + "\nTeam points: " + currentpoints + "\n");
}
}
/*
public static void main(String[] args) {
System.out.println("\nList of Teams: \n");
Data t1 = new Data(110,42,"Juventus");
Data t2= new Data(105,45,"Manchester City");
Data t3= new Data(240,50,"Barcelona");
Data t4= new Data(122,36,"Arsenal");
Data Team = new Data(0,0,""); //use for erase
t1.print();
t2.print();
t3.print();
t4.print();
System.out.println("Teams erased: \n");
Team.Erase(110);
Team.Erase(122);
Team.Erase(0);
System.out.println("\n\nTeams Registered: \n");
t1.Register("Real madrid", 11);
t1.Register("Atletico Madric", 112);
}
}
*/
What are you trying to erase the teams from?
If they were in a list, for example...
Data t1 = new Data(110,42,"Juventus");
Data t2= new Data(105,45,"Manchester City");
Data t3= new Data(240,50,"Barcelona");
Data t4= new Data(122,36,"Arsenal");
List<Data> teams = Arrays.asList(t1, t2, t3, t4);
...you could create a list with a team erased like this...
public List<Data> erase(List<Data> team, int id) {
return team.stream()
.filter(t -> t.getId() != id)
.collect(Collectors.toList());
}
So...
List<Data> remainingTeam = erase(team, 122); // Removes Arsenal
...would remove the first element from the list
I will not answer this to elaborately since it is homework. I will try to give you a hint though.
If you have a team and want to do something with it. Otherwise you just have a team which just stays there in a particular scope (if you do not know what scope is, look it up!). If you have a team you most likely want do do something with it. In this case you seem to want to store information about the teams to use in a championship. Important to note here is that the teams are not the focus here. The real focus is the Championship. The teams are just a part of the championship. There can still be a championship even if all teams does not choose to participate. But you want all teams choosing to participate to be registered to this particular championship (eg UEFA Champions League).
This leads to something called aggregate or association depending on how hard you want to tie the object to the championship. However you do probably not need to pursue these terms any further at this point. What is important to remember is that there is an "has a" relation between the championship and the teams. The championship "has a" collection of participating teams. This is normally reflected in this way in code,
public class Championship {
private Team[] teams; // Or List<Team>, Collection<Team>, HashMap<Team>, ...
}
The Championship can then have methods for registering a team, removing a team, updating status, etc...
public void register(Team t) {
if (numberOfTeams < teams.length) {
teams[numberOfTeams] = t; // Index starts at zero
numberOfTeams++;
} else {
throw new IndexOutOfBoundsException("The list is full. " +
"No more teams may be registered!")
}
}
Even though the function erasing a team was requested, I believe I will not write it down. This design is so different from your original intent, so that writing the erase function will likely solve your complete homework. However, you do actually not have to erase the team it is perfectly possible to just overwrite the position with the next team as,
teams[i] = teams[i+1];
Hope this helps!
Short answer:
public void erase(int id) {
// who needs an if statement, if we can use predicates?
teams.removeIf(team -> team.getId() == id);
}
But this will not work with your current code. Your current code misses the container for your teams.
Longer answer:
For the fun of it. Solving your homework:
class Team {
int id;
String name;
int points;
Team(int id, String name, int points) {
this.id = id;
this.name = name;
this.points = points;
}
#Override
public String toString() {
// ugly formatted... another homework? ;-)
return "Team '" + name + "' (" + id + "): " + points;
}
}
Note, that I will not add any getter or setter, nor will I care about visibility here. I will leave that as another homework for you.
class Championship {
List<Team> teams = new ArrayList<>();
void register(Team team) {
teams.add(team);
}
void erase(int id) {
teams.removeIf(team -> team.id == id);
}
#Override
public String toString() {
// for additional fun... sorted by descending points
return "=== Championship table ===\n"
+ teams.stream()
.sorted((o1, o2) -> Integer.compare(o2.points, o1.points))
.map(Objects::toString)
.collect(Collectors.joining("\n"));
}
}
Somewhere else:
public static void main(String[] args) {
Championship championship = new Championship();
championship.register(new Team(1, "not the best ones", 3));
championship.register(new Team(2, "The better ones", 7));
championship.register(new Team(3, "The winners", 11));
System.out.println(championship);
championship.erase(3);
System.out.println(championship);
}
Output:
=== Championship table ===
Team 'The winners' (3): 11
Team 'The better ones' (2): 7
Team 'not the best ones' (1): 3
=== Championship table ===
Team 'The better ones' (2): 7
Team 'not the best ones' (1): 3
Too much of information? Just start with something like a championship-class or at least use a collection of Teams (e.g. List<Team>).
By the way... Do not deliver this solution as your homework, except you understand what is going on and you can explain it with your own words. Otherwise you are only betraying yourself.
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
}
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.
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. */
If anyone familiar with Rebecca Wirfs-Brock, she has a piece of Java code found in her book titled, Object Design: Roles, Responsibilities, and Collaborations.
Here is the quote >Applying Double Dispatch to a Specific Problem
To implement the game Rock, Paper, Scissors we need to write code that determines whether
one object “beats” another. The game has nine possible outcomes based on the three kinds of
objects. The number of interactions is the cross product of the kinds of objects. Case or switch statements are often governed by the type of data that is being operated on. The
object-oriented language equivalent is to base its actions on the class of some other object. In Java,
it looks like this
Here is the piece of Java code on page 16 '
import java.util.*;
import java.lang.*;
public class Rock
{
public static void main(String args[])
{
}
public static boolean beats(GameObject object)
{
if (object.getClass.getName().equals("Rock"))
{
result = false;
}
else if (object.getClass.getName().equals("Paper"))
{
result = false;
}
else if(object.getClass.getName().equals("Scissors"))
{
result = true;
}
return result;
}
}'
===>This is not a very good solution. First, the receiver needs to know too much about the argument.
Second, there is one of these nested conditional statements in each of the three classes. If new
kinds of objects could be added to the game, each of the three classes would have to be modified.
Can anyone share with me how to get this "less than optimal" piece of code to work in order to see it 'working'. She proceeds to demonstrate a better way, but I will spare you.
Thanks
I would start by defining classes RPSSystem and RPSObject. The code to construct the classic RPS-game would look like this:
RPSObject rock = new RPSObject("Rock");
RPSObject paper = new RPSObject("Paper");
RPSObject scissors = new RPSObject("Scissors");
RPSSystem classicRPS = new RPSSystem(rock, paper, scissors);
// new RPSSystem(Collection<RPSObject> objects) possible too
classicRPS.defineBeatsRule(rock, scissors);
classicRPS.defineBeatsRule(paper, rock);
classicRPS.defineBeatsRule(scissors, paper);
RPSSystem would have a method
int fight(RPSObject a, RPSObject b)
which would return -1 when a wins, 1 when b wins and 0 when the result is not defined. Internally RPSObjects could be stored in a list and beating rules could be stored in a matrix (columns and rows would match the indices of the objects in the list). If multiple instances of similar RPSObject should be allowed, the equals-method of RPSObject should be written accordingly.
Having a separate class for each object in the system seems a bit too complicated.
EDIT:
Complete classes:
package rpsgame;
public final class RPSObject {
private final String name;
public RPSObject(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return getName();
}
}
package rpsgame;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public final class RPSSystem {
private final List<RPSObject> objects;
private final int[][] beatsRules;
public static final int WINS = 1;
public static final int TIE = 0;
public static final int LOSES = -1;
public RPSSystem(RPSObject... objects) {
this.objects = Arrays.asList(objects.clone());
this.beatsRules = new int[objects.length][objects.length];
}
void defineBeatsRule(RPSObject winner, RPSObject loser) {
if (winner.equals(loser)) throw new IllegalArgumentException();
int winnerIndex = getObjectIndex(winner);
int loserIndex = getObjectIndex(loser);
beatsRules[winnerIndex][loserIndex] = WINS;
beatsRules[loserIndex][winnerIndex] = LOSES;
}
public int fight(RPSObject a, RPSObject b) {
int aIndex = getObjectIndex(a);
int bIndex = getObjectIndex(b);
return beatsRules[aIndex][bIndex];
}
public List<RPSObject> getObjects() {
return Collections.unmodifiableList(objects);
}
private int getObjectIndex(RPSObject o) {
int index = objects.indexOf(o);
if (index < 0) throw new IllegalArgumentException();
return index;
}
// test
public static void main(String[] args) {
RPSSystem classicRPS = buildClassicRPS();
List<RPSObject> objects = classicRPS.getObjects();
for (RPSObject a: objects) {
for (RPSObject b: objects) {
int result = classicRPS.fight(a, b);
switch (result) {
case RPSSystem.WINS:
System.out.println(a + " beats " + b);
break;
case RPSSystem.TIE:
System.out.println(a + " vs " + b + " is tied");
break;
case RPSSystem.LOSES:
System.out.println(a + " loses against " + b);
break;
}
}
}
}
private static RPSSystem buildClassicRPS() {
RPSObject rock = new RPSObject("Rock");
RPSObject paper = new RPSObject("Paper");
RPSObject scissors = new RPSObject("Scissors");
RPSSystem classicRPS = new RPSSystem(rock, paper, scissors);
classicRPS.defineBeatsRule(rock, scissors);
classicRPS.defineBeatsRule(paper, rock);
classicRPS.defineBeatsRule(scissors, paper);
return classicRPS;
}
}
Just add RPSSystem.EVERYONE_DIES and defineEveryoneDiesRule(...) and you're ready for
rps.add(atombomb);
rps.defineBeatsRule(atombomb, scissors);
rps.defineBeatsRule(atombomb, rock);
rps.defineBeatsRule(atombomb, paper);
rps.defineEveryoneDiesRule(atombomb, atombomb);
Use an enum for dealing with it (RPSObj) that has a beats(RPSObj o) method, with each enum element having a Set passed in, stored as beatset. Then, the beats(RPSObj o) method can do return beatset.contains(o);. Simples :)
Edit: You can actually use an EnumSet as the Set implementation, which should be even more efficient than other set implementations :)
You might want to take a look at this thread:
Using inheritance and polymorphism to solve a common game problem
It seems to be around the same subject.
I think personally I would simply have a utility-like class that would contain the 'beats' method. The 'beats' method would take two GameObject objects as parameters.
That way I could just pass in the two objects (rock, paper or scissors) and perform the necessary logic. Now if you add a new object, you don't change anything other than the 'beats' method within the utility class keeping things encapsulated from your main.
ryan's link is nice, it contains several other ideas for handling this situation as well.
So here's how I fixed it. I first made a new interface called GameObject since they refer to it!
public interface GameObject
{
public boolean beats(GameObject g);
}
The type didn't exist so referring to it wasn't going to work so great.
Here's my new code for Rock with comments on changes:
import java.util.*;
import java.lang.*;
public class Rock implements GameObject //Need to be an instance of GameObject somehow!
{
public static void main(String args[])
{
}
public boolean beats(GameObject object) //This isn't static anymore
{
boolean result = false; //Need to declare and initialize result
if (((Object)object).getClass().getName().equals("Rock")) //getClass should have ()
{
result = false;
}
else if (object.getClass().getName().equals("Paper")) //getClass should have ()
{
result = false;
}
else if(object.getClass().getName().equals("Scissors")) //getClass should have ()
{
result = true;
}
return result;
}
}
EDIT: You seemed to be asking for how to fix the code and not the better way to do it. I believe this should be good to go for you now.