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...
Related
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)
I'm learning to code java and I encountered some problems in which I could use help understanding how things work.
I've made a list containing "Images", on my Main class, called "myList".
public class Main{
public static void main(String[] args) {
List<Images> myList = new ArrayList<Images>();
...
And I want to access it on this "System" class. But it doesn't seem to let me.
The plan is to access a position (the 3rd, in this example) on the given list (list.get(2)).
So I created the method "work".
//Example
public class System{
public static boolean work(List<Images> list){
if( list.get(2).equals(Something) )
return false;
else ... return true;
}
On this same System class I'm trying to use the method "work", giving it the List that I created on my Main class (myList).
public class System{
...
if( work(myList) ) //Don't know how to reffer to myList
return something;
Gives me the error "myList cannot be resolved to a variable".
So the problem is how to reffer to the list I made on my Main, named "myList".
Not sure if I explained that too well but any suggestions?
Make a List a property of System class, then pass it in the constructor
public class System {
private List<Images> images;
public System(List<Images> images) {
this.images = images;
}
//your other methods
}
Ah, in your main you should also pass the list:
System system = new System(myList);
Another option its to make myList public static and access it like this:
Main.myList
Declare one helper class and declare your list with setter and getters. Mainatin a singleton object of this class and use that list then in different other classes.
you need to make sure its accessible.
Right now your list is scoped the main() function. which is static to boot.
You need to make it accessible. You can do this by storing it in a static variable and having a static function return it.
Or you pass the main object along to other object, so they can access it.
public class Main {
private List<Images> myList = new ArrayList<Images>();
public static void main(String[] args) {
new Main(args);
}
public Main(String[] args) {
myList.add('foo.png');
myList.add('bar.png');
System mySystem = new System(this);
}
public List<Images> getImages() {
return myList();
}
}
public class System{
Main global;
public System(Main main) {
global = main;
}
public void doSomething() {
Iterator<Images> it = global.getImages().iterator();
while(it.hasNext()) {
Images images = it.next();
}
}
}
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.
I'm beginning at Java, so the thinking behind organizing my code so it's cohesive isn't really coming naturally yet. Essentially, I have an ArrayList that has a method that populates it, another that shuffles it, and then a tester program to see if that even worked. My problem is organizing it. From my experience methods can't really see what's in each other, so I have it organized like so:
Class
ArrayList (named al)
Tester Method
Shuffle Method
ArrayList Population Method
My trouble is thusly; how do I, in the tester method, make the ArrayList undergo the actions defined for it in the methods. I've worked with Constructors and Objects, but they don't really seem to apply at least is what I've done so far. I thought it would be something like
al.Shuffle();
But it threw errors all over the place. Does anyone have any insight?
EDIT: as requested, here's the code
package deckofcards;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Deck{
ArrayList<String> al = new ArrayList<String>();
//test method
public void main(String[] args){
Scanner input = new Scanner(System.in);
al.Deck();
//didn't get any further, that threw a "cannot find symbol" error
}
}
private void Shuffle(){
Collections.shuffle(al);
}
private void Deck(){
al.add(0, "Ace of Spades");
//and this goes on for a deck of cards
}
}
In Your components, the class is the main component that holds the rest of your component, then the methods is a task or action that the class can do.
ArrayList is a data structure that holds a data with a specific structure. which the class can use it.
so you orginization could look like this:
class MyClass {
private ArrayList<String> list = new ArrayList<String>();
public static void main(String[] args) {//Tester Method is the main method, because the execution began from here
}
private void populate() {
//
}
private void shuffle() {
//
}
}
Define another class that extends ArrayList
public class MyArrayList extends ArrayList<Object> {
public MyArrayList(){
super();
}
public MyArrayList shuffle(MyArrayList mal){
Collections.shuffle(mal);
return mal;
}
}
And then define everything as MyArrayList. This will basically be the exact same class as ArrayList with extra functionality you want.
public class Deck {
static MyArrayList al = new MyArrayList();
//test method
public static void main(String[] args){
Scanner input = new Scanner(System.in);
Deck();
al = al.shuffle(al);
//didn't get any further, that threw a "cannot find symbol" error
for(Object i : al)
System.out.println(i);
}
private static void Deck(){
al.add(0, "Ace of Spades");
al.add(1, "1");
al.add(2, "2");
al.add(3, "3");
//and this goes on for a deck of cards
}
}
I am having problems with my program compiling to find a variable. I have two classes for this program currently and my variable lotteryNumbers is in the first class. It is an int array variable though so I am not sure how to insert it in this line of code. This program is a lottery program to let people pick their tickets. Here is the lines of code where I get my first problem of not finding the variable
import java.util.Scanner;
import java.util.InputMismatchException;
public class CashBallTest
{
public static void main(String[]args)
{
Scanner keyboard = new Scanner(System.in);
int kicker;
System.out.println("\t\t\t\tCashLottoBall");
System.out.println("Player picks four numbers from 1 to 33 called LottoCash Balls. LottoCash Ball numbers must be unique from all other LottoCash Balls.");
System.out.println();
System.out.println("The player must also pick a CashBall from 1 to 31.");
System.out.println();
System.out.println("Kicker is a brand new feature you can purchase with your CashBall ticket which lets you get in on an extra drawing.");
System.out.println();
System.out.println();
for(int index=0; index<lotteryNumbers.length; index++)
{
It is from the for(int..... line at the bottom.
Edit*
Here is the first class which is called CashBall and has the variable in it
import java.util.Scanner;
public class CashBall
{
Scanner keyboard = new Scanner(System.in);
int[] lotteryNumbers = new int[4];
int[] kicker = new int[4];
int[] kickerPowerBall = new int[1];
int yourNumbers;
int CashBallPick;
public CashBall(int yourNumbers, int CashBallPick)
{
this.yourNumbers=yourNumbers;
this.CashBallPick=CashBallPick;
}
public int getYourNumbers()
{
return yourNumbers;
}
public int getCashBallPick()
{
return CashBallPick;
}
public void setYourNumbers(int yourNumbers)
{
this.yourNumbers=yourNumbers;
}
public void setCashBallPick(int CashBallPick)
{
this.CashBallPick=CashBallPick;
}
}
You have no variable called lotteryNumbers.
have you defined lotteryNumbers as a protected or public variable in the class in which it is defined
Also you need to include the class int which the variable lotteryNumbers is defined if they are not in the same package
Or you can define a function get_lottery_Numbers() in the class in which it is defined and then call that method in other class.
There is an example here that can help
http://www.roseindia.net/java/javascript-array/call-method-another-class.shtml
In your other class you need to declare a getter for the lotteryNumbers field and then use the getter method to get that field in CashBallTest.
Here is an example. Let's assume your other class is named SomeClazz. It should look like below:-
public final class SomeClazz {
private final int[] lotteryNumbers;
public SomeClazz(int[] lotteryNumbers){
this.lotteryNumbers=lotteryNumbers;
}
public int[] getLotteryNumbers() {
return lotteryNumbers;
}
}
Then in your CashBallTest class, you should have something like below to access lotteryNumbers:-
int[] lotteryNumbers = {1,2,3};
SomeClazz clazz = new SomeClazz(lotteryNumbers);
for(int index=0; index<clazz.getLotteryNumbers().length; index++){
}
Now you have a way to access lotteryNumbers from your other class and hence no longer the unknown symbol error should appear.
If by "lotteryNumbers is in the first class" you mean that there is a field lotteryNumbers in the class CashBallTest, then the way to access it depends on how it's declared. If it is a static variable, you can refer to it by CashBallTest.lotteryNumbers. If it is not static, then you need to create an instance of CashBallTest (let's call it test), and then refer to it by test.lotteryNumbers.
So in your CashBall class, you need:
import java.util.Scanner;
import java.util.InputMismatchException;
public class CashBall
{
// you should probably initialize this variable in your constructor
private int[] lotteryNumbers;
public int[] getLotteryNumbers() { return lotteryNumbers; }
}
This defines a private variable internal to the class called lotteryNumbers and then creates a public method that exposes it to the testing class. Then you need to create a CashBall object in your CashBallTest, and access its lottery numbers. Like:
public class CashBallTest
{
public static void main(String[]args)
{
CashBall test = new CashBall();
for(int index=0; index < test.getLotteryNumbers().length; index++) ;
}
}
We do this to encapsulate the variable such that later we can change the internal variable CashBall uses to store the lotteryNumbers without forcing other classes that use CashBall to change all their code.
For example, I could change:
private int[] lotteryNumbers;
to
import java.util.collections.ArrayList
private ArrayList<Integer> lotteryNumbers;
public int[] getLotteryNumbers() {
int[] returned;
return lotteryNumbers.toArray(returned);
}
Encapsulation is good coding practice, so be sure you get in the habit of encapsulating your privates.
For extra credit, you probably don't want to iterate across the length of the array in your test. This is bad because your test becomes dependent on CashBall having an int[]. If CashBall changes, your test has to change.
To "do it right", you should add methods inside of CashBall that handle "picking lottery numbers" (which I assume is what this first loop is trying to do), "validating lottery numbers", and "playing with kicker. Then your testing class would become like this:
import java.util.Scanner;
import java.util.InputMismatchException;
public class CashBallTest
{
CashBall toTest;
public static void main(String[]args)
{
toTest = new CashBall(); // add parameters here as necessary
toTest.collectUserLotteryNumbers(); // put the Scanner stuff in here. Make the menu its own void method that's called from here
if(toTest.validateUserNumbers() == false) {
throw new InputMismatchException("Numbers must be between 1-31, and cannot be repeated");
}
}
}
As you gain more experience coding, you'll find yourself writing them like this:
public class CashBallTest
{
CashBall toTest;
public static void testUserCollection()
{
toTest = new CashBall(); // add parameters here as necessary
toTest.collectUserLotteryNumbers(); // put the Scanner stuff in here. Make the menu its own void method that's called from here
if(toTest.validateUserNumbers() == false) {
throw new InputMismatchException("Numbers must be between 1-31, and cannot be repeated");
}
public static void main(String[]args)
{
testUserCollection();
}
}
}
This allows you to break up each thing you're testing into its own particular method, making it easy to add individual tests or modify them without breaking other stuff in your main method. Once you get in this practice, you'll be ready to learn about Unit Testing frameworks like JUnit.