I would like to make movement of a square with only using Instance Variable. I'm having troubles this is my code :
I have one for Variables.JAVA for Variables :
public class Variables {
String name;
int Playerx;
int Playery;
int Playerw;
int Playerh;
}
and one where it is the main but doesn't change the variables above. (simplified)
public static void main(String args[]) throws InterruptedException {
while (true) {
Variables P = new Variables(){
synchronized (c) {
c.clear();
first_level();
P.Playerx = 50;
P.Playery = 50;
P.Playerw = 100;
P.Playerh = 100;
c.drawRect(P.Playerx, P.Playery, P.Playerw, P.Playerh);
}
Thread.sleep(25);
// Controls
if (c.isKeyDown(Console.VK_UP)) {
P.Playery -= 10;
}
else if (c.isKeyDown(Console.VK_DOWN)) {
P.Playery += 10;
}
else if (c.isKeyDown(Console.VK_LEFT)) {
P.Playerx -= 10;
}
else if (c.isKeyDown(Console.VK_DOWN)) {
P.Playery += 10;
}
}
The P.Player(x,y,w,h) don't change?
How can this be solved?
You are setting the defaults in every iteration, your code is synchronic and therefore responding to the keys is done after you draw, and in the next iteration you are overriding the values again so you will never see any changes.
In addition you instantiate a new P object every time and not keeping the previous instances alive, therefore they are GC.
Related
I just started with Java and to learn it I was trying to program a Tamagotchi in BlueJ. This is an extract of the code:
public class Tamagotchi
{
private int hunger;
private int mood;
private int fatigue;
private int hBorder;
private int mBorder;
private int fBorder;
private String generalCondition;
public Tamagotchi(int hungerBorder, int moodBorder, int fatigueBorder)
{
// Instanzvariable initialisieren
hunger = 0;
mood = 0;
fatigue = 0;
hBorder = hungerBorder;
mBorder = moodBorder;
fBorder = fatigueBorder;
generalCondition = "indifferent";
}
public void setGeneralCondition(){
if (fatigue > fBorder){
generalCondition = "tired";
}
if ((fatigue < fBorder) & (hunger > hBorder)){
generalCondition = "hungry";
}
if ((mood > mBorder) & (hunger < hBorder) &
(fatigue < fBorder)){
generalCondition = "happy";
}
else {
generalCondition = "indifferent";
}
}
public void play()
{
if (hunger > hBorder){hunger += 2; mood += 2; fatigue += 3;
}
else {}
setGeneralCondition();
}
public void eat(){
if (fatigue > fBorder){hunger -= 2; fatigue += 2;
}
else{}
setGeneralCondition();
}
public void sleep(){
if (hunger > hBorder){hunger += 1; mood -= 1; fatigue = 0;
}
else{hunger += 1; mood += 1; fatigue = 0;
}
setGeneralCondition();
}
public void pet(){
hunger += 1;
mood += 2;
setGeneralCondition();
}
public String getGentralCondition(){
return generalCondition;
}
public void makeHappy(){
eat();
sleep();
}
}
My problem is that the generalCondition does not change when I use any of the methods. I think something with the method setGeneralCondition is wrong but I don't know where the problem is. Can somebody help :/ ?
THX in advance.
EDIT:
I posted the hole code now. As I said in the comment: I want the generalCondition to change whenever I use a method like eat(), play()...
The method setGeneralCondition was supposed to check if one of the values hunger mood or fatigue passes a certain border and change the Condition (to tired, hungry or happy). But whenever I use one of the other methods the generalCondition doesn't change.
EDIT: I have made further edits to your code and have come up with a little main that runs your code and changes generalCondition! Check it out and run it for yourself to see.
My intuition tells me this class Tamagotchi is a class file or an object Tamagotchi that will be used by a main method that rests somewhere in another file. If that is the case, I believe it is a simple fix and all you need to do is add this. in a lot of places. I have gone ahead and done just that for you below. Try this and let me know if this works!
public class Tamagotchi{
private int hunger;
private int mood;
private int fatigue;
private int hungerBorder;
private int moodBorder;
private int fatigueBorder;
private String generalCondition;
public Tamagotchi(int hungerBorder, int moodBorder, int fatigueBorder)
{
// Instanzvariable initialisieren
this.hunger = 30;
this.mood = 30;
this.fatigue = 30;
this.hungerBorder = hungerBorder;
this.moodBorder = moodBorder;
this.fatigueBorder = fatigueBorder;
this.generalCondition = "indifferent";
}
public void setGeneralCondition(){
if (fatigue > fatigueBorder){
this.generalCondition = "tired";
return;
}
if ((fatigue < fatigueBorder) && (hunger > hungerBorder)){
this.generalCondition = "hungry";
return;
}
if ((mood > moodBorder) && (hunger < hungerBorder) && (fatigue < fatigueBorder)){
this.generalCondition = "happy";
return;
} else {
this.generalCondition = "indifferent";
}
}
public String getGeneralCondition(){
return generalCondition;
}
public void play()
{
if (!generalCondition.equalsIgnoreCase("hungry")){
hunger += 2; mood += 2; fatigue += 3;
} else {
}
setGeneralCondition();
}
public void eat(){
if (fatigue > fatigueBorder){
hunger -= 2; fatigue += 2;
} else{
}
setGeneralCondition();
}
public void sleep(){
if (hunger > hungerBorder){
hunger += 1; mood -= 1; fatigue = 0;
} else{
hunger += 1; mood += 1; fatigue = 0;
}
setGeneralCondition();
}
public void pet(){
hunger += 1;
mood += 2;
setGeneralCondition();
}
public void makeHappy(){
eat();
sleep();
}
}
Here is a little main method I wrote to test the code above.
public class Test {
public static void main(String[] args) {
Tamagotchi test = new Tamagotchi(10, 10, 10);
test.play();
test.makeHappy();
System.out.println(test.getGeneralCondition());
}
}
Output :
hungry
Hope this helps!
P.S. here is a link to basic coding styles. Practice coding with these styles as it makes your code easier to read for others, yourself, it looks a lot cleaner, and it is easier to see and fix errors! Coding Style Guide
There are few major problems with the code that you posted.
As sloughy stated, you need to add "this" to hungerBorder, moodBorder, and fatigueBorder in the Tamagotchi constructor. What you are currently doing is setting the PARAMETERS hungerBorder, moodBorder and fatigueBorder to themselves. When you add "this" in front of a variable, you are now referencing the class variable regardless of whatever local variables you are currently working with.
Additionally, you shouldn't compare Strings with == and !=. This will only work when both strings in the comparison are pointing to the same internal reference. Instead you should use .equals() which can be called like this:
String testString = "test";
String otherString = "other";
if (testString.equals(otherString)) {
System.out.println("equal");
} else {
System.out.println("not equal");
}
This is working code from compilation perspective. The problem you've met is probably in data or logic you implemented. To get generalCondition changed you need condition
((mood > mBorder) & (hunger < hBorder) & (fatigue < fBorder)) to return true otherwise you'll set same default value.
Few tips:
Most probably you didn't debug your app. Start doing this especially when you new in programming/java.
Use && instead of & short. In 99% of usage this in if clause it's better (with time you'll know why)
So as the title says im struggling to add a value to an integer and then pass it to another class that uses it, then this class will pass it to the next and then that one will pass it over to the main class. Its an integer that changes the stat template of the enemies in my small game im writing.
I have tried to make constructors in two of my classes as I thought that was the problem, Ive tried to see if they work by passing some messages in them.
The problem seems to be that when I save something in the "private int l" It dosnt actually change the value of that int and I cant figure out why that is.
Here is my code, its probably not very pretty so if you have any suggestions to structure changes that I might wanna do please feel free too let me know!
Thanks in advance!
import java.util.Scanner;
public class Stor {
public static void main(String[] args) {
Scanner user_Input = new Scanner(System.in);
Menu user = new Menu();
EnemyValue monster = new EnemyValue();
user.namn();
user.AnvNamn = user_Input.next();
user.introMeny();
user.difficulty();
System.out.println(“Your enemy has " + monster.HP + " HP and " +
monster.DMG + " Damage" );
user_Input.close();
}
}
class Menu {
Scanner user_Input = new Scanner(System.in);
String AnvNamn;
String difficultySvar;
String nivåSvar;
int svar;
private int i; /
private int l;
public int getL() {
return l;
}
boolean difficultyLoop = true;
boolean felLoop = true;
void introMeny() {
System.out.println(“Welcome " + AnvNamn + "!");
}
void namn() {
System.out.print(“Pick a name: “);
}
void difficulty() {
do {
System.out.println("\nWhat level do you want ?\n1 = Easy.\n2 =
Medium.\n3 = Hard.”);
svar = user_Input.nextInt();
if (svar == 1) {
System.out.println(“Your not very brave are you ? Are you sure
this is how you wanna play ?”);
difficultySvar = user_Input.next();
if (difficultySvar.equalsIgnoreCase(“Yes”)) {
difficultyLoop = false;
l = 1;
} // If ja 1
else if (difficultySvar.equalsIgnoreCase(“Nej”)) {
System.out.println(“Ahh good! I figuerd you would change
your mind.”);
}
else
System.out.println(“I don’t understand….”);
} // if 1
else if (svar == 2) {
System.out.println(“Not to hard or to easy, a good choice! But
maybe you want to go for something harder ? Or maybe easier ?");
difficultySvar = user_Input.next();
if (difficultySvar.equalsIgnoreCase(“Yes”)) {
difficultyLoop = false;
l = 2;
} // if ja 2
else if (difficultySvar.equalsIgnoreCase(“No”)) {
System.out.println(“I sure hope you don’t pick the easy
way…..”);
}
else
System.out.println("I don’t understand….");
} // Else if 2
else if (svar == 3) {
System.out.println(“Damn! We have a big player here! Are you
sure you can handle this ?");
difficultySvar = user_Input.next();
if (difficultySvar.equalsIgnoreCase(“Yes”)) {
difficultyLoop = false;
l = 3;
} // If ja 3
else if (difficultySvar.equalsIgnoreCase(“No”)) {
System.out.println(“Wuss.”);
}
else
System.out.println(“I don’t understand….”);
} // Else if 3
else {
if (i == 0) {
System.out.println(“Ha you thought you could fool the system?!
The system fools you!”);
System.out.println(“Nah but seriously, you can only choose
between 1-3…..“);
i++;
} // if i 0
else if (i == 1) {
System.out.println(“Alright I get that its hard but
COMEON!”);
i++;
} // if i 1
else if (i == 2) {
System.out.println(“OKEY YOU GET ONE LAST CHANCE!!”);
i++;
} // if i 2
else if (i == 3) {
System.out.println(“Alright thats it…. GET OUT!”);
System.exit(0);
} // if i 3
} // Else
} // do while loop
while(difficultyLoop == true);
} //Difficulty metod.
} // Menu class.
class Nivå {
//Menu level = new Menu();
//int levelChoice = level.getL();
int levelChoice;
private int enemyLife;
public int getenemyLife() {
return enemyLife;
}
private int enemyDMG;
public int getenemyDMG() {
return enemyDMG;
}
Nivå(){
Menu level = new Menu();
levelChoice = level.getL();
System.out.println("testNivå");
}
void fiendeLiv() {
if (levelChoice == 1)
enemyLife = 100;
else if (levelChoice == 2)
enemyLife = 150;
else if (levelChoice == 3)
enemyLife = 200;
} // fiendeliv method
void fiendeDMG() {
if (levelChoice == 1)
enemyDMG = 5;
else if (levelChoice == 2)
enemyDMG = 10;
else if (levelChoice == 3)
enemyDMG = 15;
} // fiendeDMG method
} // Nivå class
class EnemyValue {
public int HP;
public int DMG;
int maxLife;
int maxDMG;
EnemyValue(){
Nivå stats = new Nivå();
maxLife = stats.getenemyLife();
maxDMG = stats.getenemyDMG();
System.out.println("TestEnemyValue");
}
void rank1() {
HP = maxLife;
DMG = maxDMG;
} // rank1 easy method
} // EnemyValue class
You say that when you save something in l (poor choice of a variable name, by the way) it does not save the value. How do you know that? Where in the code do you check whether the value is saved?
In the constructor for class Nivå you create a new Menu and then call getL() on that menu before you have ever set the value of that variable.
Everything runs at the start of your public static void main(String[] args) method, and nothing will run if its instructions are not in there. For example, you are not actually creating any Niva objects in the main method, so the Niva constructor is never called. That is one issue. The other is your constructors are creating new instances of objects and then getting their values; this gives you empty values from a brand new object:
Nivå(){
Menu level = new Menu(); // Don't do this. This is an empty menu
levelChoice = level.getL(); // Getting the blank L value from the empty menu
System.out.println("testNivå");
}
Instead, you need to define constructors with parameters to pass the values into the class like this:
Nivå(int level){ // add an int parameter
levelChoice = level; // Direct assignment
fiendeDMG(); // Call this in the constructor to set up your last value
System.out.println("testNivå");
}
Then, when you call the constructor (which you must if you want it to exist), include the parameter. Inside the Stor class:
public static void main(String[] args) {
Scanner user_Input = new Scanner(System.in);
Menu user = new Menu();
user.namn();
user.AnvNamn = user_Input.next();
user.introMeny();
user.difficulty(); // Run this before creating the other classes; you need the l value
Nivå niva = new Nivå(user.getL()); // Creates new Niva while also assigning l to the levelChoice and then getting DMG
EnemyValue monster = new EnemyValue(/*add some parameters for life and dmg*/);
}
There is still more that needs to be done, like modifying the constructor of the EnemyLevel. Just remember that methods are never called unless they connect to something running from main and use parameters in functions and constructors to pass on data to other objects. Hope this helps.
I have a program and want to create a simple highscore method for it. The method will only tell if the current amount of points is higher than the ones before.
public class Highscore {
public static int Highscore(int poang) {
int count = 0;
int poäng1 = 0;
int poäng2 = 0;
As you see in above, the counter is set to 0;. This is to save the first entry. However, it resets to 0 every time the method is being used. How can i recode this? Here is the rest of the code:
if (count == 0) {
poäng1 = poang;
count++;
} else if (count > 0) {
if (poäng2 > poäng1) {
poäng1 = poäng2;
}
}
return poäng1;
}
}
Local variables are redefined (and re-initialized) every time the block (in your case - a static method) is entered. If you want them to keep their value beyond the scope of that block, they should be defined outside of it.
In this case, you could have count as a (static) member:
private static int count = 0;
public static int Highscore(int poang) {
// Code comes here
This is the code I am running:
public class MyRunnableClass implements Runnable {
static int x = 30;
int y = 0;
#Override
public void run() {
for(int i=0;i<30;i++){
getFromStash();
}
}
public synchronized void getFromStash(){
x--;
y++;
}
}
and my Test class:
public class MyRunnableClassTest {
public static void main(String[] args){
MyRunnableClass aa = new MyRunnableClass();
MyRunnableClass bb = new MyRunnableClass();
Thread a = new Thread(aa);
Thread b = new Thread(bb);
a.start();
b.start();
System.out.println(aa.y);
System.out.println(bb.y);
}
}
Sometimes I see output:
30
30
and sometimes I see:
30
0
Why? The method I have, is synchronized?
I actually expect to see something like 15 - 15 but it is definetly not what I am getting.
You need to wait for the threads to finish.
a.start();
b.start();
a.join();
b.join();
System.out.println(aa.y);
System.out.println(bb.y);
At that point you should see predictable results.
Added
Now you've had a chance to play - here's my attempt at what you seem to be trying to do.
public class MyRunnableClass implements Runnable {
static AtomicInteger stash = new AtomicInteger(1000);
int y = 0;
#Override
public void run() {
try {
while (getFromStash()) {
// Sleep a little 'cause I'm on a single-core machine.
Thread.sleep(0);
// Count how much of the stash I got.
y += 1;
}
} catch (InterruptedException ex) {
System.out.println("Interrupted!");
}
}
public boolean getFromStash() {
// It must be > 0
int was = stash.get();
while (was > 0) {
// Step down one.
if (stash.compareAndSet(was, was - 1)) {
// We stepped it down.
return true;
}
// Get again - we crossed with another thred.
was = stash.get();
}
// Must be 0.
return false;
}
}
Remove the bb and use only the aa object to create the two threads.
It's synchronized on this and you use two different objects (i.e. this values) - aa and bb. So practically you defeat the whole synchronization idea by using the two different objects.
Thread a = new Thread(aa);
Thread b = new Thread(aa);
a.start();
b.start();
Alternatively, you can do something like this.
public class MyRunnableClass implements Runnable {
private static final Object lock = new Object();
static int x = 30;
int y = 0;
#Override
public void run() {
for(int i=0;i<30;i++){
getFromStash();
}
}
public void getFromStash(){
synchronized(lock){
x--;
y++;
}
}
}
Here is what I think you want to achieve.
class Stash {
private int x = 30;
private int y = 0;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public synchronized void getFromStash(){
System.out.println("Method getFromStash called by " + Thread.currentThread().getName() + ".");
x--;
y++;
}
}
public class MyRunnableClass implements Runnable {
private Stash st = null;
private volatile boolean done = false;
public MyRunnableClass(Stash st){
this.st = st;
}
#Override
public void run() {
for(int i=0;i<30;i++){
this.st.getFromStash();
try {
double m = Math.random();
Thread.sleep((long)((m + 1) * 100.0));
}catch(InterruptedException ex){
ex.printStackTrace();
}
}
System.out.println("Thread ---> " + Thread.currentThread().getName() + " finished!");
this.done = true;
}
public static void main(String[] args) throws Exception {
Stash st = new Stash();
MyRunnableClass aa = new MyRunnableClass(st);
MyRunnableClass bb = new MyRunnableClass(st);
Thread a = new Thread(aa);
Thread b = new Thread(bb);
a.setName("Thread A");
b.setName("Thread B");
a.start();
b.start();
while (true){
System.out.println(st.getX() + " " + st.getY());
Thread.sleep(10);
if (aa.done && bb.done) break;
}
System.out.println("Main thread finished too!");
}
}
Since you print the values right after you start the threads, you're not going to "catch" the threads in the middle of the for loops. The thread scheduler is returning control to the main thread sometimes after the threads are done and sometimes before they start, but never during run(). You have to wait until the threads are done.
As you've already figured out, your first attempt didn't work the way you wanted because 1) you weren't waiting for the threads to finish, so sometimes you read the values before they'd done their work, and 2) you're not looking for each thread to pull from the stash 30 times, but rather for the sum total of the pulls to be 30 (divided among the threads however it happens).
Your move to stopping each thread when x > 0 instead of after N pulls is the right approach, but the test for whether x > 0 (and therefore whether to continue) needs to be synchronized as well. Otherwise you could test the value and find that x == 1, decide to do a pull, and then before you actually do it the other thread takes the last one. Then you do your pull, leaving x at -1 and the sum of the two y's at 31.
To solve this, you either need to put a check for x > 0 within the synchronized getFromStash() method (so you don't actually change x and y unless it's safe to do so), or you need to expose the lock outside the Stash object from peter.petrov's answer, so that both threads can explictly synchronize on that object when they test x > 0 and then call getFromStash() if applicable.
Also, it's generally much harder to figure out thread synchronization when you're using static variables; there tend to be interactions you don't anticipate. You're much better off creating a separate object (e.g. peter.petrov's Stash class) to help you represent the pool, and the pass a reference to it to each of your thread classes. That way all access is via non-static references, and you'll have an easier time making sure you get the code right.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Can't figure this out, I've created a simple class of coordinates to hold x and y ints. In another class I have a global array of Coordinates declared called "ords". In my loop I'm adding Coordinates. When trying to use method getX() and getY() from the Coordinates class in my getaction method, I get a null pointer exception. I'm sure the objects are not null, but I still can't figure out whats going wrong. Any help appreciated.
import java.util.*;
import org.w2mind.net.*;
import java.io.Serializable;
public class ConorsMind implements Mind
{
int [][] surroundings = new int [12][16];
Coordinates [] ords = new Coordinates [192];
int currentX;
int currentY;
//====== Mind must respond to these methods: ==========================================================
// newrun(), endrun()
// getaction()
//======================================================================================================
public void newrun() throws RunError
{
}
public void endrun() throws RunError
{
}
private void formTwoDimmensional(int [] someArray)
{
int counter = 0;
int n=0;
for(int i = 0; i < 15; i++)
{
for(int z = 0; z < 12; z++)
{
surroundings[z][i] = someArray[counter];
if(surroundings[z][i] ==0) {
currentX=z;
currentY=i;
}
else if(surroundings[z][i]==4){
ords[n]= new Coordinates(z,i);
n++;
}
System.out.print(z+" , "+i+": "+surroundings[z][i]);
System.out.println();
counter++;
}
}
}
public Action getaction ( State state )
{
String s = state.toString();
String[] x = s.split(",");
int act =MinerWorldUpdated.NO_ACTIONS;
int counter = 0;
int [] surround = new int [192];
//in this way user will have ability to see what surrounds him
for(int i = 11; i < 203; i++)
{
surround[counter] = Integer.parseInt(x[i]);
counter++;
}
formTwoDimmensional(surround);
int [] response = new int [x.length];
for(int i = 0; i < x.length; i++)
{
response[i] = Integer.parseInt ( x[i] );
}
System.out.println("Current position: "+currentX+" ,"+currentY);
int coalX=ords[0].getX();
int coalY=ords[0].getY();
System.out.println("Coal position: "+coalX+" ,"+coalY);
if(coalX != 0 && coalY !=0)
{
if(coalX>currentX)
{
act=MinerWorldUpdated.ACTION_DOWN;
}
else if(coalY<currentY)
{
act=MinerWorldUpdated.ACTION_LEFT;
}
else if(coalX<currentX)
{
act=MinerWorldUpdated.ACTION_DOWN;
}
else if(coalY<currentY)
{
act=MinerWorldUpdated.ACTION_LEFT;
}
}
String a = String.format ( "%d", act );
return new Action ( a );
}
}
class Coordinates implements Serializable
{
private int x;
private int y;
public Coordinates(int x1, int y1)
{
x=x1;
y=y1;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
}
Error is as follows:
java.lang.NullPointerException
at ConorsMind.getaction(ConorsMind.java:146)
The error is stemming from the following two lines:
int coalX=ords[0].getX();
int coalY=ords[0].getY();
I am calling formTwoDimensional() and its working perfectly, the ords objects are being created successfully and are not null as testing with System.out.println(ords[n].getX()) is printing the expected result when placed in my else if(surroundings[z][i]==4) block.
You need to make sure that you're calling formTwoDimensional(). If you are indeed, then it's likely that you're not ever getting into your else if block in the nested for loop, and hence ords[0] is never actually being set, so when you try to access it, it's null.
The other thing to do, if you don't want to post the rest of your code, is to add some more debugging code. See below the boolean zero_pos_set. But make sure that you see the print "Zero pos set" before your program crashes. My bet is that you don't.
public class ConorsMind implements Mind
{
int [][] surroundings = new int [12][16];
Coordinates [] ords = new Coordinates [192];
boolean zero_pos_set = false;
private void formTwoDimmensional(int [] someArray)
{
int counter = 0;
int n=0;
for(int i = 0; i < 15; i++) {
for(int z = 0; z < 12; z++) {
surroundings[z][i] = someArray[counter];
if(surroundings[z][i] ==0) {
currentX=z;
currentY=i;
} else if(surroundings[z][i]==4) {
zero_pos_set = true;
ords[n]= new Coordinates(z,i);
n++;
}
counter++;
}
}
}
public Action getaction ( State state ) {
if(zero_pos_set) {
System.out.println("Zero pos set!");
}
int coalX=ords[0].getX();
int coalY=ords[0].getY();
System.out.println("Coal position: "+coalX+" ,"+coalY);
return new Action ( a );
}
}
Based on all of the debugging information posted within this thread, it seems that in your getaction() function, you're being passed some state, that doesn't contain 4.
When you parse this information and pass it to formTwoDimensional(), you will never reach the else if block, and so ords[0], or any other ords[n], will never be set.
As a result, when you try to access ords[0] back in your getaction() function, you actually get null, and hence your NullReferenceException.
It's an order of operations issue.
If you never make a call to formTwoDimmensional(), you'll never initialize anything inside of your array. Be sure you're calling that first.
The actual NPE happens when you attempt to call coalX=ords[0].getX();, which won't work if ords[0] is null.