I have two classes Boat and Mines, which have exactly the same methods and variables.
the only difference is that they are Initialized in different positions.
for Boat
xPosition = 3
yPosition = 4
for Mine
xPosition = 1
yPosition = 1
I've been told specifically not to use inheritance for this, what else could I use to improve the design
You could give both of them some sort of location class, give that class the X and Y positions, and make it a property of both the mine and the boat. Sad thing you'll need getters/setters for the location class nevertheless.
The idea of object-oriented programming is for this exact reason.
Boat and Mine should not be classes, they should be new objects made from another class (we'll call it - waterStuff).
class waterStuff {
public xPosition;
public yPosition;
}
... then somewhere in the code you set them to new objects. I don't use Java so I'll do it as close as I can:
(these would probably be inside another class using the waterStuff as a namespace for reference)
Boat = new waterStuff;
Mine = new waterStuff;
Boat->xPosition = 3;
Boat->yPosition = 4;
Mine->xPosition = 1;
Mine->yPosition = 1;
I wish I could be more java-specific but hopefully this gets you on the right track.
EDIT: Don't you just love CS101
If they only differ in the values of their members, inheritance seems somewhat pointless in any case. But having 2 unrelated classes would be worse.
How about something like this?
class SomeClass
{
int xPosition, yPosition;
enum Type
{
Boat, Mine
}
public SomeClass(Type type)
{
if (type == Type.Boat)
{
xPosition = 3;
yPosition = 4;
}
else
{
xPosition = 1;
yPosition = 1;
}
// assign 'type' to a class variable here if required
}
}
Construct using:
new SomeClass(SomeClass.Type.Boat)
or:
new SomeClass(SomeClass.Type.Mine)
You may want to pick a better name than SomeClass.
Related
I have this method called setMonster(), in a class called 'AssetSetter' in a package called 'main', which creates new monsters based on information in another class from a different package called 'MON_GreenSlime'.
SetMonster() inside of the AssetSetter class looks like this(the list is much longer in reality but you get the jig):
public void setMonster(){
gp.monster[0] = new MON_GreenSlime(gp);
gp.monster[0].worldX = gp.tileSize * 26;
gp.monster[0].worldY = gp.tileSize * 20;
gp.monster[1] = new MON_GreenSlime(gp);
gp.monster[1].worldX = gp.tileSize * 22;
gp.monster[1].worldY = gp.tileSize * 18;
gp.monster[2] = new MON_GreenSlime(gp);
gp.monster[2].worldX = gp.tileSize * 24;
gp.monster[2].worldY = gp.tileSize * 17;
}
So inside of the MON_GreenSlime class I have a method called setAction() which sets AI movement to the monster. Inside this setAction() I want to make an if statement that checks the index of the gp.monster[] from the m as its condition. Something along the lines of this(if this would work)
if (gp.monster[index] index == 0){
//do something
}
else if (gp.monster[index] index == 1){
//do something
}
//And so on... (The index is just as an example) Like I explained, I don't know how I would write such an if statement
The individual monsters AI movement is controlled by it's default x and y location, therefore when I create more than 1 monster I feel like I need some sort of if or switch statement to treat each array index individually.
Someone please let me know if you know of a simple solution :) I'm pretty new to Java, so go easy on me if its obvious
I am new to Java, and I am also new to posting a question online. So please bear with me.
I am currently constructing a Java program which displays several canvases, and I require the different canvases to use shared and/or inherited information. Let's assume for simplicity that canvas C1 displays a polygon with random vertices on a circle. Currently these vertices are created in a coordinate class and are then instantiated by a drawing class. I am now trying to store these values in a way which allows the second canvas C2 (via drawing class) to use them, but without instantiating it, as I need the same sequence of random numbers.
Let this be a simplified example of my coordinate class:
public class Coord {
public Complex[] z = new Complex[5];
public Coord() {}
// create n random vertices (length of a and z will match)
public Complex[] randCoord(Complex[] a) {
for(int i = 0; i < a.length; i++){
z[i] = new Complex(200 * Math.random(), 200 * Math.random());
}
return z;
}
// public static Complex[] getCoord() {
// return z;
// }
}
The commented out section is one of my million attempts to generate a static version of the coordinate list, but I am not allowed to return z as it is not a static variable (in this case). I am probably missing something painfully obvious in regard to transferring between static and non-static methods, but any insight on how to store the random sequence (and likewise, how to call it) would be appreciated.
It sounds like the Singleton pattern would be helpful :
public class Coord {
private static final Complex[] z = fixedRandomPoints(5);
private Coord() {}
//this is the method you call from both canvases
public static Complex[] getInstance() {
return z;
}
private static Complex[] fixedRandomPoints(int n) {
final Complex[] results = new Complex[n];
for(int i = 0; i < n.length; i++){
results[i] = new Complex(200 * Math.random(), 200 * Math.random());
}
return results;
}
}
The only thing thats unclear is the relationship of this class to the 'a' variable, which I think you need to explain a little better.
First of all, you should read up on the MVC-pattern: Model-View-Controller.
Secondly, it looks like what you're currently trying to do can simply be done by declaring z to be static:
public static Complex[] z = new Complex[5];
Hey I'm having a problem with 3 lines of coding, and I still don't know what the problem is.
public class HealthBar{
int min = 0;
int max = 100;
JProgressBar PlayerHealth = new JProgressBar(min,max);
JProgressBar EnemyHealth = new JProgressBar(min,max);
PlayerHealth.setStringPainted(true);
}
You can't call this method:
PlayerHealth.setStringPainted(true);
like you're doing inside the class and not in a constructor or method. Instead, make this call in your class's constructor. And again, next time you ask a similar question, please provide all the information needed including the error message.
i.e.,
public class HealthBar {
// it's OK To declare and initialize variables here
int min = 0;
int max = 100;
JProgressBar playerHealth = new JProgressBar(min,max);
JProgressBar enemyHealth = new JProgressBar(min,max);
// but this is not valid
// playerHealth.setStringPainted(true);
// constructor
public HealthBar() {
// instead do it here!!!
playerHealth.setStringPainted(true);
}
}
As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter.
Following these suggestions as well as following good code formatting practices will allow others (such as us!) to better understand your code, and more importantly, will allow your future self to better understand just what you were thinking 6 months ago when you wrote the code.
This question already has answers here:
When to use nested class?
(3 answers)
Closed 9 years ago.
If a function returns 2 values, for example: min/max in array or for example, x and y axis of a point, it would need to create an object, since a function cannot return 2 values.
Now, consider a client whose 'only' function is to use getters in the returned object and print.
AND
The returned object say MinMax or Point object is created only by one class,
Should we use a nested class (eg: MinMax, Point can be nested class) or use a top level class?
This is a generic question - below is just one such example related to the question. Please done answer related to the code sample as it is a very generic question not bound to the sample code.
Should the Point class be inner class returned similar to the way itr is returned by arraylist ?
class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
int getX() {
return x;
}
int getY() {
return y;
}
}
public class IntersectionOf2Lines {
public static Point calculateIntersection(Line line1, Line line2) {
int x = (line2.getConstant() - line1.getConstant()) / (line1.getSlope() - line2.getSlope());
int y = line1.getSlope() * x + line1.getConstant();
return new Point(x, y);
}
Line line3 = new Line(2, 2);
Line line4 = new Line(3, 2);
Point p1 = IntersectionOf2Lines.calculateIntersection(line3, line4);
System.out.println("Expected: x = 0, Actual x = " + p1.getX() + " Expected y=2, Actual y = " + p1.getY());
IMHO it is a matter of style. I would look at it from the point of view of someone who is reading your code from the first time. Which classes do you want to make obvious and which ones do you want to group away and they only need to read when they get into the details.
BTW: A nested class need to be nested inside the scope of another class, not just in the same class file as it is in your example.
I'm trying some Java recently and look for some review of my style. If You like to look at this exercise placed in the image, and tell me if my style is good enought? Or maybe it is not good enought, so You can tell me on what aspect I should work more, so You can help me to improve it?
exercise for my question
/*
* File: MathQuiz.java
*
* This program produces Math Quiz.
*/
import acm.program.*;
import acm.util.*;
public class MathQuiz extends ConsoleProgram {
/* Class constants for Quiz settings. */
private static final int CHANCES = 3;
private static final int QUESTIONS = 5;
private static final int MIN = 0;
private static final int MAX = 20;
/* Start program. Number of questions to ask is assigned here. */
public void run() {
println("Welcome to Math Quiz");
while(answered != QUESTIONS) {
produceNumbers();
askForAnswer();
}
println("End of program.");
}
/* Ask for answer, and check them. Number of chances includes
* first one, where user is asked for reply. */
private void askForAnswer() {
int answer = -1;
if(type)
answer = readInt("What is " + x + "+" + y + "?");
else
answer = readInt("What is " + x + "-" + y + "?");
for(int i = 1; i < CHANCES+1; i++) {
if(answer != solution) {
if(i == CHANCES) {
println("No. The answer is " + solution + ".");
break;
}
answer = readInt("That's incorrect - try a different answer: ");
} else {
println("That's the answer!");
break;
}
}
answered++;
}
/* Produces type and two numbers until they qualify. */
private void produceNumbers() {
produceType();
produceFirst();
produceSecond();
if(type)
while(x+y >= MAX) {
produceFirst();
produceSecond();
}
else
while(x-y <= MIN) {
produceFirst();
produceSecond();
}
calculateSolution();
}
/* Calculates equation solution. */
private void calculateSolution() {
if(type) solution = x + y;
else solution = x - y;
}
/* Type of the equation. True is from plus, false is for minus. */
private void produceType() {
type = rgen.nextBoolean();
}
/* Produces first number. */
private void produceFirst() {
x = rgen.nextInt(0, 20);
}
/* Produces second number. */
private void produceSecond() {
y = rgen.nextInt(0, 20);
}
/* Class variables for numbers and type of the equation. */
private static boolean type;
private static int x;
private static int y;
/* Class variables for equation solution. */
private static int solution;
/* Class variable counting number of answered equations,
* so if it reaches number of provided questions, it ends */
private static int answered = 0;
/* Random generator constructor. */
RandomGenerator rgen = new RandomGenerator();
}
One thing I noticed was that all of your methods take no parameters and return void.
I think it would be clearer if you use method parameters and return values to show the flow of data through your program instead of using the object's state to store everything.
There are a few things you should do differently, and a couple you could do differently.
The things you should do differently:
Keep all fields together.
static fields should always be in THIS_FORM
you've used the static modifier for what clearly look like instance fields. (type,x,y,solution, answered). This means you can only ever run one MathsQuiz at a time per JVM. Not a big deal in this case, but will cause problems for more complex programs.
produceFirst and produceSecond use hardcoded parameters to nextInt rather than using MAX and MIN as provided by the class
There is no apparent need for answered to be a field. It could easily be a local variable in run.
Things you should do differently:
There is a small possibility (however tiny), that produceNumbers might not end. Instead of producing two random numbers and hoping they work. Produce one random number and then constrain the second so that a solution will always be formed. eg. say we are doing and addition and x is 6 and max is 20. We know that y cannot be larger than 14. So instead of trying nextInt(0,20), you could do nextInt(0,14) and be assured that you would get a feasible question.
For loop isn't really the right construct for askForAnswer as the desired behaviour is to ask for an answer CHANCES number of times or until a correct answer is received, whichever comes first. A for loop is usually used when you wish to do something a set number of times. Indeed the while loop in run is a good candidate for a for loop. A sample while loop might look like:
int i = 1;
boolean correct = (solution == readInt("What is " + x + "+" + y + "?"));
while (i < CHANCES && !correct) {
correct = (solution == readInt("Wrong, try again."));
i++;
}
if (correct) {
println("Well done!");
} else {
println("Nope, the answer is: "+solution);
}
Looks like a very clean program style. I would move all variables to the top instead of having some at the bottom, but other than that it is very readable.
Here is something I'd improve: the boolean type that is used to indicate whether we have an addition or subtraction:
private void produceType() {
type = rgen.nextBoolean();
}
produceType tells, that something is generated and I'd expect something to be returned. And I'd define enums to represent the type of the quiz. Here's my suggestion:
private QuizType produceType() {
boolean type = rgen.nextBoolean();
if (type == true)
return QuizType.PLUS;
else
return QuizType.MINUS;
}
The enum is defined like this:
public enum QuizType { PLUS, MINUS }
Almost good I have only a few improvements:
variables moves to the top
Inside produceNumbers and your while you have small repeat. I recommend refactor this
Small advice: Code should be like books - easy readable - in your run() method firstly you call produceNumber and then askForAnswer. So it will be better if in your code you will have the same order in definitions, so implementation askForAnswer before produceNumber. But it isn't necessary
Pay attention to have small methods. A method shouldn't have much to do - I think that askForAnswer you could split to two methods