I'm building a simulation game using Java. I have an interface, "Critter" and an abstract class "AbstractCritter". All of my "critters" are defined using these two.
Critter
public interface Critter {
// create constants
// each holds a unique integer value
final int NORTH = 1;
final int WEST = 2;
final int SOUTH = 3;
final int EAST = 4;
final int CENTER = 5;
// create abstract methods
public char getChar();
public int getMove(CritterInfo theInfo);
}
AbstractCritter
public abstract class AbstractCritter implements Critter{
// create char to hold a particular critter
private char critterChar;
public AbstractCritter(final char theChar) {
critterChar = theChar;
}
public char getChar() {
return critterChar;
}
}
Example critter:
public class Stone extends AbstractCritter {
public Stone(char S) {
super(S);
// This is the main constructor for stone
}
public int getMove(CritterInfo theInfo) {
// The stone cannot move.
return 5;
}
}
And the main loop:
public final class CritterMain {
/** private constructor to inhibit instantiation. */
private CritterMain() {
// Do not instantiate objects of this class
throw new IllegalStateException();
}
/**
* The start point for the CritterMain application.
*
* #param theArgs command line arguments - ignored
*/
public static void main(String[] theArgs) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
CritterFrame frame = new CritterFrame();
frame.add(100, Stone.class);
frame.add(50, Bat.class);
frame.add(25, Frog.class);
frame.add(25, Mouse.class);
frame.add(25, Turtle.class);
frame.add(25, Wolf.class);
frame.start();
}
});
}
}
Whenever I try to run the main CritterMain, I get this weird error I can't find anywhere on google: "Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: no zero-argument constructor for class Stone"
It has something to do with how I am defining my critters. Can anyone help me figure this out?
When you make an instance of a class, you may use one of the available constructors.
A constructor may have no arguments, or more than zero arguments.
In case you don't declare a constructor with no argument and attempt to instantiate a class with no arguments, you obviously get an an error.
So just making a constructor with no arguments, will stop the error.
Related
I have created an array which I wanted to control from main. My code runs, but I don't know how to add integers to the array from the main class. Also as each ConcreteSubject has its own storage array, how would i change this to store them all in the same array?
public class ConcreteSubject extends AbstractSpy
{
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy s) {
if (i < spies.length) {
spies[i] = s;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass
{
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
spies.addSpy(spies);
}
}
It seems like your program logic is a little borked. This bit in particular doesn't make much sense:
***AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
***spies.addSpy(spies);
What you're doing is creating TWO AbstractSpy instances, one named cs and one named spies. On that last line you're adding spies to itself! That doesn't help you at all.
Note that AbstractSpy is the most granular unit in your setup - it shouldn't have an addSpy() method and its own internal array, it should be the thing that's added to something else's array!
Here's the same code, but cleaned up a bit:
public abstract class AbstractSpy { }
public class ConcreteSpy extends AbstractSpy { }
public class ConcreteSubject {
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy spy) {
if (i < spies.length)
{
spies[i] = spy;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass {
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spy = new ConcreteSpy();
cs.addSpy(spy);
}
}
The big difference here is that ConcreteSpy is an implementation of AbstractSpy that you can add to your ConcreteSubject's array of spies. I think you might have been confused by Java's insistence that you can't create an instance of an abstract class on its own unless you supply an anonymous class that inherits from the abstract class.
I apologize if this is a basic question.
I am attempting to create several unique objects in one class, then get the values of one of the objects in another class.
I have created two classes and followed some examples to end with this
public class Type {
public String name;
public int healthmod;
public int strmod;
public int accmod;
public int armmod;
public int refmod;
public int intmod;
public String advantages;
public String disadvantages;
public Type() {
Type fire = new Type();
fire.name = "Fire";
fire.healthmod = 0;
fire.strmod = 1;
fire.accmod = 0;
fire.armmod = 0;
fire.refmod = 0;
fire.intmod = 1;
}
}
and then in the main class:
Player.typename = Type.fire.name;
Edit
public class Player {
public static String name, classname, racename, elementname;
public static int maxhealth, healthpts, healthptscost, healthupgnum, healthmod, currenthealth, basehealth;
public static int str, strpts, strptscost, strupgnum, strmod;
public static int acc, accpts, accptscost, accupgnum, accmod;
public static int arm, armpts, armptscost, armupgnum, armmod;
public static int ref, refpts, refptscost, refupgnum, refmod;
public static int intelligence, intpts, intptscost, intupgnum, intmod;
public static int mana, maxmana, managain, managainak;
public static int hitChance, critChance, Level, statPts, statTotal, damage, damageDealt, goldmult, itemmod, itemdefboost, itemdamboost, itemmodboost;
public static String[] focusStats;
}
What I am trying to do is create a few objects in the Type class and access them in the Main class in order to store the values in the Player class, but in the Main class, fire "cannot be resolved or is not a field"
Edited to provide more clarity on the purpose.
You are completely mixing things here.
In the concstructor of Type you are creating a new local Object named fire. This object is only available in this constructor and not outside of it, e.g. in the main class.
A valid solution can only be found if you give more information about what you try to accomplish.
I could write like that your Type construct:
public Type() {
this.name = "Fire";
this.healthmod = 0;
this.strmod = 1;
this.accmod = 0;
this.armmod = 0;
this.refmod = 0;
this.intmod = 1;
}
So when using the Player class in your Main method, like that:
public static void main(String args[]) {
Type type = new Type();
Player.typename = type.name;
}
You can also put a reference of type inside Player class like that:
public class Player {
public static Type fire;
}
So in your main method like that:
public static void main(String args[]) {
Player.fire = new Type();
System.out.println(Player.fire.name);
}
this is my first time using Java and I seem to be stuck. I'm trying to access a method (getHeading) from a subsystem (DriveTrain) in a command (DriveStraight), but I keep getting the error that "the type getHeading(double) is undefined for the type Subsystem" when I try heading = Robot.DriveTrain.getHeading();. This is the command:
public class DriveStraight extends Command {
private double speed;
private double duration;
private double heading;
public DriveStraight(float driveSpeed, float duration) {
requires(Robot.DriveTrain);
**heading = Robot.DriveTrain.getHeading();**
}
// Called just before this Command runs the first time
protected void initialize() {
setTimeout(duration);
}
// Called repeatedly when this Command is scheduled to run
protected void execute() {
**float currentheading = Robot.DriveTrain.getHeading();**
Robot.DriveTrain.arcadeDrive(speed, (heading - currentheading) * 0.08);
}
And this is the subsystem:
public class DriveTrain extends Subsystem {
AnalogGyro gyro;
RobotDrive drive;
VictorSP frontLeftMotor, rearLeftMotor, frontRightMotor, rearRightMotor;
public DriveTrain() {
frontLeftMotor = new VictorSP(RobotMap.frontLeftMotor);
rearLeftMotor = new VictorSP(RobotMap.rearLeftMotor);
frontRightMotor = new VictorSP(RobotMap.frontRightMotor);
rearRightMotor = new VictorSP(RobotMap.rearRightMotor);
gyro = new AnalogGyro(RobotMap.analogGyro);
gyro.setSensitivity(0.00666);
gyro.calibrate();
}
public void arcadeDrive(float speed, float turn) {
drive.arcadeDrive(OI.joy.getRawAxis(OI.LEFT_Y_AXIS),
OI.joy.getRawAxis(OI.RIGHT_X_AXIS), true);
}
public void tankDrive(float leftValue, float rightValue) {
drive.tankDrive(OI.joy.getRawAxis(OI.LEFT_Y_AXIS),
OI.joy.getRawAxis(OI.RIGHT_Y_AXIS), true);
}
public double getHeading() {
return gyro.getAngle();
}
protected void initDefaultCommand() {
arcadeDrive(0, 0);
}
}
I just came from using C++ so I think I might be trying to use pointers, but I'm not sure. So what's the right way to call a method from a subsystem?
Thanks,
Sethra53
You're not managing an instance of Robot.DriveTrain anywhere - all your method calls on the DriveTrain class are being seen by the compiler as calls to static methods (which don't relate to an object, only to the class). The nearest matching method you have defined anywhere is public double getHeading() {, which is an instance method and so should be called on an instance. There are 4 places in your code which are referring to Robot.DriveTrain and I'm not sure what your requires method is doing so it's tricky to know what you should be passing to it. The other three places, however, should be referring to instances of Robot.DriveTrain.
e.g.
public class DriveStraight extends Command {
private double speed;
private double duration;
private double heading;
private Robot.DriveTrain driveTrain;
public DriveStraight(float driveSpeed, float duration) {
requires(Robot.DriveTrain);
driveTrain = new Robot.DriveTrain() // create new shared instance
heading = driveTrain.getHeading(); // use instance.
}
// Called just before this Command runs the first time
protected void initialize() {
setTimeout(duration);
}
// Called repeatedly when this Command is scheduled to run
protected void execute() {
float currentheading = driveTrain.getHeading(); // use instance created in constructor.
driveTrain.arcadeDrive(speed, (heading - currentheading) * 0.08);
}
...
I can't guarantee any of that will 'work' however, without understanding how the requires method call works.
A better approach would be to pass the instance in to the DriveStraight constructor...
public class DriveStraight extends Command {
private Robot.DriveTrain driveTrain;
public DriveStraight(float driveSpeed, float duration, DriveTrain driveTrain) {
this.driveTrain = driveTrain; // use instance created elsewhere
...
When I'm trying to create a new object from a class I previously defined, I keep getting a "cannot find symbol" error, and there's an arrow pointing towards the "S" in the first "SnowFallReport" in my constructor. I've had this problem when trying to create other objects in other programs and I just wanna throw my laptop! I feel like it's a simple solution, I just don't know what it is.
The code follows:
import java.util.Random;
public class SnowfallReport
{
// Random amount of snow
private double snowAmount;
// Default constructor creates random amount and assigns to snowAmount
public void SnowFallReport()
{
Random snowFall = new Random();
snowAmount = (snowFall.nextDouble()) * 20;
}
public double getSnow()
{
return snowAmount;
}
public void getStars()
{
for (int starAmount = 0; starAmount == snowAmount; starAmount++)
{
System.out.print("*");
}
}
public static void main(String[] args)
{
**SnowFallReport day1 = new SnowFallReport();**
}
}
java is case sensitive language SnowfallReport != SnowFallReport
your class name is SnowfallReport thus you create your object like:
SnowfallReport ref = new SnowfallReport ();
also, constructor name should be the same as class name and they don't have return type not even void.
// Default constructor creates random amount and assigns to snowAmount
public void SnowFallReport()
{
should be
public SnowfallReport()
{
I'm having a problem where I receive this error:
Exception in thread "main" java.lang.NullPointerException
at com.noxia.Main.startCombat(Main.java:101)
at com.noxia.Area1.createArea1Enemy(Area1.java:43)
at com.noxia.Main.main(Main.java:30)
I know that I need to initialize the variables because they are null, but I can't seem to figure out what I need to put where. I've minimized the code to show just the relevant parts as there are many other variables and methods left out, but this seems to pertain to the issue. Any help would be greatly appreciated =)
public class Main {
Player p;
Enemy e;
Area1 a1;
public static void main(String[] args) {
Main main = new Main();
main.a1 = new Area1();
main.p = new Player(100);
//the line directly below this is line 30 where the error occurs
main.a1.createArea1Enemy(10);
}
public void startCombat()
{
//the line directly below this is line 101 where the error occurs
while (p.getCurrentLife() > 0 & a1.e.getLife() > 0)
{
p.playerAttack();
if (p.getCurrentLife() > 0 & a1.e.getLife() > 0)
{
e.enemyAttack();
}
}
}
public class Player extends Main {
private int currentLife;
public int getCurrentLife()
{
return currentLife;
}
public void setCurrentLife(int cl)
{
currentLife = cl;
}
public Player(int cl)
{
currentLife = cl;
}
public class Enemy extends Main {
private int life;
public int getLife()
{
return life;
}
public void setLife(int lf)
{
life = lf;
}
public Enemy (inf lf)
{
life = lf;
}
public class Area1 extends Main {
public void createArea1Enemy(int enemyCounter)
{
while (enemyCounter > 0)
{
String[] enemyList = {"Enemy1", "Enemy2"} //code for Enemy2 left out below
int enemyListLength = enemyList.length;
int randomEnemy = (int) (Math.random() * enemyListLength);
if (enemyList[randomEnemy].equals("Enemy1"))
{
Enemy enemy1 = new Enemy("Enemy1", 100);
//the line directly below this is line 43 where the error occurs
startCombat();
}
enemyCounter--;
}
}
}
The simple answer is that you have to set e to an enemy before calling startCombat.
But a better way to do this would be to remove e, and pass the enemy object to startCombat using a method parameter. The e field is conceptually wrong. To understand the wrongness, try to come up with a coherent explanation of what it means in terms of the state of a Main object.
Clearly this is beginner code ... and there are a number of bad things about what you have written:
The fields of a class should be for object state, not for passing parameter values to methods.
You should avoid writing code that accesses the innards of a class ... like your main method does.
Best practice is to make fields private, and defined getter and / or setter methods (as required) for external classes to access / modify them.
You need to learn how to write constructors with parameters.
You need to design your code properly. Everything extending Main means that there is going to be no rational model of what the objects "mean". And there's the problem that each instance of Enemy and Area1 will have their own copies of the p, e, and a1 fields, and a whole bunch of inappropriate methods.
The main problem is that you never initialize Enemy e;. You create an enemy but never assign it to this.e.
Change this line:
Enemy enemy1 = new Enemy("Enemy1", 100);
To this:
this.e = new Enemy("Enemy1", 100);
There are also many other problems with your code.
Learn how to write a constructor properly. This code is wrong.
I see no reason at all why a Play, Area1, and Enemy should extend Main.