JButtons don't follow the intended handlers? - java

I'm making a minesweeper game, in the first part, I'm deciding whether or not there is a bomb at a certain button by using boolean1 (the field is a 16x16 array) I have tested this part, and the output is correct. 50 random true values and the rest are false my problem starts at the second part, where I want to get a certain action by the button based on the value of the boolean1. When implementing the code, all of the jbuttonsfollow the second ActionListener where the icon is set to bomb I want to get the jbuttons to also follow the first handler.
1st procedure
static void placeMines()
{
for (int x=0;x<16;x++)
{
for (int y=0;y<16;y++)
{
if(boolean1[x][y]=(true))
{
boolean1[x][y]=false;
}
}
}
int minesPlaced = 0;
Random random = new Random();
while(minesPlaced < 50)
{
int a = random.nextInt(Width);
int b = random.nextInt(Height);
boolean1[a][b]=(true);
minesPlaced ++;
}
}
2nd procedure:
static void buttonfunctions()
{
for(int c=0;c<16;c++)
{
for(int d=0;d<16;d++)
{
if (boolean1[c][d]=false)
{
final int temp3=c;
final int temp4=d;
jbuttons[c][d].addActionListener(new ActionListener()
{
#Override
public void actionPerformed (ActionEvent e)
{
jbuttons[temp3][temp4].setIcon(clickedCell);
}
});
}
if(boolean1[c][d]=true)
{
final int temp1=c;
final int temp2=d;
jbuttons[temp1][temp2].addActionListener(new ActionListener()
{
#Override
public void actionPerformed (ActionEvent e)
{
jbuttons[temp1][temp2].setIcon(bomb);
}
});
}
}
}
}

In order to check if a boolean is true, you want to do :
if (myBoolean)
doing
if (myBoolean == true)
is equivalent, but more verbose than needed.
doing
if (myBoolean = true) is syntactically correct, but has the effect of assigning true to myBoolean, and then evaluating the result of the assignment, which is true. So, going back to your code:
If the intent of the following code is to reset the matrix:
if(boolean1[x][y]=(true))
{
boolean1[x][y]=false;
}
then you should just do
boolean1[x][y] = false;
Also
if (boolean1[c][d]=false)
should probably be:
if (! boolean1[c][d])
There may be more stuff wrong with your code, but you may want to start fixing this.

Related

How to randomly get item from string array?

I am trying to generate random questions from my String array called Questions. There 10 items inside. I am trying to set the text of JLabel where once the button is click one of the questions from the array will randomly be selected and displayed. However these 2 sections of code doesn't return anyting.
public String getNextQuestion() {
int NextQues = (int)(Math.random()*10);
return Questions[NextQues];}
public void actionPerformed (ActionEvent e) {
if(e.getSource() == Button) {
Hello.setText(Questions[NextQues]);
Don't hardcode the magic number 10 in getNextQuestion(). I would prefer
ThreadLocalRandom over Math.random(). Like,
public String getNextQuestion() {
return Questions[ThreadLocalRandom.current().nextInt(Questions.length)];
}
Then invoke that method in actionPerformed like,
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Button) {
Hello.setText(getNextQuestion());
}
}
You should be calling your method getNextQuestion
OK, you need an actionlistener on your button in order for something to happen. Something like
public String getNextQuestion() {
int NextQues = (int)(Math.random()*10);
return Questions[NextQues];}
// inside main method
...
Button.addActionListener (
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Hello.setText(getNextQuestion());
}
});
...

Java add Typewriter effect to JTextArea

I need to display output to a JTextArea one character at a time, with a slight delay between each character. My attempt is as follows:
private static void printInput(final String input)
{
Timer timer = new Timer(60,new ActionListener(){
public void actionPerformed(ActionEvent e)
{
for(int i = 0; i<input.length(); i++)
{
messageArea.append(Character.toString(input.charAt(i)));
}
}
});
}
There are similar questions however I could not find one with an example I could use to figure out my problem
A Timer is a pseudo loop, that it is, it triggers an cycle after a predefined delay, each cycle is an iteration of the loop and each iteration you need to update the UI and update the iterator value.
Now, because I don't like working in the static context, the first thing I suggest is you wrap up the basic concept into a separate class. This way you can easily encapsulate the state
public class TypeWriter {
private Timer timer;
private int characterIndex = 0;
private String input;
private JTextArea textArea;
public TypeWriter(JTextArea textArea, String input) {
this.textArea = textArea;
this.input = input;
timer = new Timer(60, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (characterIndex < input.length()) {
textArea.append(Character.toString(input.charAt(characterIndex)));
characterIndex++;
} else {
stop();
}
}
});
}
public void start() {
textArea.setText(null);
characterIndex = 0;
timer.start();
}
public void stop() {
timer.stop();
}
}
So, this is pretty basic, all this does is, using a Timer, check to see if there are any more characters that need to be printed, if there is, it takes the next character and appends it to the text area and updates the iterator value. If we're at the end of the text, it will stop the Timer (ie, the exit condition)

Java Robot clicking is going at 70 clicks per second cannot figure out the math / what is going wrong

volatile private boolean mouseDown = false;
private int max = 0;
private int min = 0;
private Robot robot;
public MouseClickListener()
{
try
{
robot = new Robot();
} catch (AWTException e)
{
e.printStackTrace();
}
}
#Override
public void nativeMouseClicked(NativeMouseEvent nativeMouseEvent)
{
}
#Override
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent)
{
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
max = Native.get().getFrame().getCps().getValue() + Native.get().getFrame().getDev().getValue();
min = Native.get().getFrame().getCps().getValue() - Native.get().getFrame().getDev().getValue();
mouseDown = true;
initThread();
}
}
#Override
public void nativeMouseReleased(NativeMouseEvent nativeMouseEvent)
{
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
mouseDown = false;
}
}
Hi there, so basically I'm trying to make an auto clicker which clicks at values to a JSlider (a random value between say 9 and 13, just for example).
So on mouse click the initThread method is called, and the clicks per second is worked out ( a random number between the JSlider value, which is from a diff. class), and then from that, I click and then sleep the thread for 1 / randomNum (in seconds) so that it clicks that many times per second.
For some reason it's clicking at like 200cps and lagging my computer out. Does anyone see any problem with my code?
Thanks.
NEW CODE FOR CLICKER;
public class ClickMethod implements Runnable
{
#Override
public void run()
{
System.out.println("STARTED");
do
{
System.out.println("RUNNING");
Random r = new Random();
int random = r.nextInt((max - min) + 1) + min;
robot.mousePress(BUTTON1_MASK);
robot.mouseRelease(BUTTON1_MASK);
try
{
Thread.sleep(1000 / random);
} catch (InterruptedException e)
{
e.printStackTrace();
}
} while (mouseDown);
}
}
For some reason this only runs once and then isn't called when the mouseDown variable changes.
If this is intended to be clicked by you every so often then it creates numerous threads which all click away
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent)
{
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
max = Native.get().getFrame().getCps().getValue() + Native.get().getFrame().getDev().getValue();
min = Native.get().getFrame().getCps().getValue() - Native.get().getFrame().getDev().getValue();
mouseDown = true;
initThread();
}
}
You need to remove initThread() from there and call it once somewhere , e.g., in the constructor.

JLabel.setText() is only setting text for last element in a loop

First of all, apologies for how long winded this is.
I'm trying to make a simple roulette game that allows a user to add players, place bets for these players, and spin the roulette wheel, which is represented as a simple JLabel that updates it's text with each number it passes.
However, I've run into a bug that I'm having a lot of trouble with: the JLabel only updates the text for the last element in my loop.
Basically, my solution works like this:
When a user presses a button labelled "Spin" (given that users have been added to the game), I call a method from a class called SpinWheelService, which is an Observable singleton which in turn calls the notifyObservers() method:
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
String description = null;
if (ADD_PLAYER.equals(cmd)) {
addDialog();
} else if (PLACE_BET.equals(cmd)) {
betDialog();
} else if (SPIN.equals(cmd)) {
SpinWheelService.sws.setSpinWheelService();
} else if (DISPLAY.equals(cmd)) {
System.out.println("Display selected!");
}
}
Here is my SpinWheelService class:
package model;
import java.util.*;
public class SpinWheelService extends Observable {
public static SpinWheelService sws = new SpinWheelService();
public void setSpinWheelService() {
setChanged();
notifyObservers();
}
}
The only listener registered for SpinWheelService is this class, where GameEngine is my game engine that handles internal game logic, WheelCallbackImpl is a class that updates the View:
class SpinWheelObserver implements Observer {
GameEngine gameEngine;
ArrayList<SimplePlayer> players;
WheelCallbackImpl wheelCall;
int n;
public SpinWheelObserver(GameEngine engine, WheelCallbackImpl wheel, ArrayList<SimplePlayer> playerList) {
players = playerList;
gameEngine = engine;
wheelCall = wheel;
}
public void update(Observable sender, Object arg) {
// check if any players are present
if (players.size() == 0) {
System.out.println("Empty player array!");
return;
}
do {
gameEngine.spin(40, 1, 300, 30, wheelCall);
n = wheelCall.playback();
} while (n== 0);
}
}
The main point of note here is my gameEngine.spin() method, which is this:
public class GameEngineImpl implements GameEngine {
private List<Player> playerList = new ArrayList<Player>();
// method handles the slowing down of the roulette wheel, printing numbers at an incremental delay
public void delay(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
System.out.println("Sleep method failed.");
}
}
public void spin(int wheelSize, int initialDelay, int finalDelay,
int delayIncrement, WheelCallback callback) {
Random rand = new Random();
int curNo = rand.nextInt(wheelSize) + 1;
int finalNo = 0;
assert (curNo >= 1);
// while loop handles how long the wheel will spin for
while (initialDelay <= finalDelay) {
delay(initialDelay);
initialDelay += delayIncrement;
// handles rotating nature of the wheel, ensures that if it reaches wheel size, reverts to 1
if (curNo > wheelSize) {
curNo = 1;
callback.nextNumber(curNo, this);
curNo++;
}
assert (curNo <= wheelSize);
callback.nextNumber(curNo, this);
curNo++;
finalNo = curNo - 1;
}
calculateResult(finalNo);
callback.result(finalNo, this);
}
The method callback.nextNumber(curNo, this):
public void nextNumber(int nextNumber, GameEngine engine) {
String strNo = Integer.toString(nextNumber);
assert (nextNumber >= 1);
System.out.println(nextNumber);
wcWheel.setCounter(strNo);
}
Where in, wcWheel is my singleton instance of my View, which contains the method setCounter():
public void setCounter(String value) {
label.setText(value);
}
Sorry for how convoluted my explanation is, but basically what it boils down to is that setCounter() is definitely being called, but seems to only call the setText() method on the final number. So what I'm left with is an empty label that doesn't present the number until the entire roulette has finished spinning.
I've determined that setCounter() runs on the event dispatch thread, and I suspect this is a concurrency issue but I have no idea how to correct it.
I've tried to include all relevant code, but if I'm missing anything, please mention it and I'll post it up as well.
I'm at my wits end here, so if anyone would be kind of enough to help, that would be so great.
Thank you!
Your while loop along Thread.sleep() will block and repainting or changing of the UI until the loop is finished.
Instead you'll want to implement a javax.swing.Timer for the delay, and keep a counter for the number of ticks, to stop it. You can see more at How to Use Swing Timers
The basic construct is
Timer ( int delayInMillis, ActionListener listener )
where delayInMillis is the millisecond delay between firing of an ActionEvent. This event is listened for by the listener. So every time the event is fired, the actionPerfomed of the listener is called. So you might do something like this:
Timer timer = new Timer(delay, new ActionListener()(
#Override
public void actionPerformed(ActionEvent e) {
if (count == 0) {
((Timer)e.getSource()).stop();
} else {
//make a change to your label
count--;
}
}
));
You can call timer.start() to start the timer. Every delay milliseconds, the label will change to what you need it to, until some arbitrary count reaches 0, then timer stops. You can then set the count variable to whatever you need to, if you want to to be random, say depending on how hard the wheel is spun :D
I think you didn't post all the relevant code that is required to know exactly the problem.
But most likely the problem is due to you run your loop and JLabel.setText() in the EDT (Event Dispatching Thread).
Note that updating the UI components (e.g. the text of a JLabel) also happens in the EDT, so while your loop runs in the EDT, the text will not be updated, only after your loop ended and you return from your event listener. Then since you modified the text of the JLabel it will be refreshed / repainted and you will see the last value you set to it.
Example to demonstrate this. In the following example a loop in the event listener loops from 0 to 9 and sets the text of the label, but you will only see the final 9 be set:
JPanel p = new JPanel();
final JLabel l = new JLabel("-1");
p.add(l);
JButton b = new JButton("Loop");
p.add(b);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for ( int i = 0; i < 10; i++ ) {
l.setText( "" + i );
try { Thread.sleep( 200 ); } catch ( InterruptedException e1 ) {}
}
}
} );
A proposed solution: Use javax.swing.Timer to do the loop's work. Swing's timer calls its listeners in the EDT so it's safe to update swing components in it, and once the listener returns, a component UI update can happen immediately:
JPanel p = new JPanel();
final JLabel l = new JLabel("-1");
p.add(l);
JButton b = new JButton("Loop");
p.add(b);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
new Timer(200, new ActionListener() {
int i = 0;
#Override
public void actionPerformed(ActionEvent e2) {
l.setText("" + i);
if ( ++i == 10 )
((Timer)e2.getSource()).stop();
}
}).start();
}
} );
In this solution you will see the label's text counting from 0 up to 9 nicely.
It's appears to me that your entire game must block in the action handler until the while loop has finished? So the text of the label will be getting updated but only the last update will be visible once the AWT thread is running again.

Return boolean from Mouselistener

The class "board" wants to know if any of his objects in the array is clicked. So he have a function
private void CheckButtons()
{
for(int y = 0; y < yheight; y++)
{
for(int x = 0; x < xwith; x++)
{
if(_boardNodes[x][y].NodeClick())
{
MoveIfICan(x,y);
}
}
}
}
This "board" class have a function that is called by its own thread to always check if a button is clicked. It does that by the above function that calls a inner function of the class Node
What i want to do, is a way to return true if the label is clicked. The function in the node class looks like this
public boolean NodeClick()
{
_isClicked = false;
_clickAbleLabel.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e)
{
_isClicked = true;
System.out.println("Clicked button respons");
}
});
System.out.println("Is Clicked: " + _isClicked);
return _isClicked;
}
This dont work at all. So i need tips on a better solution than this failed one.
Note: I always get a "Clicked button respons" but the _isClicked will remain false at all time.
//Thanks

Categories

Resources