Greenfoot - isKeyDown() seems to hold its value - java

This is a sprinting function for a game, if the player has greater then 0% spring left then he can sprint, if it is at 0% the player cannot sprint. If the player is not sprinting then the sprint % will start to regenerate.
The problem:
When the player hits 0% sprint the player is still able to sprint.
public class User extends Characters
{
private int walk = 3;
private int run = 10;
private int speed = walk;
private boolean isRunning = false;
private int runDuration = 100;
private int baseRunDuration = 100;
private int runCoolDown = 300;
public void act()
{
playerMove();
}
//Contains movement inputs as well as run imputs
void playerMove(){
getWorld().showText("Run Duration: " + runDuration, 100, 100);
if(Greenfoot.isKeyDown("w") ){
setLocation(getX(), getY()-speed);
}
if(Greenfoot.isKeyDown("a")){
move(-speed);
}
if(Greenfoot.isKeyDown("s")){
setLocation(getX(), getY()+speed);
}
if(Greenfoot.isKeyDown("d")){
move(+speed);
}
if(Greenfoot.isKeyDown("shift") && runDuration > 0){
if(runDuration > 0){
isRunning = true;
speed = run;
runDuration--;
}
}
else{
speed = walk;
isRunning = false;
}
if(isRunning == false){
if(runDuration < baseRunDuration){
runDuration++;
}
}
}
}

Obicere is right that you are either sprinting, or you're alternately sprinting and not sprinting, giving a half-speed sprint. There's various ways to fix this. I'd suggest only recharging your sprint when you're not moving. You can do this using a boolean to keep track of whether you've moved this frame, or simply by using else-if to change your middle block of code to:
if(Greenfoot.isKeyDown("w") ){
setLocation(getX(), getY()-speed);
}
else if(Greenfoot.isKeyDown("a")){
move(-speed);
}
else if(Greenfoot.isKeyDown("s")){
setLocation(getX(), getY()+speed);
}
else if(Greenfoot.isKeyDown("d")){
move(+speed);
}
else if(runDuration < baseRunDuration){
runDuration++;
}
Note the new elses, and the final clause on the end which is moved up from the bottom of your code.

Related

Make an image change on hero direction, Simple 2D game

Hi every one i am having a bit of trouble with my java game, it is very simply made as i am new to java. and the game works fine well as good as i can achieve. But i am stuck on how i can change the images in real time. I am trying to figure out how to make my Monsters face me "the hero frylark" when they chase me. i have made 2 simple methods in my monster class. left and right How could i apply these methods to make the image change from image = getImage("/Game/images/police-right.png"); to image = getImage("/Game/images/police-left.png");.
Oh and in my project library is golden_0_2_3.jar which contains some game engine stuff.
Please.
Many thanks from edwin.
import com.golden.gamedev.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.awt.event.KeyEvent;
public class MyGame extends Game {
// set the values
public Random random;
private Hero frylark;
private Monster[] monsters = new Monster[3];
private Token coin;
private GameBackGround grass;
private BufferedImage image;
public void initResources() {
// set a new random number
random = new Random();
// get the background image.
image = getImage("/Game/images/background.png");
// set the name "grass" to background and given the image from the image set above.
grass = new GameBackGround("grass", image);
// get the monsters image.
image = getImage("/Game/images/police.png");
// give the monsters their names "" and set them their image from the image set above.
monsters[0] = new Monster("Monster", image);
monsters[1] = new Monster("Monster2", image);
monsters[2] = new Monster("Monster3", image);
// get the tokens image.
image = getImage("/Game/images/donut.png");
// set the name "coin" for the token, then its x and y position, and set the image from the image set above.
coin = new Token("coin", 400, 300, image);
// get the heros image.
image = getImage("/Game/images/snake.png");
// set the name "frylark" for the hero, then his score "0" and lives "5".
frylark = new Hero("Frylark", 0, 5);
//set the monsters random x and y positions.
monsters[0].setX(random.nextInt(750));
monsters[0].setY(random.nextInt(550));
monsters[1].setX(random.nextInt(750));
monsters[1].setY(random.nextInt(550));
monsters[2].setX(random.nextInt(750));
monsters[2].setY(random.nextInt(550));
}
// update method
public void update(long elapsedTime) {
// Pause the hero "frylark" on hold of the space bar.
if (!keyDown(KeyEvent.VK_SPACE)){
// if dead stop frylark moving on the 5 second game over sequence, being displays details and playing the game over sound.
if (Hero.dead(frylark)){
if(keyDown(KeyEvent.VK_LEFT))
{
// Move left
frylark.moveLeft();
}
if (keyDown(KeyEvent.VK_RIGHT))
{
// Move right
frylark.moveRight();
}
if (keyDown(KeyEvent.VK_UP))
{
// Move up on press of up key
frylark.moveUp();
}
if (keyDown(KeyEvent.VK_DOWN))
{
// Move down on press of down key
frylark.moveDown();
}
}
if (keyDown(KeyEvent.VK_ESCAPE))
{
// Exit game on press of esc key.
System.exit(0);
}
}
if (!keyDown(KeyEvent.VK_SPACE))
{
// Pause the monsters on hold of the space bar
monsters[0].chase(frylark);
monsters[1].chase(frylark);
monsters[2].chase(frylark);
}
// if monster 0 has eaten frylark move to a random position and lose a life, plus play the lose life sound.
if (monsters[0].eaten(frylark)) {
monsters[0].setX(random.nextInt(750));
monsters[0].setY(random.nextInt(550));
frylark.loseLife();
playSound("/Game/sounds/lost_a_life.wav");
}
// if monster 1 has eaten frylark move to a random position and lose a life, plus play the lose life sound.
if (monsters[1].eaten(frylark)) {
monsters[1].setX(random.nextInt(750));
monsters[1].setY(random.nextInt(550));
frylark.loseLife();
playSound("/Game/sounds/lost_a_life.wav");
}
// if monster 2 has eaten frylark move to a random position and lose a life, plus play the lose life sound.
if (monsters[2].eaten(frylark)) {
monsters[2].setX(random.nextInt(750));
monsters[2].setY(random.nextInt(550));
frylark.loseLife();
playSound("/Game/sounds/lost_a_life.wav");
}
// if coin is collected increase score and move to a random position, and play the coin collect sound.
if (coin.collected(frylark)) {
coin.setX (random.nextInt(750));
coin.setY (random.nextInt(550));
frylark.increaseScore();
playSound("/Game/sounds/coin.wav");
}
}
public void render(Graphics2D g) {
// draw all the monsters, hero, and coin and background.
g.drawImage(grass.getImage(),grass.getX(),grass.getY(),null);
g.drawImage(monsters[0].getImage(), monsters[0].GetX(), monsters[0].GetY(), null);
g.drawImage(monsters[1].getImage(), monsters[1].GetX(), monsters[1].GetY(), null);
g.drawImage(monsters[2].getImage(), monsters[2].GetX(), monsters[2].GetY(), null);
g.drawImage(image,frylark.getX(),frylark.getY(),null);
g.drawImage(coin.getImage(),coin.getX(),coin.getY(),null);
// if monster 0 overlaps another monster mover him back
if (monsters[0].overlap(monsters)){
monsters[0].x -=20;
monsters[0].y -=70;
}
// if monster 1 overlaps another monster mover him back
if (monsters[1].overlap(monsters)){
monsters[1].x -=21;
monsters[1].y -=70;
}
// if monster 2 overlaps another monster mover him back
if (monsters[2].overlap(monsters)){
monsters[2].x -=22;
monsters[2].y -=70;
}
// draw the lives bar, and set the font colour and size
g.setColor(Color.RED);
g.setFont(new Font("default", Font.BOLD, 18));
for (int i = 0; i < frylark.getLives(); i++) {
g.fillRect( (i + 1) * 15, 10, 10, 10);
}
// draw the score
g.setColor(Color.GREEN);
g.drawString("Score: " + frylark.getScore(), 10, 50);
// draw the level
g.setColor(Color.YELLOW);
g.drawString("level: " + frylark.getScoreNum(), 10, 80);
// game over sequence, changes the font to size 40 and displays game over, as well as the payers score and level reached plus the game over sound.
if (frylark.getLives() ==0){
g.setColor(Color.RED);
g.setFont(new Font("override", Font.BOLD, 40));
g.drawString("Game over !", 280, 290);
playSound("/Game/sounds/game_over.wav");
g.drawString("You reached Level " + frylark.getScoreNum() + " Your Score: " + frylark.getScore(), 60, 330);
}
}
// main method which after all classes have been read and checked, "Game development environment OK! " will be printed to the console.
// then a new game is created and given dimensions and launched.
public static void main(String args[]) {
System.out.println("Game development environment OK! ");
GameLoader gameLoader = new GameLoader();
MyGame myGame = new MyGame();
gameLoader.setup(myGame,new Dimension(800,600),false);
gameLoader.start();
}
}
and my Monster class
import java.util.Random;
import java.awt.image.BufferedImage;
public class Monster {
private String name;
int x;
int y;
private BufferedImage image;
Random rand;
public Monster (String nameIn, BufferedImage imageIn)
{
name = nameIn;
x = 0;
y = 0;
image = imageIn;
}
public void chase(Hero hero) {
if (hero.getX() < x) { // if hero is to the left
x--;
}
if (hero.getX() > x) { // if hero is to the right
x++ ;
}
if (hero.getY() < y) { // if hero is to the above
y--;
}
if (hero.getY() > y) { // if hero is to the below
y++;
}
}
public boolean overlap(Monster monsters[]){
if (monsters[0].x == monsters[1].x && monsters[0].y == monsters[1].y || monsters[0].x == monsters[2].x && monsters[0].y == monsters[2].y ||
monsters[1].x == monsters[0].x && monsters[1].y == monsters[0].y || monsters[1].x == monsters[2].x && monsters[1].y == monsters[2].y ||
monsters[2].x == monsters[0].x && monsters[2].y == monsters[0].y || monsters[2].x == monsters[1].x && monsters[2].y == monsters[1].y) {
return true;
}
else{
return false;
}
}
public boolean eaten(Hero hero) {
if (hero.getX() == x && hero.getY() == y) {
return true;
}
else {
return false;
}
}
public BufferedImage getImage() {
return image;
}
public int GetX(){
return x;
}
public int GetY(){
return y;
}
public String getName()
{
return this.name;
}
public void setX(int xIn) {
x = xIn;
}
public void setY(int yIn) {
y = yIn;
}
public boolean left(Hero hero) {
if (hero.getX() < x) {
return true;
}
else {
return false;
}
}
public boolean right(Hero hero) {
if (hero.getX() > x) {
return true;
}
else {
return false;
}
}
}
I would modify your Monster constructor to accept both images. Then modify Monster.getImage() to call left() and return the correct one based on the result. You probably don't need to call right() as well, since if the monster is not facing left then you know it needs to face right. Unless you want to get more sophisticated and also add a view facing straight forward or backward.

How to delete entity when "health <= 0"?

Ive been followin an online tutorial for a top down shooter game, but the tut is unfinished (and I dont see the creator continuing it), so Id like to complete it myself. So far, the tutorial has helped me to give the player health and a string above it to show how much health, but nothing happens when health gets to and goes below 0. It just goes down in the increment I set. Id like the game to close when there is no more health, so how would I go about doing this?
This is what happens when the player gets hit by an enemy bullet:
private void playerBulletCollision(){
for (Bullet b:mobBullets){
if (b.collisionBox.intersects(player.collisionBox)){
player.health -= b.damage;
b.isAlive = false;
break;
}
}
}
And this is what happens when player bullet hits enemy
private void mobBulletCollision(){
for (Bullet b:bullets){
for (Entity m: mobs){
if (b.collisionBox.intersects(m.collisionBox)){
m.health -= b.damage;
b.isAlive = false;
break;
}
}
}
}
so how can I make it so the game ends when player health is no more? Sorry if my explanation isnt clear or the code I showed isnt enough/not relevant. Tell me and Ill fix it to the best of my abilities.
Thank you
Edit: I tried to make it so it checks to see if health <= 0 and if it does it despawns:
private void playerBulletCollision(){
for (MobBullet b:mobBullets){
if (b.collisionBox.intersects(player.collisionBox)){
player.health -= b.damage;
b.isAlive = false;
break;
}
if(player.health <=0)
player.isAlive = false;
}
}
It didnt work.
Edit 2: This is the process to remove the dead enemies. I think because there is no such thing for the player, player.health = false; does nothing.
private void removeDead(){
for (int i = 0; i <bullets.size(); i++){
if (bullets.get(i).isAlive == false )
bullets.remove(i);
}
for (int i = 0; i <mobs.size(); i++){
if (mobs.get(i).isAlive == false )
mobs.remove(i);
}
for (int i = 0; i <mobBullets.size(); i++){
if (mobBullets.get(i).isAlive == false )
mobBullets.remove(i);
}
bullets.trimToSize();
mobs.trimToSize();
mobBullets.trimToSize();
}
How should this piece be modified to incorporate the player?
You should do this. On a collision you decrement the health and after the loop you check the player health if this is <=0 you set isAlive to false.
private void playerBulletCollision(){
for (MobBullet b:mobBullets){
if (b.collisionBox.intersects(player.collisionBox)){
player.health -= b.damage;
b.isAlive = false;
break;
}
}
if(player.health <=0){
player.isAlive = false;
}

Weird behavior in Java While Loop [duplicate]

This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I am writing a basic Tic-Tac-Toe Single player game using basic swing graphics. I completed the game, but there is a weird problem I am facing. At one place, I used a while loop with a SOP statement. If I omit this statement, program works differently and nothing happens (like some kind of infinite loop), and if I keep it, it works just fine. I don't know what's happening in the code. Please help.
Below is the source code which causing problem. Sorry for my amateur coding style.
import java.util.Random;
public class SinglePlayer implements Runnable{
public final int MINIMUM = -1000000;
private GameBoard game;
public SinglePlayer(){
game = new GameBoard("Single Player");
}
public static void main(String[] args){
SinglePlayer gameSingle = new SinglePlayer();
gameSingle.run();
}
public void run(){
boolean machinePlayed = true, userPlayed = false;
// Outer loop is to maintain re-match option of program
while(this.game.quitTwoPlayer == false){
// Inner loop is a single game b/w user and machine
while(this.game.GameQuitStatus() == false){
/* I kept two conditions to switch b/w machine and user mode
* of game and they just keep changing to simulate the game
* b/w machine and user.
*/
if(machinePlayed == false && userPlayed){
try {
MachineMove("O");
} catch (CloneNotSupportedException e) {
e.printStackTrace();
break;
}
this.game.ChangePlayerLabels();
machinePlayed = true;
userPlayed = false;
}
else if(machinePlayed && userPlayed == false){
int earlierCount = this.game.CountSteps();
/* THIS IS THE WHILE LOOP I AM TALKING ABOUT.
* If I omit the print statement inside the body of loop,
* program behaves differently, but when I keep it,
* it working just fine.
* */
while(earlierCount == this.game.CountSteps()){
System.out.println("Player User thinking");
}
this.game.ChangePlayerLabels();
machinePlayed = false;
userPlayed = true;
}
this.game.DeclareResult();
}
this.game.dispose();
}
}
public void MachineMove(String player) throws CloneNotSupportedException{
/* If board is empty, play at center of the board */
if(this.game.CountSteps() == 0){
this.game.MakeMove(1, 1);
}
/* If center is blank, play it there. Otherwise, pick a corner randomly */
else if(this.game.CountSteps() == 1){
if(this.game.IsEmpty(1, 1))
this.game.MakeMove(1, 1);
else{
Random randomNum = new Random();
int num = randomNum.nextInt(4);
if(num == 0)
this.game.MakeMove(0, 0);
else if(num == 1)
this.game.MakeMove(2, 0);
else if(num == 2)
this.game.MakeMove(0, 2);
else if(num == 3)
this.game.MakeMove(2, 2);
}
}
else{
/* If the next move is such that it should be taken, otherwise opponent will win */
String opponent = "";
if(this.game.GetCurrentPlayer().equals("O"))
opponent = "X";
else
opponent = "O";
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(this.game.IsEmpty(i,j)){
GameBoard tempGame = new GameBoard(this.game, "Single Player");
tempGame.MakePossibleMove(i, j, opponent);
if(tempGame.GameWinner().equals(opponent + " wins")){
this.game.MakeMove(i,j);
return;
}
}
}
}
/* If the next move is not such that if missed, game is lost, then play most optimal move towards winning */
Move tempMove = new Move(MINIMUM, 0, 0);
Move bestMove = new Move(MINIMUM, 0, 0);
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(this.game.IsEmpty(i,j)){
GameBoard tempGame = new GameBoard(this.game, "Single Player");
tempMove = MakeMoves(tempGame, i, j);
if(tempMove.score > bestMove.score){
bestMove.row = tempMove.row;
bestMove.col = tempMove.col;
bestMove.score = tempMove.score;
}
}
}
}
this.game.MakeMove(bestMove.row, bestMove.col);
}
}
public Move MakeMoves(GameBoard tempGame, int row, int col){
String player = tempGame.GetCurrentPlayer();
tempGame.MakeMove(row, col);
if(tempGame.GameWinner().equals("Match Draw")){
return new Move(0, row, col);
}
else if(tempGame.GameWinner().equals("X wins")){
if(player.equals("X")){
return new Move(1, row, col);
}
else{
return new Move(-1, row, col);
}
}
else if(tempGame.GameWinner().equals("O wins")){
if(player.equals("O")){
return new Move(1, row, col);
}
else{
return new Move(-1, row, col);
}
}
else{
Move bestMove = new Move(MINIMUM, 0, 0);
Move tempBestMove = new Move(0, 0, 0);
for(int i = 0; i<3; i++){
for(int j = 0; j<3; j++){
if(tempGame.IsEmpty(i,j)){
GameBoard newGame = new GameBoard(tempGame, "Single Player");
tempBestMove = MakeMoves(newGame, i, j);
if(tempBestMove.score > bestMove.score)
bestMove = tempBestMove;
}
}
}
return bestMove;
}
}
}
class Move{
public int score;
public int row;
public int col;
public Move(int score, int row, int col){
this.score = score;
this.row = row;
this.col = col;
}
}
Your loop is likely typing up your processor, and the SOP slows the loop enough to allow other processes to occur. But regardless and most importantly, you don't want to have this loop present in the first place. You state that you have a,
Tic-Tac-Toe Single player game using basic swing graphics
Remember that Swing is an event driven GUI library, so rather than loop as you would in a linear console program, let events occur, but respond to them based on the state of the program.
In other words, give your class several fields including a boolean variable that tells whose turn it is, such as boolean playersTurn, a boolean variable gameOver, ..., and change the state of these variables as the game is played, and base the games behavior depending on these states. For instance the game would ignore the player's input if it was not his turn.

pattern when using Math.random

I am trying to have a mouse go through rooms to a target room. I am using a graph-like system with an x and y axis. I have a problem where the computer doesn't seem to want to add or subtract from an already existing variable.
Console:
The mouse is in room (5,4)
The mouse is in room (5,6)
The mouse is in room (6,5)
The mouse is in room (5,4)
The mouse is in room (5,6)
The mouse is in room (5,6)
Code for mouse:
package mouse_maze;
public class Mouse {
private int xCord = 5;
private int yCord = 5;
//position of the mouse when it starts
public int getXCord() {
return this.xCord;
}
public int getYCord() {
return this.yCord;
}
public void move() {
//method for the movement of the mouse
boolean verticalMove = Math.random() < .5;
boolean horizontalMove;
if (verticalMove == true)
horizontalMove = false;
else
horizontalMove = true;
int moveBy = 1;
if (Math.random() < .5)
moveBy = -1;
if (verticalMove) {
int test = this.yCord + moveBy;
if(test < 1 || test > 9) return;
this.yCord += moveBy;
}
if (horizontalMove) {
int test = this.xCord + moveBy;
if(test < 1 || test > 9) return;
this.xCord += moveBy;
}
System.out.println("The mouse is in room (" + xCord + "," + yCord + ")");
}
}
Code for maze:
package mouse_maze;
public class Maze {
private boolean onGoing = false;
private int tarX;
private int tarY;
//creates the target for the mouse.
public static void main(String[] args) {
new Maze(6, 8).init();
}
public Maze(int tarX, int tarY) {
this.tarX = tarX;
this.tarY = tarY;
}
public void init() {
this.onGoing = true;
while(this.onGoing)
this.iterate();
}
public void iterate() {
Mouse m = new Mouse();
m.move();
if (m.getXCord() == tarX && m.getYCord() == tarY) {
this.onGoing = false;
System.out.println("The mouse has beat the maze!");
//checks if the mouse has gotten to the target room.
}
}
}
First, learn to use a debugger, or at least learn to debug by whatever means. It is meaningless to always "assume" the problem without actually proving it.
Your whole problem has nothing to do with random etc.
In your iterate() method, you are creating a new mouse every time, instead of having the same mouse keep on moving.

Java textField infinite loop

Game class:
import java.util.Random;
public class Game {
public static void main(String args[]){
//----------Sets up GUI----------
GUI gameGUI = new GUI();
gameGUI.setVisible(true);
Player.setGUI(gameGUI);
//----------Sets initial number of marbles, computer player and human player----------
Random random = new Random();
int initialNum;
//loop makes sure initialNum of marbles is between 10 and 100
do{
initialNum = random.nextInt(100);
}while(initialNum < 10);
//*****gameGUI.manageMarbles(initialNum, true);
//end loop
Pile pile = new Pile(initialNum);
gameGUI.setPile(pile);
int compChoice = random.nextInt(2) + 1; //number index (1 or 2) representing SIMPLE_COMPUTER or SMART_COMPUTER
Player computer = new Player(Player.Type.values()[compChoice]);
Player humanPlayer = new Player(Player.Type.HUMAN);
//----------Game loop----------
//Randomly determine first player
Player currentPlayer;
int playerIndex = random.nextInt(2); //will be used to determine next player in the loop
if(playerIndex == 0){ currentPlayer = computer; }
else { currentPlayer = humanPlayer; }
//Loop
while(pile.getNumMarbles() != 0){
System.out.printf("%d marbles left.\n", pile.getNumMarbles());
int removed = currentPlayer.playTurn(pile.getNumMarbles());
pile.removeMarbles(removed);
//Determine next player
playerIndex = Math.abs(playerIndex - 1); //if playerIndex = 0, it becomes 1, and vice-versa
if(playerIndex == 0){ currentPlayer = computer; }
else { currentPlayer = humanPlayer; }
}
System.out.println(currentPlayer + " won");
}
}
Player class:
import java.util.Scanner;
import java.util.Random;
public class Player {
public enum Type{HUMAN, SIMPLE_COMPUTER, SMART_COMPUTER}
private Type type;
static private GUI gui;
public Player(Player.Type type){
this.type = type;
}
public Player.Type getType(){
return type;
}
public int playTurn(int pileSize){
Random random = new Random();
if(type == Type.HUMAN){
int marbles;
do{
marbles = gui.getMarblesToRemove();
}while(marbles < 0);
return marbles;
}
else if(type == Type.SIMPLE_COMPUTER){
if(pileSize == 1){
return 1;
}
else{
int remove = random.nextInt(pileSize/2) + 1;
if(remove == (pileSize/2) + 1){ remove -= 1; }
return remove;
}
}
else if(type == Type.SMART_COMPUTER){
if(pileSize == 1){
return 1;
}
else if(pileSize == 3 || pileSize == 7 || pileSize == 15 || pileSize== 31 || pileSize== 63 || pileSize <= 3){
int remove = random.nextInt(pileSize/2) + 1;
if(remove == (pileSize/2) + 1){ remove -= 1; }
return remove;
}
else{
for(int i=1; i<=pileSize/2; i++){
int size = pileSize - i;
if(size == 3 || size == 7 || size == 15 || size == 31 || size == 63){
return i;
}
}
}
}
return 0;
}
public String toString(){
return ""+type;
}
public static void setGUI(GUI guii){
gui = guii;
}
}
GUI class:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class GUI extends JFrame {
private JPanel panel;
private JButton removeButton; //button to remove marbles
private JTextField marblesAmount; //amount of marbles to remove
private static final int FIELD_WIDTH = 2;
private JLabel marblesLabel;
private JLabel errorLabel;
private Pile pile;
private int marblesToRemove;
private ClickListener listener;
static final private int WIDTH = 700, HEIGHT = 600;
public GUI(){
super.setTitle("test");
super.setSize(WIDTH, HEIGHT);
super.setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
marblesLabel = new JLabel("How many marbles to remove?");
errorLabel = new JLabel("");
removeButton = new JButton("Remove");
listener = new ClickListener();
removeButton.addActionListener(listener);
marblesAmount = new JTextField(FIELD_WIDTH);
panel.add(removeButton);
panel.add(marblesLabel);
panel.add(marblesAmount);
panel.add(errorLabel);
super.add(panel);
marblesToRemove = 0;
}
public void setPile(Pile pile){
this.pile = pile;
}
private class ClickListener implements ActionListener{
public void actionPerformed(ActionEvent event){
marblesToRemove = Integer.parseInt(marblesAmount.getText());
}
}
public int getMarblesToRemove(){
return marblesToRemove;
}
}
Pile Class:
public class Pile {
private int initialNum;
private int currentNum;
public Pile(int initialNum){
setNumMarbles(initialNum);
currentNum = initialNum;
}
public int getNumMarbles(){
return currentNum;
}
public void removeMarbles(int numToRemove){
currentNum = currentNum - numToRemove;
}
public void setNumMarbles(int amount){
initialNum = amount;
}
public String toString(){
return "Number of marbles: " + currentNum;
}
}
What I am trying to do is to get the function playTurn(int pileSize) in the Player class to return the variable marbles(inside the if(type == Type.HUMAN) block ) only when it is not zero. The variable marblesToRemove from the gui class is assigned to marbles, by calling the function getMarblesToRemove().
marblesToRemove is initially set to 0 in the default constructor for the gui class, and that causes the functionplayTurn(int pileSize) to go in an infinite loop. But marblesToRemove is changed to another value that is input in a JTextField (marblesAmount) when a a button(removeButton) is pressed. But the the do while loop will still be an infinite loop and the function will return nothing, why? Can someone please help? Thanks.
This is probably because of at least two issues that I can see. The first is that you are modifying the variable in one thread, and reading it in the other. This should be done using either synchronization, or some other locking mechanism (Lock or AtomicInteger, etc.).
The second issue is that your reading-thread should not be doing a 'tight' loop. This is bad practices that sends one CPU to 100% usage. It should be done using some form of notification. Again, synchronization comes to mind.
Until you fix these two issues, you will always have unreliable results.
For what it's worth, in your particular case, if I were to make an educated guess, I would guess that there are two important copies of the marblesAmount (and there are alsways multiple copies). There's the copy thati's in the L1 and registers of one CPU that's doing a tight loop waiting for that register to change, and the other is in another core on your CPU setting it to a new value. Unless you use some synchronization, or somethin from the java.util.concurrent.* library you ave no way to tell one copy of the variable to refresh the other.
I got it to work finally. I just added a line of code "System.out.print("");" in the do-while loop in the Player class.
So now it looks like
do{
marbles = gui.getMarblesToRemove();
System.out.print("");
}while(marbles < 0);
I have no idea why that works, but it does lol. Now the function actually returns the value that I set in the JTextField if it is not zero.

Categories

Resources