Variables (possibly) get out of scope - java

Ok, so have two classes Player and child class Classes. I use the child class to set the player stats inside main class through switch statement that lets user choose his class. But for some reason the set variables fall out of scope when executed in main class. For the love of me, I can't figure why is it happening
Here is the Player class:
public class Player {
private int HP;
private int ATK;
private int DEF;
private int DAMAGE;
void setHP(int a){
HP=a;
}
void setATK(int a){
ATK=a;
}
void setDEF(int a){
DEF=a;
}
void setDAMAGE(){
DAMAGE = damageCalculation();
}
int damageCalculation(){
int damage = (2*ATK);
return damage;
}
Player(String Class){
Classes classes = new Classes();
switch(Class){
case "Barbarian":
classes.Barbar();
System.out.println("Done");
break;
case "Rogue":
break;
default: System.out.println("Error");
}
}
void getStats(){
System.out.format("Player stats:"
+ "\nHP: %d"
+ "\nATK: %d"
+ "\nDEF: %d"
+ "\nDAMAGE: %d\n",HP,ATK,DEF,DAMAGE);
}
}
Here is the Classes class(note that in child class get stats return valid values):
public class Classes extends Player {
public void Barbar(){
Player player = new Player();
player.setHP(60);
player.setATK(15);
player.setDEF(25);
player.setDAMAGE();
player.getStats();
}
}
And here is the main class:
import java.util.Scanner;
public class SurvivalGame {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in,"Windows-1250");
System.out.println("Enter your class");
Player player = new Player(scan.nextLine());
player.getStats(); //here getStats return zeros,
//possibly out of scope variables if player enters Barbarian
}
}

public void Barbar(){
Player player = new Player();
If you look closely you are creating a new Player and adding values to that, not the Player in main method.

You're creating an extra instance of Player that is never accessed. Just walk through your code:
/* Main Method */
// You get a new Player object using direct user input
// (Which is somewhat dangerous, you should do some data validation first)
Player player = new Player(scan.nextLine())
/* Player constructor */
// Let's say user entered correctly "Barbarian". You are in the process of constructing
// a new Player object when you call this:
classes.Barbar();
/* Barbar method */
// The very first line creates a brand new player - different from one you were
// in the process of constructing.
Player player = new Player();
// Then you assign values to the new Player, which goes out of scope as soon as the
// method ends.
Instead of having Classes extend Player (which seems a bit odd to me, to be honest), I'd just make the Barbar method belong to the Player class itself (which can then be called during your switch statement). Then you can just modify the current Player's values directly, instead of relying on a different class to do that for you.
For example:
public class Player
{
public Player(String class)
{
switch (class)
{
case "Barbarian":
Barbar();
break;
}
}
public void Barbar()
{
HP = 60;
ATK = 15;
DEF = 25;
setDAMAGE();
}
}

When you extend a class, you get something that is an instance of the superclass, but with the extra methods and fields that you choose to add in the subclass. So when you write
public class Classes extends Player {
//...
}
Your Classes instances already have the HP (etc.) fields in them. Your Barbar method can modify them without needing to create a new instance of Player:
public void Barbar(){
setHP(60);
setATK(15);
setDEF(25);
setDAMAGE();
getStats();
}
You're confusing composition and inheritance.

Related

Why can I not access an instance of class that is created in a constructor ( Java )

To preface the question, I'm very new to Java.
I have classes called, Game, Player, and SystemIO.
My main() is in the Game class. Below is it's code
public static void main(String[] args){
SystemIO systemIO = new SystemIO();
}
Once SystemIO is called, it's constructor creates an instance of Player with the line
Player player = new Player("Bob");
where the Player constructor takes 1 argument as a String.
Further down in the SystemIO class I have a method that accesses information from "player" the instance.
player.getName();
When I try to do this, the console reports
SystemIO.java:339: error: cannot find symbol
I have checked that I am not trying to reference the class name with a capital "Player."
Like I said, I'm extremely new to Java and just trying to wrap my head around it and I believe it's a scope issue...but I'm not sure.
Edit to add reproducible code:
Game.java
package com.myapps;
import com.myapps.system.SystemIO;
public class Game{
public static void main(String[] args){
SystemIO systemIO = new SystemIO();
}
}
Player.java
package com.myapps.player;
public class Player{
String name;
public Player(String playerName){
name = playerName;
}
}
public String getName(){
return name;
}
SystemIO.java
package com.myapps.system;
import com.myapps.player.Player;
public class SystemIO{
public SystemIO(){
Player player = new Player("Bob");
readPlayerName();
}
public void readPlayerName(){
System.out.println(player.getName());
}
}
Make player a class variable.
Put someone in your class:
Player player;
and change the code of your constructor to:
player = new Player("Bob");
This is called a scope error. A variable that you want to be accessable to ALL the methods of the class, should be declared IN the class and not in ONE specific method (in your case, you did it in the constructor)

How do you pass an updated global class variable from one method into another?

I update a variable (which is global in the class) in one method and I cannot seem to be able to then pass that updated variable into another method.
Any help would be appreciated, thank you.
Here's my shortened code:
public class Game{
private int randomIndexX;
protected String spawn(){
randomIndexX = randomGenerator.nextInt(10);
return null;
}
protected String test(){
System.out.println(this.randomIndexX);
return null;
}
}
public class Player extends Game{
protected String getNextAction(String command) {
switch(command){
case "test":
test();
break;
}
}
}
public static void main(String[] args) {
Game game = new Game();
Player player = new Player();
game.spawn();
player.getInputFromConsole();
}
EDIT: so when i call test() from the Player class i want it to print out randomIndexX but it still doesn't seem to be working even with this.randomIndexX in the method test()
EDIT: so when i call test() from the Player class i want it to print out randomIndexX but it still doesn't seem to be working even with this.randomIndexX in the method test().
So test() is instance method, which means you'll have to make an instance of Class Game in order to call that method, your randomIndexX is instance member so you need to think well what you want to do, IF randomIndexX is common for all the objects of Game class, you should declare it static as in:
private static in randomIndexX;
As it's value won't change depending on an object instance.
So in order to access that variable from outside of the class since it's private you declare a public method to retrieve that value (getter or also known as accessor):
public static int getRandomIndex(){
return randomIndexX;
}
So when in main, you don't even have to make an instance of the Game class to access value that's being held in randomIndexX, you just call the getter method like this:
System.out.println(Game.getRandomIndex());
The line above will print 0 to the console as 0 is default value for members of type int, now if you want to be able to change it, you just make a setter or mutator method in Game class as well:
public static void setRandomIndex(int n){
randomIndexX = n;
}
And there you go, you can now set and retrieve "randomIndexX" field from outside of the Game class.
For example, the code below will set value of randomIndexX to 5 and then print it in the console:
Game.setRandomIndex(5);
System.out.println(Game.getRandomIndex());
The first problem I can see is that you don't have a constructor.(Optional)
(If you don't make one the compiler makes what is called a "Default" constructor which is a constructor without any parameters. Its usually good practice to explicitly create a class constructor.
The second problem I can see is that you missing the end bracket.
Fix shown below.
public class Game
{
private int randomIndexX;
protected String spawn()
{
randomIndexX = 0;
return null;
}
protected String test()
{
System.out.println(randomIndexX);
return null;
}
}
You can construct it and trigger any methods you wish:
Game game = new Game();
game.spawn();
game.test()

Creating and passing objects java

Trying to understand how to correctly access and pass other objects within a program using java.
In my little program we see the following:
I have a combat class that will need to know the current HP of my hero, which is an instance of my Hero class.
Previously, if another class needed to know the hero's HP, I would simply use a static variable to store HP. I was told this was incorrect usage of static. Below, I created a method in combat for the explicit use of passing the hero into combat. Thus, going forward, any time I need combat to access anything related to my hero object, I can.
Does this make sense? Am I on the right path?
public class Combat
{
public void passHero(Hero hero1)
{
}
}
public class Main
{
public static void main(String args[])
{
Hero hero1 = new Hero();
//passing hero to Combat
combat.passHero(hero1);
}
}
You are on the right track. When you want to set attributes on an object (in this case the Hero attribute of Combat), that object (Combat) usually provides public methods for setting and retrieving its attributes. You probably want to just create a hero setter on the combat class, or pass the hero in to a constructor
public class Combat
{
private Hero hero;
//setter
public void setHero(Hero hero1)
{
this.hero = hero1;
}
//constructor
public Combat(Hero hero1)
{
this.hero = hero1;
}
}
public class Main
{
public static void main(String args[])
{
Hero hero1 = new Hero();
//passing hero to Combat
Combat combat = new Combat(hero1);
//or
combat.setHero(hero1);
}
}

Accessing public variables in the main class within other classes

I am trying to port my game I made in Python to Java. In the Python version, I had all the methods and variables in one "class" and players were a dictionary like this:
game.py
...
new_player={"name":"","hp":0,...}
players=[]
//to add new player
players.append(new_player.copy())
Player's data values are then added separately:
...
players[0]["name"]="bob"
players[0]["hp"]=50
...
In the Java version, I have a separate class used to define a Player object, as well as a main method for the game.
For example (this is a small version):
game.java (returns omitted)
import java.utils.*;
public class game
{
public static ArrayList<player> players = new ArrayList<player>();
public static ArrayList<String> pdead = new ArrayList<String>();
public static int turn = 0;
public static void main(String[] args)
{
//do stuff
players.add(new player(name));
//do other stuff
}
public static void do_move(move)
{
//some move is selected
players.get(turn).set_hp(10);
//at this point compiler throws error: cannot find symbol
//compiler does not recognize that a player should have
//been added to the players variable
//other stuff
};
};
player.java (returns omitted)
public class player
{
//arbitrary list of private variables like hp and name
public player(new_name)
{
name = new_name;
//other variables defined
};
public void set_hp(int amount) //Adding hp
{
hp += amount;
};
public void set_hp(int amount,String type) //taking damage
{
mana += amount;
//go through types, armor, etc.
hp -= amount;
};
public void display stats() //displays all player's stats before choosing move
{
//display stats until...
//later in some for loop
System.out.println(players.get(index).get_hp());
//here compiler throws error again: cannot find symbol
//players arraylist is in main class's public variables
//other stuff
};
//other stuff
};
Supposedly, when the two classes-to-be are compiled together, the program will be able to run since the main variables are public and player variables are defined as the program goes on. However, the compiler does not recognize this and throws errors since the classes (in the same directory, by the way) do not read each other and objects are not "defined" in the array/arraylist while checking it.
How do you get the variables to be seen by the compiler as defined? I can upload the current working version of both classes and the final python version if need be, but I like to keep my games closed-source.
EDIT: fixed ArrayList initialization according to sjkm's reply
Define the generic type of your lists:
change
public static ArrayList players = new ArrayList<player>();
public static ArrayList pdead = new ArrayList<String>();
to
public static ArrayList<player> players = new ArrayList<player>();
public static ArrayList<String> pdead = new ArrayList<String>();
otherwise you always have to cast the objects you get from the list...

How do I call a constructor?

I am currently done making a sokoban game with GUI and everything and I am working on optimzation, I would like to keep the objects as sensible as possible and therefore need to be able to call the constructor from a method in the class/object. Suppose:
public class BoardGame() {
public BoardGame)() {
this(1)
}
public BoardGame(int level){
//Do stuff, like calling filelevel-to-board loaderclass
}
How do I create a method that calls the constructor of this object/class in the object/class itself? Eg:
public BoardGame nextLevel() {
return BoardGame(currentLevel+1);
}
The above is apparently undefined!
Such that if I want to use this object in another class I should be able to do:
GameBoard sokoban = new GameBoard(); //lvl1
draw(GameBoard);
draw(GameBoard.nextLevel()); //draws lvl2
You need to use the new keyword to call the constructor.
public BoardGame nextLevel() {
return new BoardGame(currentLevel + 1);
}
Calling the constructor requires the new keyword and always creates a new instance. For instance, in your example code
GameBoard sokoban = new GameBoard(); //lvl1
draw(sokoban );
draw(sokoban.nextLevel()); //draws lvl2
sokoban <-- still level 1
Maybe you want the GameBoard to be mutable:
public class GameBoard {
public GameBoard() {
setLevel(1);
}
private void setLevel(int i) {
currentLevel = i;
....
}
public void nextLevel() {
setLevel(currentLevel+1);
}
}

Categories

Resources