How to access variables from another method - java

I have a class named "Game" in Java, and the aim/goal is to reach a certain room, the "throne" room. When the throne room is reached the game ends.
public class Game {
// fields
private Room currentRoom;
private boolean finished;
private Room throne;
/**
* Create the game and initialise its internal map.
*/
public Game()
{
finished = false;
createRooms();
}
/**
* Create all the rooms and link their exits together.
*/
private void createRooms()
{
Room gate, graveyard, church, crypt, entrance, hall, kitchen, buttery, greathall, staircase,
dungeon, topstaircase, throne, solar, wardrobe, privy;
// create the rooms
gate = new Room("outside the old gate of the castle");
graveyard = new Room("on a wind-swept gaveyard");
church = new Room("in a small ancient church");
throne = new Room("in the throne room with golden walls");
// other rooms ...
// initialize room exits
gate.setExit("north", graveyard);
throne.setExit("south", topstaircase);
// other exits ...
}
}
To go in one direction/room :
public String goRoom(String direction)
{
assert direction != null : "Game.goRoom gets null direction";
// Try to leave current room.
Room nextRoom = currentRoom.getExit(direction);
if (nextRoom == null) {
return "There is no exit in that direction!";
} else {
currentRoom = nextRoom;
return currentRoom.getLongDescription();
}
}
To go into a specific room to end the game i.e "throne" room here's what I did :
if (currentRoom.equals(throne)) {
finished = true;
return "Congrats you have reached the throne room";
}
But I keep getting this error : cannot find symbol - variable throne
This is a project based on the "Object first with Java using blueJ"

Instead of declaring the Room throne in your private void createRooms(), you can declare it as a field, so right after the constructor you can say Room throne;, you can then still initialize it in your createRooms method.
You could consider making it final because it won't change anymore and that clearly states the intention
In this case I wouldn't pass it to the next parameter, to me it would make sense to have it as a field
Edit: on the topic of your unreachable statement comment, what I suspect you're doing is checking for the finished state of the game after your following code:
} else {
currentRoom = nextRoom;
return currentRoom.getLongDescription();
}
Because you're already returning from the method here, you're never actually checking for the end state of the game.

You are storing your Rooms as local variables. These variables are deleted as soon as your method terminates, so the Rooms will disappear.
To solve this, you should declare your variables at the class level:
public class Game {
private Room currentRoom;
private boolean finished;
private Room Goal;
private Map<String, Room> rooms;
public Game() {
finished = false;
rooms = new HashMap<>();
createRooms();
}
//....
private void createRooms() {
rooms.put("gate", new Room("outside the old gate at the castle"));
//similar for other rooms
//...
}
Then, you can access your rooms by defining a function
public Room getRoom(String roomName) {
if (rooms.containsKey(roomName))
return rooms.get(roomName);
throw new IllegalArgumentException("No such room: " + roomName);
}
For example:
if (currentRoom.equals(getRoom("throne")) {
finished = true;
return "Congrats you have reached the throne room";
}
If goRoom() is not in Game, you will need to get an instance of Game first, and then call getRoom() on that instance.

But I keep getting this error : "cannot find symbol - variable
throne". I believe i need a field somewhere but I am unsure where and
how this is useful.
You are getting this error because variable throne is a local variable whose scope is just inside the method it is declared
private void createRooms()
{
Room gate, graveyard, church, crypt, entrance, hall, kitchen, buttery, greathall, staircase,
dungeon, topstaircase, throne, solar, wardrobe, privy;
// create the rooms
gate = new Room("outside the old gate of the castle");
graveyard = new Room("on a wind-swept gaveyard");
church = new Room("in a small ancient church");
throne = new Room("in the throne room with golden walls");// local variable
// other rooms ...
// initialise room exits
gate.setExit("north", graveyard);
throne.setExit("south", topstaircase);
// other exits ...
}
Now Instead of making it local you can make it as instance variable or class variable so it can be accessible , if you wish to make this variable as private instance variable then provide getters and setters to access this variable's value .

Related

Using arrayList pointers instead of multiple loops?

I am trying to write a program that contains many classes and in one class called "Dorm",I have an arrayList of Blocks,and in the "Block" class,I have an arrayList of Rooms,and in the "Room" class,I have an arrayList of "Students".
I am trying to access the number of available rooms(the rooms that at least have one empty space) through another class called the "Manager class". I have been told that I can just create another arrayList in the manager class to be used as a pointer and search up the empty rooms of the whole dormitory.
My question is,how is this going to work?
ps:This is what I wrote:
public static void availableRooms() { //Shows the available rooms in the dormitory.
Dorms dormitory = new Dorms();
Room room1 = new Room();
for(int i=0;i<dormitory.getBlocks().size();i++)
for(int j=0;j<Block.getRoomList().size();j++) {
if(!(room1.getStudentList().get(room1.getRoomCapacity()).equals(null)))
System.out.print("/t" + room1.getStudentList().get(i) + "/t");
}
}
My code isn't complete yet,so I'm not sure if it works...
Could you share your code/tentative? and clearly specify what's not working?
This being said, unless tied to specific constraints, one should make use of encapsulation and single responsibility principle (see SOLID on wiki) by keeping implementation details private and delegating tasks to the more relevant classes.
You may have something like:
class Dorm {
private List<Block> blocks = ...
...
public int getAvailableRooms() {
int total = 0;
for (Block b : blocks) {
total += b.getAvailableRooms();
}
return total;
}
}
class Block {
private List<Room> rooms = ....
...
public int getAvailableRooms() {
int total = 0;
for (Room r : rooms) {
if (! r.isFull()) {
total++;
}
}
}
class Room {
private int capacity = ...
private List<Student> students = ..
...
public boolean isFull() {
return capacity == students.size();
}
}
Where the Manager class, holding (an) instance(s) of Dorm, just make use of the getAvailableRooms() method which behind the scene delegate to the underlining Blocks and aggregate result... and so on.

How to make an array of objects that creates new accounts when called?

I need help on a programming assignment. The class of BankAccount already exists and works as it should. I have never been asked to place objects into arrays before, and am having trouble doing so.
I have started with the following:
public class Bank
{
private BankAccount[] Bank;
public Bank(BankAccount[] Bank)
{
BankAccount[] b1 = new BankAccount[10];
}
Although it compiles, it is wrong. I am not sure where to go.
The following are the requirements of the code that I am currently stuck on.
An object of class Bank can hold up to 10 BankAccount objects.
The constructor for the Bank object will create an array that can hold up to 10 BankAccount objects.
The following code is the test program that our professor included with the assignment that we must use:
System.out.println("\nCreate bank1");
Bank bank1 = new Bank();
System.out.println("\nOne account");
BankAccount b1 = new BankAccount("Joe Mac", 1234);
b1.adjust(1000.0);
bank1.addAccount(b1);
bank1.printAccounts();
System.out.println("\nTwo accounts");
BankAccount b2 = new BankAccount("Sally Ride", 2345);
b2.adjust(2000.0);
bank1.addAccount(b2);
bank1.printAccounts();
System.out.println("\nThree accounts");
BankAccount b3 = new BankAccount("Pat Armstrong", 3456);
b3.adjust(3000.0);
bank1.addAccount(b3);
bank1.printAccounts();
System.out.println("\nMonthly Fee");
bank1.monthlyFee(fee);
bank1.printAccounts();
System.out.println("\nErrors:");
Help would be immensely appreciated. Thank you.
You just have to add a method to add a new account and test that it doesn't go more bigger than 10:
public class Bank
{
private BankAccount[] accounts; //Don't name variables with uppercase
private int accountsPointer; //This is going to keep track of how many accounts are there in the array
public Bank() //The constructor doesn't need to accept any bank account since it'll start as empty
{
accounts = new BankAccount[10]; //Here we initialize the array
accountsPointer = 0; //Here the pointer starts as 0 since the array is empty
}
public void addAccount(BankAccount account){
accountsPointer++;
if(accountsPointer<10){ //We test it here so it won't throw an out of bounds exeption
accounts[accountsPointer-1]=account;//It assigns the account to the next empty space on the array
}
}
You can use below code to solve your problem.
class Bank {
private static final int MAX_NO_OF_ACCOUNT = 10;
private int pointer = 0;
private BankAccount[] bank;
public Bank() {
bank = new BankAccount[MAX_NO_OF_ACCOUNT];
}
public void addAccount(BankAccount bankAccount) throws Exception {
if (pointer == MAX_NO_OF_ACCOUNT) {
throw new Exception("No of bank account reached max no"); // you should own custom exception
} else {
bank[pointer] = bankAccount;
pointer++;
}
}
}
Explanation :
As per requirements, one Bank object can hold max 10 account. I have put it in available name MAX_NO_OF_ACCOUNT as I know it is constant. static final variables in Java known as constant. Also, it gives the flexibility to change the max no of account easily (as that may use in multiple places). I have to make it private as I don't want to expose that value outside the class. However, I believe that should be more configuration driven. The pointer variable will always point to the last added element index so that I can check before add. Let come to the constructor. When I carate a Bank object I have initialized the BankAccount[] array which can hold MAX_NO_OF_ACCOUNT of account.
Now addAccount method:
I made the addAccount method as the checked exception as I think the user of that API/Class can add more than max no of account. If such case happens we force to handle such situation.

Java element of a new List using a Set

I have the method changePlayer() that sets an element from the set players from the class Model as the value of the field currentPlayer of Model; since I can't get elements directly from a set, so I created a new ArrayList using that set.
What I want to know is that if that element created is still using the reference from the old one or has a new reference and therefore any change I make to it will not change the original element from the set created in Model.
public class Model extends Observable<Change> {
private Set<Player> players;
private Player currentPlayer;
public Model() {
players = new HashSet<Player>();
}
public void addPlayer(Player player) {
currentPlayer = player;
this.players.add(player);
}
public Set<Player> getPlayers() {
return Collections.unmodifiableSet(this.players);
}
public Player getCurrentPlayer() {
return currentPlayer;
}
public void setCurrentPlayer(Player currentPlayer) {
this.currentPlayer = currentPlayer;
}
}
public void changePlayer(Model game) {
Player player2 = new Player(0);//the id in this case is 0
//this is the part of the code where i create a list using the set
List<Player> playersList = new ArrayList<Player>(game.getPlayers());
for (int i = 0; i < playersList.size(); i++) {
... // some code that will set player2 by player2 = playersList.get(i)
}
// change the current player for the game
game.setCurrentPlayer(player2);
}
You're only creating a new List, but the references in the List are still the same references(the reference values are copied but the values still point to the same instances of Player, which is similar to no matter how many times of your passport number is copied, the number still identifies you). Thus, if you change the referenced Player in your method, you're actually changing the Player in your original Model, which is obvious, since you haven't created any new Player in your method body, have you? The Player instances won't just magically be copied since they are not primitive types. There will be only one exception that you're actually cloning all the Player instances, which is in your game.getPlayers(), you actually deep copied every Player. However, this is not what programmers would usually do.

Java Inheritance - Getting a Parameter from Parent Class

I'm trying to take one parameter from the parent class of Car and add it to my array (carsParked), how can i do this?
Parent Class
public class Car
{
protected String regNo; //Car registration number
protected String owner; //Name of the owner
protected String carColor;
/** Creates a Car object
* #param rNo - registration number
* #param own - name of the owner
**/
public Car (String rNo, String own, String carColour)
{
regNo = rNo;
owner = own;
carColor = carColour;
}
/** #return The car registration number
**/
public String getRegNo()
{
return regNo;
}
/** #return A String representation of the car details
**/
public String getAsString()
{
return "Car: " + regNo + "\nColor: " + carColor;
}
public String getColor()
{
return carColor;
}
}
Child Class
public class Carpark extends Car
{
private String location; // Location of the Car Park
private int capacity; // Capacity of the Car Park - how many cars it can hold
private int carsIn; // Number of cars currently in the Car Park
private String[] carsParked;
/** Constructor for Carparks
* #param loc - the Location of the Carpark
* #param cap - the Capacity of the Carpark
*/
public Carpark (String locations, int room)
{
location = locations;
capacity = room;
}
/** Records entry of a car into the car park */
public void driveIn()
{
carsIn = carsIn + 1;
}
/** Records the departure of a car from the car park */
public void driveOut()
{
carsIn = carsIn - 1;
}
/** Returns a String representation of information about the carpark */
public String getAsString()
{
return location + "\nCapacity: " + capacity +
" Currently parked: " + carsIn +
"\n*************************\n";
}
}
Last Question Method
public String getCarsByColor (String carColour)
{
for (int num = 0; num < carsParked.length; num++)
{
if ( carColour.equals(carsParked[num]) )
{
System.out.print (carsParked[num]);
}
}
return carColour;
}
I have this so far so that if "red" is put in the parameters, it would list all the cars with the color red and it's corresponding information but does not seem to work ~_~.
You seem to have the wrong relationship here: a car park is not a car. I would recommend against using inheritance in either direction between these classes. And Carpark should probably just have an array or collection of cars.
Also note that the parameter carsIn isn't necessary - just get the length of the array of cars (or size() if it's a Collection).
Edit: Okay, ignoring the inheritance part, it seems like it makes sense to add cars when driveIn is called, and remove them when driveOut is called.
driveIn should probably take a Car as an argument, so the method can access the parameter you want to store (personally I would just store Car references, but fine). Since we're going to be adding and removing these parameters, it'll be much easier to use a List that can resize itself instead of an array, like ArrayList. For example:
private final List<String> carsRegNosParked = new ArrayList<String>();
public void driveIn(Car car) {
carsRegNosParked.add(car.getRegNo());
}
It's less clear what driveOut should do. It could take a specific registration number to remove:
public void driveOut(String regNo) {
carsRegNosParked.remove(regNo);
}
Or it could just indiscriminately remove a car, say the first car added:
public void driveOut() {
if (!carsRegNosParked.isEmpty()) {
carsRegNosParked.remove(0);
}
}
Note the difference between remove(Object) and remove(int).
First change carsParked to a list. So:
private String[] carsParked;
becomes
private List<String> carsParked;
Then in you constructor initialize it to an empty list by doing:
carsParked = new ArrayList();
Then in your drive in method, make it take a car parameter and pull the param you want:
public void driveIn(Car car) {
carsParked.add(car.getRegNo());
}
Also you do not need to keep track of the number of cars this way. Since you could always do carsParked.size() to find out.
Now I would probably change that list to be List<Car> instead of string and just dump the whole car in there. Sure you may only need one item right now, but who knows down the road, maybe you will need something else.
EDIT:
Sure you could do it with an simple array. The issue with that is sizing. Say you initially create an array of size 5, when you go to add the 6 item you will need to create a new larger array, copy the original data, then add the new item. Just more work. Now if the idea is you have a carpark, and it can have X number of spots then you initilize your array to that size from the begining.
public Carpark (String locations, int room){
location = locations;
capacity = room;
//this creates an array with the max number of spots
carsParked = new String[capacity];
//also good idea to init
carsIn = 0; //initial number of cars parked
}
then in your driveIn() method:
public void driveIn(Car car) {
carsParked[carsIn] =car.getRegNo();
carsIn=carsIn+1;
}
now driveOut()
public void driveOut(Car car) {
//loop through the array until we find the car
for (int i=0; i < carsParked.length; i=i+1){
if (car.getRegNo().equals(carsParked[i])){
//we found the car, so set the space null
carsParked[i] = null;
carsIn=carsIn-1;
//stop looping now
break;
}
}
}
Looks nice doesn't it. Well no it is not. Now the driveIn will not work, since we have null spots scattered all over the place. How do we fix it:
public void driveIn(Car car) {
//loop through the array until we find a null spot,
//then park the car
for (int i=0; i < carsParked.length; i=i+1){
if (carsParked[i] == null){
//we found the car, so set the space null
carsParked[i] = car.getRegNo();
carsIn=carsIn+1;
//stop looping now
break;
}
}
}
It could still be improved further. I would probably still change String[] carsParked to Car[] carsParked as to not throw away information.
I would also change the driveIn and driveOut methods to return booleans to indicate if the successfully parked or un-parked a car.
Final Edit:
Okay, if you want to keep track of what cars are parked in the car park and which spot they are in you need to know enough about each car to make it unique. In your case you may only need regNo. So when you call driveIn or driveOut you have to pass that information so we can store it at the appropriate index (parking spot) in the array. Otherwise all you will know is a car was parked somewhere, or that a car left. Not which spots are open.
So in short the parameter Car car in those two methods contain the information needed to uniquely identify each car that is being parked, or is leaving. Without it the car park instance would have no clue who is currently parked, or where they are parked.

How to make different instances of a class?

I am making a simple programm that allows people to checkin and out a hotel (for my CS class).
What I need to be able to do is check in a person in a room. There are four rooms. How can i make it so that when someone is checked in, the next person that checks in will check in room 2.
i have the following already:
class Hotel {
Room room1, room2, room3, room4;
Hotel() {
room1 = new Room();
room2 = new Room();
room3 = new Room();
room4 = new Room();
}
static checkIn() {
Scanner sc = new Scanner(System.in);
System.out.print("naam:");
String invoer2 = sc.nextLine();
if (room1.guest == null) {
room1.guestst = invoer2;
System.out.println("Guest " + room1.guest + " gets room 1");
return;
} else {
System.out.println("no rom");
}
return;
}
}
class Room {
static int count;
String guest;
Room() {
guest = null;
count--;
}
Room(String newGuest) {
guest = newGuest;
count++;
}
}
class Guest {
String name;
Guest(String newName) {
name = newName;
}
}
To start off, a Hotel has more than one Room. Depending on what you've learnt as far, you should be using an array to hold all Room instances
Room[] rooms;
Hotel() {
rooms = new Room[4];
}
or an ArrayList
List<Room> rooms;
Hotel() {
rooms = new ArrayList<Room>();
}
See also:
Arrays tutorial
Collections tutorial
Update as per your comment: just check every room if it has a guest until you find a room without a guest (like as in real world!). Pseudo:
if there is no guest in room1, then use room1;
else if there is no guest in room2, then use room2;
else if there is no guest in room3, then use room3;
else if there is no guest in room4, then use room4;
else say "sorry, no rooms left!";
This is by the way easier to do in a simple loop when you use an array.
for each room, check if there is no guest in room, then use room;
if there is no room, then say "sorry, no rooms left!";
Oh, don't forget to make the guest null when s/he leaves the room. This will make the room eligible for reuse.
See also:
if-then-else statements
for statement
class Hotel {
Room room1, room2, room3, room4;
Hotel() {
room1 = new Room();
room2 = new Room();
room3 = new Room();
room4 = new Room();
}
}
If you haven't learned an Array yet.
But an Array (or ArrayList) is a better way to do this.
a comment on the static (also noticed by Ishtar).
If you make checkIn static on the Hotel class (and not instance) you are saying that checkIn is the same over all hotels, and not just your hotel. That suggests that if you have 5 hotels, each with its own rooms, all the rooms are alike. So you could checkIn in hotel 1 and get a room from hotel 2. That's really not what you want to do.
public class Hotel {
// stuff
// Check a guest into this hotel
public Room instanceCheckIn(Guest guest) {
//stuff
}
// Check a guest into one of our hotels. It doesn't matter to which
// particular hotel this room belongs :)
public static Room staticCheckIn(Guest guest) {
//stuff
}
}
Usage:
Hotel instanceHotel = new Hotel();
// check a guest into a room of this hotel (instanceHotel)
instanceHotel.instanceCheckIn(someGuest);
// Check a guest into one of the rooms of our hotels
Hotel.staticCheckIn(someGuest);
// Error: cannot call a non-static method on a class
Hotel.instanceCheckIn(someGuest);
// Technically OK, but incredibly bad taste. You suggest something
// is happening with this hotel (called instanceHotel) but in stead
// your actually working on all hotels together (shared data).
instanceHotel.staticCheckIn(someGuest);
In general it's a very good habit to not use static unless you really need it. It suggests something is broken in your domain model. That does not mean you should not use it, but realize that it has a particular odor. (public static void main(String[] args) is of course a special case).
the next person that checks in will
check in room 2
This can't be done right now. Your hotel only has one room! It should have more, 3 for example:
class Hotel {
Kamer kamer1;
Kamer kamer2;
Kamer kamer3;
Hotel (){
kamer1 = new Kamer();
kamer2 = new Kamer();
kamer3 = new Kamer();
}
}
Or better use arraylist
class Hotel {
ArrayList<Kamer> kamers;
Hotel (){
kamers = new ArrayList<Kamer>();//make room-list
kamers.add( new Kamer() );//add one room
kamers.add( new Kamer() );//add one room
kamers.add( new Kamer() );//add one room
//more?
}
}
If you need a hotel with 3 rooms, just call: new Hotel();.
static void checkIn() {
Kamer k1 = new Kamer(g1.naam);
Why are you making a new room when someone wants to check in? You can't just build a new room if you need one, right? If you remove the static you can use the fields kamer1, kamer2 (or kamers if you used the ArrayList).
void checkIn()
{
if (kamer1.guest==null)
//kamer1 is available!
//
//

Categories

Resources