Hi!

I have a super class called character, subclass player.
when i compile, i get this error:
constructor Room in class Room cannot be applied to given types;
from this bit of code in Character:

public Character(Room room, String name)

    this.name=name;
    currentRoom = room;
    Room currentRoom = new Room(); // here is the problem

the thing is that Room needs arguments to be passed to it (description for the constructor)
the problem is that i need to use an insttance of room "currentRoom" instansiatied from the main class Game,

following a similar post from before, the solution is to pass an instance of Game to Character, and then
call a method from Game in Character.

My problem is that Character is an Abstract class, so the player and (enemy or whatever) is gonna use the current room
plus, I will have the same problem for all the other classes, and it would seem like a bad programming practice to have
two methods for every task I want (one in Game, and the other in Character).
i ran the program without initializing Room in character, and when i typed command look, this is the code from Player:

public void look(Command command)

    if(command.hasSecondWord()) 
        // an error message if there was a second word
        System.out.println("You can't enter a second with look");
        System.out.println("Look is used to know what room you are in, the exits and the availabe items");
        return;

    else

    System.out.println(currentRoom.getLongDescription()); ---- problem in here
    System.out.println(currentRoom.listOfItems());

because currentRoom is not defined in Player?
i guess I have serious problems in understanding inheritance and OOP! any help will be much appreciated!
Thank you for your time!

currentRoom = room;
Room currentRoom = new Room(); // here is the problem

Why creating a new room there, can't you just use the one passed to the constructor?

Also, could you clarify the following, not sure if I understand it:

My problem is that Character is an Abstract class, so the player and (enemy or whatever) is gonna use the current room
plus, I will have the same problem for all the other classes, and it would seem like a bad programming practice to have
two methods for every task I want (one in Game, and the other in Character).
i ran the program without initializing Room in character, and when i typed command look, this is the code from Player

To get a better idea it might be helpful if you could also post your other code.

Edited 3 Years Ago by mvmalderen

yeah, i guess you are right! but how can i make the one passed in the constructor to be the same as the one instancetiated by Class Game?

here is

yeah, i guess you are right! but how can i make the one passed in the constructor to be the same as the one instancetiated by Class Game?

here is the code for Character:


/**
 * Write a description of class Character here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Character
{

    private Room currentRoom;
    private Item item;
    private String name;
    private String description;
    private String location;
    private Parser parser;

    /**
     * Constructor for objects of class Character
     */
    public Character(Room room, String name)
    {
        this.name=name;
        currentRoom = room;
        Room currentRoom = new Room();

        // initialise instance variables

    }

    /**
     * An example of a method - replace this comment with your own
     * 
     * @param  y   a sample parameter for a method
     * @return     the sum of x and y 
     */
    public String getName()
    {
        // put your code here
        return name;
    }

    /**
     * a method to return the location of the character
     */
    public String getLocation()
    {
        return currentRoom.getDescription();

    }


    /**
     * a method to return a description of the character
     */
    public String getDescription()
    {
        return description;
    }

    /**
     * a method to set current position/location for the character
     */
    public void setRoom(Room room)
    {
        currentRoom= room;
    }
}


and for player:


/**
 * Write a description of class Player here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Player extends Character
{

    // instance variables - replace the example below with your own
    private Inventory playerInventory;
    private Room currentRoom;


    /**
     * Constructor for objects of class Player
     */
    public Player(Room room, String name, Inventory playerInventory)
    {
        super(room, name);
        playerInventory=this.playerInventory;




    }

    /**
     * adding a look method as a command to check if there are any items in the room, plus the room and its exits. 
     * If a second word is entered, an error message pops up accordingly.
     * @param command: is the second word of the entered by the user.
     */
    public void look(Command command)
    {
        if(command.hasSecondWord()) {
            // an error message if there was a second word
            System.out.println("You can't enter a second with look");
            System.out.println("Look is used to know what room you are in, the exits and the availabe items");
            return;
        }

        else
        {
        System.out.println(currentRoom.getLongDescription());
        System.out.println(currentRoom.listOfItems());
    }
    }

    /**
     * eat command, prints a simple message as an output. If a second word is entered, 
     * an error message pops up accordingly.
     * @param command: is the second word of the entered by the user.
     */
    public void eat(Command command)
    {
        if(command.hasSecondWord()) {
            // an error message if there was a second word
            System.out.println("you can not enter a second word with eat");
            System.out.println("eat is used to eat without specifiying what");
            return;
        }
        else
        {
        System.out.println("You have eaten now and you are not hungry anymore");
    }
    }

    /**
     * inspect method, to return details about specific items available in the room. 
     * If the item is not in the room or unknown, an error message is printed accordingly.
     * @param command: is the second word of the entered by the user.
     */
    public void inspect(Command command)
    {
        if(!command.hasSecondWord()) {
            // if there is no second word, we don't know where to go...
            System.out.println("Inspect what?");
            return;
        }
        String itemInspected = command.getSecondWord();

        //if the item is not known, an error message pops up accordingly
        //if the item is not present in the room, an error message pops up accordingly      
        System.out.println(currentRoom.itemDetails(itemInspected));
    }

    /**
     * Method to take items
     */
     public void takeItem(Command command)
     {
         if (!command.hasSecondWord()){
                // if there is no second word, we dont know which item to take
                System.out.println("Which Item 9otli ya mja9ji9?");
                return;
         }
         String itemToBePicked = command.getSecondWord();

         playerInventory.addItemToInventory(itemToBePicked);
         if (playerInventory.canBePicked(itemToBePicked))
         {
             currentRoom.removeItem(itemToBePicked);
         }

         return;
     }

    /**
     * method to drop items
     */
        public void dropItem (Command command)
        {
            if (!command.hasSecondWord()){
                // if there is no second word, we dont know which item to take
                System.out.println("Which Item 9otli ya mja9ji9 you want to drop?");
                return;
            }
            String itemToBeDropped = command.getSecondWord();

            playerInventory.dropItemFromInventory(itemToBeDropped);

            return;
        }

     /**
      * a method for inventory info
      */
        public void inventoryInfo()
        {
            System.out.println(playerInventory.getInventoryInformation());
        }

    }

    and for game:

    import java.util.Set;
import java.util.HashMap;
import java.util.Stack;
import java.util.ArrayList;


/**
 *  This class is the main class of the "Adventure of a Student" application. 
 *  "Adventure of a Student" is a very simple, text based adventure game.  Users 
 *  can walk around some scenery. Enter and leave rooms, and inspect different items.
 * 
 *  To play this game, create an instance of this class and call the "play"
 *  method.
 * 
 *  This main class creates and initialises all the others: it creates all
 *  rooms, items and creates the parser and starts the game.  It also evaluates and
 *  executes the commands that the parser returns.
 * 
 * @author  Mustafa Gaja-mg348
 * @version 2012.11.13
 */

public class Game 
{
    private Parser parser;
    private Room currentRoom;
    private Room previousRoom;
    private Room nextRoom;
    private Inventory playerInventory;
    private Stack roomsVisited;
    private ArrayList<String> directions; 
    private HashMap<String, Room> rooms;
    private Player protagonistPlayer;




    /**
     * Create the game and initialise its internal map.
     */
    public Game() 
    {
        createRooms();


        parser = new Parser();
        roomsVisited = new Stack<Room>();
        String p = "Mustafa";
        protagonistPlayer = new Player(currentRoom, p, playerInventory);




    }

    /**
     * Create all the rooms and link their exits together. 
     * Create items and put them in specific rooms.
     */
    private void createRooms()
    {
        Room outside, theatre, pub, lab, office, disco, restuarant, cafe, bathroom;
        Item ipad, iphone, computer, waterBottle, ipod, sandwich, toothBrush, camera, lens, stappler, projector;

        // create the rooms
        outside = new Room("outside the main entrance of the university");
        theatre = new Room("in a lecture theatre");
        pub = new Room("in the campus pub");
        lab = new Room("in a computing lab");
        office = new Room("in the computing admin office");
        disco = new Room("in the dance club");
        bathroom = new Room("in the bathroom");
        restuarant = new Room("in the resuarant");
        cafe = new Room("in the cafe");

        //create a hashmap with the room names and the corresponding room object
        rooms =  new HashMap<String, Room>();
        rooms.put("outside", outside);
        rooms.put("theatre", theatre);
        rooms.put("pub", pub);
        rooms.put("lab", lab);
        rooms.put("office", office);
        rooms.put("disco", disco);
        rooms.put("bathroom", bathroom);
        rooms.put("restuarant", restuarant);
        rooms.put("cafe", cafe);

        //creat inventory
        playerInventory = new Inventory(this);


        //create the item
        waterBottle = new Item("waterBottle", "A bottle of water to drink", 20);
        ipod = new Item("ipod", "To listen to music", 10);
        ipad = new Item("ipad", "To read magazines and books", 10);
        iphone = new Item("iphone", "To use as a phone", 18);
        computer = new Item("computer", "To analyse data", 27);
        toothBrush = new Item("toothBrush", "To brush your teeth",5 );
        stappler = new Item("stappler", "To staple papers",8 );
        sandwich = new Item("sandwich","To eat",10);
        projector = new Item("projector", "To present data",25 );
        camera = new Item("camera", "To take photos",12 );
        lens = new Item("lens", "To magnify small things",7 );

        //add items to the allitems list
        playerInventory.addItemToAllList("waterBottle", waterBottle);
        playerInventory.addItemToAllList("ipod", ipod);
        playerInventory.addItemToAllList("ipad", ipad);
        playerInventory.addItemToAllList("computer", computer);
        playerInventory.addItemToAllList("iphone", iphone);
        playerInventory.addItemToAllList("toothBrush", toothBrush);
        playerInventory.addItemToAllList("stappler", stappler);
        playerInventory.addItemToAllList("sandwich", sandwich);
        playerInventory.addItemToAllList("projector", projector);
        playerInventory.addItemToAllList("camera", camera);
        playerInventory.addItemToAllList("lens", lens);



        //creates a list with the availabe directions
        directions = new ArrayList<String>();
        directions.add("south");
        directions.add("north");
        directions.add("east");
        directions.add("west");
        directions.add("up");
        directions.add("down");



        // initialise room exits
        //initialise items per room

        outside.setExits("east", theatre);
        outside.setExits("south", lab);
        outside.setExits("west", pub);
        outside.addItem(camera);

        theatre.setExits("west", outside);
        theatre.setExits("up", cafe);
        theatre.addItem(projector);

        pub.setExits("east", outside);
        pub.setExits("down", disco);
        pub.addItem(waterBottle);

        lab.setExits("north", outside);
        lab.setExits("east", office);
        lab.setExits("down", bathroom);
        lab.addItem(computer);
        lab.addItem(ipad);
        lab.addItem(lens);

        office.setExits("west", lab);
        office.setExits("up", restuarant);
        office.addItem(stappler);
        office.addItem(iphone);

        bathroom.setExits("east", disco);
        bathroom.setExits("up", lab);
        bathroom.addItem(toothBrush);

        disco.setExits("up", pub);
        disco.setExits("west", bathroom);
        disco.addItem(ipod);

        restuarant.setExits("north", cafe);
        restuarant.setExits("down", office);

        cafe.setExits("south", restuarant);
        cafe.setExits("down", theatre);
        cafe.addItem(sandwich);

        currentRoom = outside;  // start game outside
    }

    /**
     *  Main play routine.  Loops until end of play.
     */
    public void play() 
    {            
        printWelcome();

        // Enter the main command loop.  Here we repeatedly read commands and
        // execute them until the game is over.

        boolean finished = false;
        while (! finished) {
            Command command = parser.getCommand();
            finished = processCommand(command);
        }
        System.out.println("Thank you for playing.  Good bye.");
    }

    /**
     * Print out the opening message for the player.
     */
    private void printWelcome()
    {
        System.out.println();
        System.out.println("Welcome to Adventures of a Student!");
        System.out.println("Adventures of a Student is a new adventure game.");
        System.out.println("It allows you to discover the scenery of the university, look for items, and inspect them");
        System.out.println("When hungry you can eat!");
        System.out.println("Type 'help' if you need help.");
        System.out.println();
        printLocationInfo();
        }


    /**
     * Given a command, process (that is: execute) the command.
     * @param command The command to be processed.
     * @return true If the command ends the game, false otherwise.
     */
    private boolean processCommand(Command command) 
    {
        boolean wantToQuit = false;

        if(command.isUnknown()) {
            System.out.println("I don't know what you mean...");
            return false;
        }

        String commandWord = command.getCommandWord();
        if (commandWord.equals("help"))
            printHelp(command);
        else if (commandWord.equals("go"))
            goRoom(command);
        else if (commandWord.equals("back")) 
            goBack(command);
        else if (commandWord.equals("inspect"))
            inspect(command);
        else if (commandWord.equals("take"))
            takeItem(command);
        else if (commandWord.equals("drop"))
            dropItem(command);
        else if (commandWord.equals("teleport"))
            teleport(command);
        else if (commandWord.equals("rooms"))
            rooms(command);
        else if (commandWord.equals("look"))
            look(command);
        else if (commandWord.equals("eat"))
            eat(command);
        else if (commandWord.equals("inventoryInfo"))
            inventoryInfo();
        else if (commandWord.equals("quit"))
            wantToQuit = quit(command);

        return wantToQuit;
    }

    // implementations of user commands:

    /**
     * Print out some help information.
     * Here we print some a cryptic message and a list of the 
     * command words. If a second word is entered, an error message pops up accordingly.
     */
    private void printHelp(Command command) 
    {
        if(command.hasSecondWord()) {
            // an error message if there was a second word
            System.out.println("You can't enter a second with look");
            System.out.println("Help is used to indicate your situation");
            System.out.println("and what are the availabe commands for use");
            return;
        }

        else
        {
        System.out.println("You are lost. You are alone. You wander");
        System.out.println("around at the university.");
        System.out.println();
        System.out.println("Your command words are:");
        System.out.println(parser.showCommands());
    }
}


    /** 
     * Try to go to one direction. If there is an exit, enter
     * the new room, otherwise print an error message. If the direction is not known, 
     * an error message pops up accordingly.
     * @param command: is the second word of the entered by the user.
     */
    private void goRoom(Command command) 
    {
        if(!command.hasSecondWord()) {
            // if there is no second word, we don't know where to go...
            System.out.println("Go where?");
            return;
        }

        String direction = command.getSecondWord();
        nextRoom = currentRoom.getExit(direction);

        //if there is no room on a known direction, it checks if the direction is a known word
        //if the direction is known, a message says that there is no door
        if (nextRoom == null) 
        {
            int n=directions.size();
            for (int i=0 ; i<n ; i++)
            {
                String x = directions.get(i);
                if (x.equals(direction))
                {
                System.out.println("There is no door!");
                return;
            }
        }
        //if the direction is not known, it prints unknown direction
        System.out.println("unknown direction");
    }
    //if there is a room in that direction, change the current room to the next room and print location info.
    else
        {
            roomsVisited.push(currentRoom);
            currentRoom = nextRoom;
            printLocationInfo();
            return;
        }
    }


    /** 
     * "Quit" was entered. Check the rest of the command to see
     * whether we really quit the game.
     * @return true, if this command quits the game, false otherwise.
     */
    private boolean quit(Command command) 
    {
        //checks if there is a second word
        if(command.hasSecondWord()) {
            System.out.println("You can't enter a second word with quit");
            return false;
        }
        else {
            return true;  // signal that we want to quit
        }
    }

    /**
     * print a long description of the current room and the availabe exits
     */
    private void printLocationInfo()
    {
         System.out.println(currentRoom.getLongDescription());

    }

    /**
     * adding a look method as a command to check if there are any items in the room, plus the room and its exits. 
     * If a second word is entered, an error message pops up accordingly.
     * @param command: is the second word of the entered by the user.
     */
    private void look(Command command)
    {
        protagonistPlayer.look(command);
    }

    /**
     * eat command, prints a simple message as an output. If a second word is entered, 
     * an error message pops up accordingly.
     * @param command: is the second word of the entered by the user.
     */
    private void eat(Command command)
    {
        protagonistPlayer.eat(command);
    }

    /**
     * inspect method, to return details about specific items available in the room. 
     * If the item is not in the room or unknown, an error message is printed accordingly.
     * @param command: is the second word of the entered by the user.
     */
    private void inspect(Command command)
    {
       protagonistPlayer.inspect(command);
    }


    /**
     * Teleport method allows teleportation to a specified room. If the room is not known,
     * an error message pops up accordingly.
     * @param command: is the second word of the entered by the user.
     */
    private void teleport(Command command)
    {
         if(!command.hasSecondWord()) {
            // if there is no second word, we don't know where to go...
            System.out.println("Teleport where?");
            return;
        }

        String roomName= command.getSecondWord();
        nextRoom = rooms.get(roomName);

        if (nextRoom == null)
        {
            System.out.println("There is no room with such name!");
            System.out.println("Maybe you want to check the availabe rooms");
            System.out.println("you can do that by typing rooms");

        }
        else
        {
            currentRoom = nextRoom;
            System.out.println("Seccesful Teleportation!");
            printLocationInfo();
            return;
        }
    }

    /**
         * Method to take items
         */
        private void takeItem(Command command)
        {
            protagonistPlayer.takeItem(command);
        }

    /**
         * method to drop items
         */
        private void dropItem (Command command)
        {
             protagonistPlayer.dropItem(command);
        }

    /**
     * a method for inventory info
     */
    private void inventoryInfo()
    {
         protagonistPlayer.inventoryInfo();
    }

    /**
     * rooms method is used to show the availabe rooms in the scenery.
     * @param command: is the second word of the entered by the user.
     */
    private void rooms(Command command)
    {
        if(command.hasSecondWord()) 
        {
            // an error message if there was a second word
            System.out.println("You can't enter a second word with rooms");
            System.out.println("rooms is used to know the availabe rooms in the scenery");
            return;
        }

        else
        {
            String returnString = "Rooms: ";
            Set<String> keys = rooms.keySet();
            for (String x : keys)
            {
                returnString += " " + x;
            }
            System.out.println(returnString);

        }
    }

     /**
     * Go back to the previous room, if invoked twice, it go back in track, 
     * if there are no rooms back, prints a message accordingly.
     * @param command: is the second word of the entered by the user.
     */
    private void goBack(Command command) 
     {
        if(command.hasSecondWord()) {
            // an error message if there was a second word
            System.out.println("Invalid entry, you can not enter a second word with back");
            return;
        }

        if (roomsVisited.empty()) {
            //an error message if there were no back rooms, i.e. the start of the game
            System.out.println("There is no door!");
        }
        else {
            currentRoom = (Room) roomsVisited.pop();
            printLocationInfo();
        }
    }

    /**
     * a method to be called by Inventoy to check item availabe in currentRoom
     */
    public boolean checkAvailability(String itemToBePicked)
    {
        return currentRoom.checkItem(itemToBePicked);
    }
}

Take a look at your Character class:

public class Character
{
    private Room currentRoom;

    ...

    // the currentRoom is passed in via the Constructor
    public Character(Room room, String name)
    {
        this.name = name;
        currentRoom = room; // here currentRoom is set
        Room currentRoom = new Room(); // no need for this line, remove it
    }

    ...
}

Now take a look at your Player class:

public class Player extends Character // inheritance!
{
    private Inventory playerInventory;
    private Room currentRoom;

    public Player(Room room, String name, Inventory playerInventory)
    {
        super(room, name);
        playerInventory = this.playerInventory;
    }

    ...
}

Now you've got two options:

  1. Remove the currentRoom field from your Player class and create a protected getter method for the currentRoom field in the Character class,
    and call it from Player everytime you need the currentRoom.
    (You lose some encapsulation here though)

  2. Add the line this.currentRoom = room; to the Player constructor.

Also notice that the following line in your Player constructor won't have the intented effect: playerInventory = this.playerInventory;
It should be: this.playerInventory = playerInventory; instead.
The explanation goes as follows: whenever you have a parameter variable in your method whose identifier (= name) is the same as the identifier (= name) of one of the attributes in your class, <identifier> will refer to the method parameter, and this.<identifier> will refer to the instance variable of your class. In other words, you are assigning the value of your instance variable to the method parameter, but it should be the other way around!

Edited 3 Years Ago by mvmalderen

well, the answer was very helpful! it is working now
thank you very much!

Edited 3 Years Ago by mumaga

I understand your concern about sharing the same currentRoom. But when you think about it... it doesn't make alot of sense to keep a reference to the currentRoom in both Game and Player.

I'd like to point out some more things though:

  1. Players know their location, so they have a field that references the currentRoom they are in. This is now the responsability of a Player. So it does not make alot sense anymore to keep currentRoom in the Game class. (Think about extensibility: multiple Players in the same Game!)
  2. Players know their Inventory, it is their responsability. Not the responsability of the Game class. So, you can take this field out of the Game class as well.
  3. Similarly Players know where they have been, so the roomsVisited field belongs in the Player class.
  4. What's the purpose of the nextRoom field? From a quick look at the code I would think that this one better had been a local variable in a method.
  5. Once you got your undo stack roomsVisited, do you really need to keep a reference to previousRoom? Won't it be the top stack element of roomsVisited?
  6. You use class Stack, this is a legacy datastructure in Java, and it extends from Vector (another legacy datastructure - still used in Swing however), my personal recommendation would be not to use it. Prefer something more recent like ArrayDeque.

    On an interesting note:

    • "This class is likely to be faster than Stack when used as a stack, and faster than LinkedList when used as a queue." (Java API - ArrayDeque))

    • "A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class." (Java API - Stack)

Edited 3 Years Ago by mvmalderen

you are def right about the extendibility thing, but I am trying to do is to keep
all the "editable" things in Game, like the name of the rooms and the names of the items.
I feel it is a better practice to have only one class where you want to make the changes in (and by changes i mean the name of the room etc)
or that is not how it works in real life?

just noticed, because I passed currentRoom to (protagonistPlayer an object of class Player) when the player goes from room to another room, the object protagonistPlayer is not updated with the currentRoom, it takes only the first declaration of it (currentRoom = outside in my case) and even if I go to another room, and want to display items, I get the items from outside,
I am using Player to do those tasks.

I feel it is a better practice to have only one class where you want to make the changes in

No, not really. That will distort the class structure and force data items into one central class regardless of where they logically belong. Focus on words like "has a", eg a room has a name. That tells you that "name" should probably be an attribute (instance variable) of Room.
In general terms, the "normal" class structure for something like this has a minimum of stuff in Game. Everything about a player is in the Player class, everything about a room is in the Room class, etc etc. The Game class just sets it all up and keeps master lists of Rooms, Players etc, and only handles stuff that doesn't logically fit anywhere else. Tux4life is making the same point with the first 3 items of his last post.

ps Just read your second post that you posted while I was still typing. It's a classic example of what tux & I are saying. A Player has a current location (room). A Player decides to go in some particular direction from the Room he's currently in, as a result of which he gets a new location. That's something that a Player does in conjuction with the info that's in the Room class. There's no reason there why the Game class needs to be involved in that.

Edited 3 Years Ago by JamesCherrill: ps

yeah, I get what you are saying, I guess I have to do some restructuring and parsing some code out from Game.
Thank you for the prompt response!

This question has already been answered. Start a new discussion instead.