Recursion inside ActionListener - java

I have to add add recursion inside ActionListener to calculate fibonacci sequence of a given number, i've tried to add recursion in this way, but it didn't work.
fibonacci.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
int a = Integer.parseInt(input1.getText());
if(a == 0)
result.setText(String.valueOf("0"));
else if(a == 1)
result.setText(String.valueOf("1"));
else
result.setText(String.valueOf(fibonacci(a - 1) + fibonacci(a - 2)));
} catch (Exception f) {
JOptionPane.showMessageDialog(rootPane, "ERROR: " + (f.getMessage()));
}
String aField = input1.getText();
if (e.getSource() == fibonacci) {
if ("".equals(aField)) {
String emptyFieldWarning;
emptyFieldWarning = "One or more fields is/are empty!";
JOptionPane.showMessageDialog(rootPane, emptyFieldWarning);
}
}
}
});

The recursion should happen within it's own method, the ActionListener should stand as the initiation of that recursion.
Something along the lines of
fibonacci.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String fibonacciStr = fibonacciRecursion(0, 1, 10);
}
}
String fibonacciRecursion(int value0, int value1, int depth){
StringBuilder fibStr = new StringBuilder();
if(depth > 0){
fibStr.append(fibonacciRecursion(value1, value0 + value1, depth-1));
}
return fibStr;
}
As you didn't mention any limit, the depth parameter is meant so your recursion has a way of stopping, as to avoid a SO.
I haven't tested this, but it should be enough to get you closer to a solution of your own design.
Edit
As per #Tom Hawtin - tackline 's comment, this can also be done via lambda expression
fibonacci.addActionListener(actionEvent->
System.our.println(fibonacciRecursion(0, 1, 10)));

Related

JPanel doesn't get new values (anymore)

So, I'm trying to program a Game of Life simulation (Conway), and I want to show it in a JFrame.
For this purpose, I've created a JPanel, and it works perfectly, until I try to actually show a new generation. With prints, I've figured out, that the list is actually correct inside the newGeneration() method, but when paint(Graphics g) gets called (aka, when I try to repaint the JFrame), the list isn't updating.
I'm sure I've missed something obvious, and I'm not well versed in Java, but it's just getting so annoying. I'd really appreciate your help.
Here's my code;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
new GameOfLife();
}
}
class GameOfLife {
// Initialising all class wide variables; sorted by type
JFrame frame = new JFrame("Game of Life");
JPanel panel;
Scanner gameSize = new Scanner(System.in);
String dimensions;
String splitHorizontal;
String splitVertical;
String confirmation;
Boolean accepted = false;
Integer split;
Integer horizontal;
Integer vertical;
Integer livingNeighbours;
int[][] cells;
int[][] newCells;
public GameOfLife() {
// Prompt for game Size
System.out.println("Please enter your game size in the following format; 'Horizontal,Vertical'");
// Run until viable game Size has been chosen
while (!accepted) {
dimensions = gameSize.nextLine();
// Check for correct format
if (dimensions.contains(",")) {
split = dimensions.indexOf(",");
splitHorizontal = dimensions.substring(0, split);
splitVertical = dimensions.substring(split + 1);
// Check for validity of inputs
if (splitHorizontal.matches("[0-9]+") && splitVertical.matches("[0-9]+")) {
horizontal = Integer.parseInt(dimensions.substring(0, split));
vertical = Integer.parseInt(dimensions.substring(split + 1));
// Check for game Size
if (horizontal > 1000 || vertical > 1000) {
System.out.println("A game of this Size may take too long to load.");
} else {
// Confirmation Prompt
System.out.println("Your game will contain " + horizontal + " columns, and " + vertical + " rows, please confirm (Y/N)");
confirmation = gameSize.nextLine();
// Check for confirmation, anything invalid is ignored
if (confirmation.matches("Y")) {
accepted = true;
System.out.println("Thank you for your confirmation. Please select live cells. Once your happy with your game, press Spacebar to start the Simulation.");
// Setting parameters depending on Size
frame.setSize(horizontal * 25 + 17, vertical * 25 + 40);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
}
}
// Prompt asking for new dimensions in case of invalid dimensions or non confirmation
if (!accepted) {
System.out.println("Please enter different dimensions.");
}
}
// Creating list of cells
cells = new int[horizontal][vertical];
// Showing the empty panel for selection of live cells
panel = new PaintCells(horizontal, vertical, cells);
frame.add(panel);
// Select live cells
panel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (cells[(int) Math.ceil(e.getX() / 25)][(int) Math.ceil(e.getY() / 25)] == 1) {
cells[(int) Math.ceil(e.getX() / 25)][(int) Math.ceil(e.getY() / 25)] = 0;
} else {
cells[(int) Math.ceil(e.getX() / 25)][(int) Math.ceil(e.getY() / 25)] = 1;
}
frame.repaint();
}
});
// Simulation start
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == ' ') {
newGeneration();
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
});
}
// Generating new generations
void newGeneration() {
newCells = new int[horizontal][vertical];
// Pause inbetween generations
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
* Way of Life Rules:
* Living cells with 2 or 3 living neighbours live on to the next generation.
* Dead cells with exactly 3 living neighbours become living cells in the next generation.
* Every other living cell dies.
*/
// iterate through every cell
for (int l = 0; l < vertical; l++) {
for (int k = 0; k < horizontal; k++) {
livingNeighbours = 0;
// check amount of neighbours
if (k - 1 > -1) {
if (l - 1 > -1) {
if (cells[k - 1][l - 1] == 1) {
livingNeighbours++;
}
}
if (l + 1 < vertical) {
if (cells[k - 1][l + 1] == 1) {
livingNeighbours++;
}
}
if (cells[k - 1][l] == 1) {
livingNeighbours++;
}
}
if (k + 1 < horizontal) {
if (l - 1 >= 0) {
if (cells[k + 1][l - 1] == 1) {
livingNeighbours++;
}
}
if (l + 1 < vertical) {
if (cells[k + 1][l + 1] == 1) {
livingNeighbours++;
}
}
if (cells[k + 1][l] == 1) {
livingNeighbours++;
}
}
if (l - 1 >= 0) {
if (cells[k][l - 1] == 1) {
livingNeighbours++;
}
}
if (l + 1 < vertical) {
if (cells[k][l + 1] == 1) {
livingNeighbours++;
}
}
// change cell value depending on amount of neighbours
if (cells[k][l] == 1) {
if (livingNeighbours < 2 || livingNeighbours > 3) {
newCells[k][l] = 0;
} else {
newCells[k][l] = 1;
}
} else {
if (livingNeighbours == 3) {
newCells[k][l] = 1;
}
}
}
}
cells = newCells;
frame.validate();
frame.paint(frame.getGraphics());
newGeneration();
}
}
// Our canvas
class PaintCells extends JPanel {
private Integer horizontal;
private Integer vertical;
private int[][] newOriginalCells;
// Get our X and Y from the original prompts
public PaintCells(Integer originalHorizontal, Integer originalVertical, int[][] originalCells) {
this.horizontal = originalHorizontal;
this.vertical = originalVertical;
this.newOriginalCells = originalCells;
}
#Override
public void paint(Graphics g) {
for (int i = 0; i < vertical; i++) {
for (int j = 0; j < horizontal; j++) {
// Check cell value
if (newOriginalCells[j][i] == 1) {
g.setColor(Color.black);
} else {
g.setColor(Color.white);
}
// paint according to value
g.fillRect(j * 25, i * 25, 25, 25);
if (newOriginalCells[j][i] == 1) {
g.setColor(Color.white);
} else {
g.setColor(Color.black);
} // maybe change style?
g.drawRect(j * 25, i * 25, 25, 25);
}
}
}
}
I'm guessing, the problem is somewhere in newGeneration(), but other than that, I really have no idea anymore.
You have a common problem which I had myself a few months ago.
Java Swing GUI system works in thread called Event Dispatch Thread (EDT). This thread handle events like mouse clicks, typing etc. and paint the components to the screen. You should use this thread not as your main thread, but as sub-thread which working only once a certain time/when event happens, and not let him run continuously. In your code, since the user choose the cell to live, this thread run non-stop (because you started the program inside a listener, which is part of the EDT), and your GUI stuck, because it's updating only at the end of the thread.
You can solve this by using javax.swing.Timer. Timer is an object that allows you do tasks once a while, and it is perfect to this problem.
Use code like this:
ActionListener actionListaner = new ActionListener(){
public void actionPerformed(ActionEvent e){
//Put here you ne genration repeating code
}
};
int delay = 1000;//You delay between generations in millis
Timer timer = new timer(delay, actionListener);
The code in the actionPerformed method will repeat every second (or any other time you want it to repeat), and every operation of the timer will recall EDT instead of let it run non-stop.

setters and getters in java

I have two files one is the driver, I'm having a problem with setters. It looks did set the value .
public class Movie {
private String name;
private int minutes;
protected int tomatoScore;
public Movie(String name, int minutes, int tomatoScore)
{
this.name=name;
this.minutes=minutes;
this.tomatoScore=tomatoScore;
}
public String getName() {return name;}
public void setName(String name) {this.name=name;}
public int getMinutes() {return minutes;}
public boolean setMinutes(int minutes) {return minutes>=0;}
public int getTomatoScore() {return tomatoScore;};
public boolean setTomatoScore(int tomatoScore) {return tomatoScore>=0 &&tomatoScore<=100;};
public boolean isFresh() {return tomatoScore>=60;};
public void display()
{
//this.name = name;
//this.minutes = minutes;
//this.tomatoScore =tomatoScore;
System.out.println("Movie: "+ getName());
System.out.println("Length: "+ getMinutes() +"min.");
if(tomatoScore>=60)
{
System.out.println("TomatoScore: Fresh");
}
else
{
System.out.println("TomatoScore: Rotten");
}
}
}
and bellow is the driver file if you notice the setters did do the job that is supposed to do I believe the problem is movie class, if you run the driver to test the program you see if you set the value to the negative the if statement does not function properly.( setMinutes and setTomatoScore are wrong. They do not set the class fields at all)
public class MovieDriver {
public static void main (String [] args){
Movie[] myCollection = new Movie[5];
myCollection[0] = new Movie("Batman The Dark Knight", 152, 94);
myCollection[1] = new Movie("Guardians of the Galaxy", 125, 91);
myCollection[2] = new Movie("The GodFather", 178, 98);
myCollection[3] = new Movie("Suicide Squad", 137, 27);
myCollection[4] = new Movie("Get out", 104, 99);
//TODO
//Initialize the variable below and add it to myCollection at index 4.
//You can pick any movie you wish.
Movie yourMovie;
System.out.println("Here are all the movies in my collection of movies.\n");
for(int i = 0; i < myCollection.length; i++) {
if(myCollection[i] != null)
myCollection[i].display();
}
System.out.println("_______________________________________________");
System.out.println("\nHere are the Fresh movies.");
for(int i = 0; i < myCollection.length; i++) {
if(myCollection[i] != null && myCollection[i].isFresh()) {
System.out.println(myCollection[i].getName() + " is fresh.");
}
}
System.out.println();
System.out.println("Here are the Rotten movies.");
for(Movie movieTmp: myCollection){
if (movieTmp != null && !movieTmp.isFresh())
System.out.println(movieTmp.getName() + " is rotten.");
}
System.out.println("_______________________________________________\n");
Movie harryPotter = new Movie("Harry Potter and the Prisoner of Azkaban", 144, 91);
System.out.println("The movie " + harryPotter.getName() + " was created.\n");
System.out.println("Is " + harryPotter.getName() + " a long movie?");
if(harryPotter.getMinutes() > 120) {
System.out.println("Yes, it is a bit long.\n");
} else {
System.out.println("Nope, that isn't too bad.\n");
}
System.out.println("Can I set the minutes of " + harryPotter.getName() + " to a negative number?");
harryPotter.setMinutes(-5);
if(harryPotter.getMinutes() == -5) {
System.out.println("It worked. The runtime is -5 minutes.\n");
} else {
System.out.println("It did NOT work. Negative runtimes are not allowed.\n");
}
System.out.println("Can I set tomato score of " + harryPotter.getName() + " to a negative number?");
harryPotter.setTomatoScore(-100);
if(harryPotter.getTomatoScore() == -100) {
System.out.println("It worked. The score is -100. This movie is terrible according to the site.\n");
} else {
System.out.println("It did NOT work. Negative scores are not allowed.\n");
}
System.out.println("Can I set tomato score of " + harryPotter.getName() + " to a number greater than 100?");
harryPotter.setTomatoScore(101);
if(harryPotter.getTomatoScore() == 101) {
System.out.println("It worked. The score is 101. Best Harry Potter movie ever!\n");
} else {
System.out.println("It did NOT work. Still the best Harry Potter movie out all the movies though.\n");
}
}
}
Your setMinutes and setTomatoScore methods don't set anything, they just return a boolean. I assume you've forgotten to add this.tomatoScore = tomatoScore for example.
As rzwitserloot mentioned, setter function for minutes and tomatoScore are not setting any thing.This might be the case.
Additional I would like add, I found it is better to use well known IDE for java programming like intellij, netBean, eclipse. They have provide many feature like auto generate setter, getter , constructor. So we can focus more on core logic and this saves our time and reduce possiblity of manual error.
One more point I would like to add,
It is better to use setter in the constructor, so before setting value is we want to perform any input validation,we can have that in setter and can use that even when setting value via constructor.
For an example,
public class Example {
private int x;
public Movie(int x){setMinutes(x);}
public void setX(int x) {
//some validation on input
if(x >= 0){this.x = x;}
public int getX() {return x;}
Looks like you need this:
public boolean setMinutes(int minutes) {
if(minutes >= 0 && minutes < 60) {
//I'm guessing the <60 part here, but whatever,
//this is how you'd set the 100 limit on your setTomatoScore method
this.minutes = minutes;
return true;
}
return false;
}
Make similar corrections for the setTomatoScore
​You need to set something tomatoScore in the state of methods as shown below​​ :
public boolean setTomatoScore(int tomatoScore) {
if (tomatoScore >= 0 && tomatoScore <= 100) {
this.tomatoScore = tomatoScore;
return true;
}
return false;
}

JComboBox doesn't give the Index

I can't understand what's wrong.
I have a JFrame, with JTextFields and JComboBoxes. When I push a button, it has to take the values from the JTextFields and pass them to one of the methods, which is chosen in the JComboBox, but I can't get the index of the items within the JComboBox.
Here is my code:
public class eHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
if (e.getSource() == esc) {
bx.setText(null);
by.setText(null);
bt0.setText(null);
setVisible(false);
window window = new window("Расчет напряжений");
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(600, 650);
}
if (e.getSource() == count) {
double x = Double.parseDouble(bx.getText());
double y = Double.parseDouble(by.getText());
double t0 = Double.parseDouble(bt0.getText());
Integer item = (Integer)ras.getSelectedIndex();
JOptionPane.showMessageDialog(null, item);
if (item == 0) {
double tens = linear(x, y, t0);
ltr.setText("Напряжение на данном периоде: " + tens + " Мпа");
}
if (item == 1) {
double tens = squard(x, y, t0);
ltr.setText("Напряжение на данном периоде: " + tens + " Мпа");
}
}
}//try
catch(Exception ex){
JOptionPane.showMessageDialog(null, "Введите корректные данные");
}
}
}
It's wrong in:
Integer item = (Integer)ras.getSelectedIndex();
JOptionPane.showMessageDialog(null, item);
Thanks for answers. But it is wrong that i try to use {Listener} for {ComboBox} in other {Listener}. I made a special {Listener} for {JComboBox}, and that has work. Best regards))

JAVA swing. movement from random point to random point

i have a problem with one thing. I have a map of 10 cities and a civilian. I want the civilian to be walking from city to city randomly. But the problem is that the city is beeing chosen on and on so the civilian is changing the destination before he reachs it. This is my part of a code of a Jpanel where everything is drawn:
#Override
public void run() {
while (running) {
update();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException ex) {
}
}
}
private void update() {
if (game != null && running == true) {
c.goTo(cities); // c is civilian
}
}
and this is part of code for civilian
private boolean set = true;
public void move(int x, int y) {
if (this.location.x != x || this.location.y != y) {
if (this.location.x > x) {
this.location.x -= 1;
} else {
this.location.x += 1;
}
if (this.location.y > y) {
this.location.y -= 1;
} else {
this.location.y += 1;
}
}
}
public void goTo(ArrayList<City> cities) {
City city;
if (set) {
city = cities.get(rand());
move(city.location.x, city.location.y);
set = false;
} else {
set = true;
}
}
public int rand() {
int i;
Random rand = new Random();
i = rand.nextInt(10);
return i;
}
How to solve it ?
So, your problem is here:
while (running) {
update();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException ex) {
}
}
You're calling update every 17 milliseconds which in turn is causing your civilian to move to a new city every 17 milliseconds. You could make a separate statement that calls update while another boolean statement is false so that you travel only when he is in a city.
For example:
boolean travelling = //whatever you go about to configure this
while(travelling == false){
update();
}
This will cause him to only travel when he is not in a city. Here is some very rough code (you will have to configure it to your liking):
//civilian x //civilian y
if(this.location.x == //randomed city.x && this.location.y == //randomed city.y){
travelling = false;
}
This will most likely need to be within the run() method in your first set of code, so it can be checked over and over. But let me explain what the above code is doing:
First, you have a thread or something keeping it running checking if your civilian's x and y correspond to the most recently randomed city's x and y, obviously when they're the same, the civilian is at the city.
Second, when the x and y's are the same, the statement makes travelling false
Third, When travelling is false, your custom update method is called, picking a new city, at random and putting your civilian back on the move.

Recursively splitting off perfect squares for display

I am attempting to create a recursive method that accepts an integer parameter and prints the first n squares
separated by commas, with the odd squares in descending order followed by the even squares in ascending order.
For example, if the input is 8, it should print the following output:
49, 25, 9, 1, 4, 16, 36, 64
My code so far is:
s and n have the same values initially, the only difference is that s changes as the code forwards while n doesn't change.
private static void genSquare(int s, int n) {
if (s >= 0 && s <= n) {
if (isOdd(s)) {
System.out.print(Math.pow(n, 2) + " ");
genSquare(s - 2, n);
}
if (s == 0 || s == 1) {
genSquare(1, n);
}
if (isEven(s)) {
System.out.print(Math.pow(n, 2) + " ");
genSquare(s + 2, n);
}
}
}
I have created a while loop version of it, which works perfectly. I just don't have the recursive version working.
Sample inputs would be using the same number for s and n.
Here is the code for the loop version:
private void genLoop(int s, int n) {
if (isEven(s)) {
s--;
}
while (s <= n) {
if (s == 1) {
System.out.print(1 + " ");
s++;
} else if (isOdd(s)) {
System.out.print(s * s + " ");
s -= 2;
} else if (isEven(s)) {
System.out.print(s * s + " ");
s += 2;
}
}
}
The problem is in this statement:
if(s == 0 || s== 1)
genSquare(1,n);
This causes the method to recurse infinitely. In fact, when you get to the point where s is zero or one, you have to make sure that you DON'T call genSquare recursively.
That's enough of a hint for you to figure the rest out for yourself ... and fix any other bugs.
In addition, there's a simpler way of squaring an integer ...
void calculateSquare(int n)
{
// odds descending and even ascending
int t=n;
if(n<=0)
return;
if(n%2==1)
{
// Calculate square now and print it also
System.out.println(n*n);
calculateSquare(--n);
}
else
{
calculateSquare(--n);
System.out.println(t*t);
}
}
This would do the job.
Try the following approach:
Assume your example where n is equal to 8. The square of 8 should printed last so you probably first should do a recursive call, then print the square of the current number.
Thinking about the task for n=7 the order of things given above should be reverted for odd numbers.
Yes it is good example for recursion . Try this it helps u
public class RecursionEx {
static int no = 0;
public static void main(String[] args) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the Number");
try
{
no = Integer.parseInt(bufferedReader.readLine());
getSquares(no,0);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void getSquares(int number,int count)
{
if(number==1)
{
System.out.print(number);
count=1;
getSquares(number+1, count);
}
else
{
if(number%2!=0&&count==0)
{
System.out.print(number*number+",");
getSquares(number-2,0);
return;
}
if(count==0)
getSquares(number-1,0);
if(number%2==0&&count==1)
{
if(number<=no)
System.out.print(","+number*number);
if(number>=no)
return;
getSquares(number+2, count);
}
}
}
}

Categories