Null Pointer Exception with a timer - java

I am having an issue with an assignment I have: I need to write a game with a timer component but I get a "Exception in thread "Timer-0" java.lang.NullPointerException" error. I am using the latest version of eclipse. Help would be appreciated.
The actual error:
Exception in thread "Timer-0" java.lang.NullPointerException
at GameFrame$MyTimerTask.run(GameFrame.java:152)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GameFrame extends JFrame implements ActionListener {
private final int NUM_BUTTONS1 = 5;
private final int NUM_BUTTONS2 = 8;
private final int NUM_BUTTONS3 = 10;
private final int NUM_LEVELS = 3;
private int[] columns,lines;
private int current_size,hours,minutes,seconds,score,selection_counter;
private int c1,c2,c3,c4,l1,l2,l3,l4;
private Color color1,color2,color3,color4;
private JButton [] buttons,selection;
private JButton [] levels;
private JPanel buttons_panel,levels_panel;
private JTextField timer_field,score_field;
private Timer timer;
public GameFrame() {
current_size = NUM_BUTTONS1;
setLayout(new BorderLayout());
buttons_panel = new JPanel();
buttons_panel.setLayout(new GridLayout(NUM_BUTTONS1,NUM_BUTTONS1));
//setup buttons
buttons = new JButton[NUM_BUTTONS3 * NUM_BUTTONS3];
for(int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton();
switch((int)(Math.random() * 4)) {
case 0:
buttons[i].setBackground(Color.BLUE);
break;
case 1:
buttons[i].setBackground(Color.RED);
break;
case 2:
buttons[i].setBackground(Color.GREEN);
break;
case 3:
buttons[i].setBackground(Color.YELLOW);
break;
}
buttons[i].addActionListener(this);
}
//add buttons to layout
for(int i = 0; i < NUM_BUTTONS1 * NUM_BUTTONS1; i++)
buttons_panel.add(buttons[i]);
levels_panel = new JPanel();
levels_panel.setLayout(new GridLayout(3,1));
levels = new JButton[NUM_LEVELS];
for(int i = 0; i < levels.length; i++) {
levels[i] = new JButton("level "+ (i + 1));
levels[i].addActionListener(this);
levels_panel.add(levels[i]);
}
selection_counter = 0;
selection = new JButton[4];
columns = new int [4];
lines = new int [4];
hours = 0;
minutes = 0;
seconds = 0;
timer = new Timer();
timer.schedule(new MyTimerTask(), 0,1000);
timer_field = new JTextField();
timer_field.setText(hours + ":" + minutes + ":" + seconds);
timer_field.setFont(new Font("random",0,50));
timer_field.setHorizontalAlignment(JTextField.CENTER);
timer_field.setBackground(Color.white);
timer_field.setForeground(Color.green);
add(timer_field,BorderLayout.SOUTH);
score_field = new JTextField();
score_field.setText("Game Score: " + score);
score_field.setFont(new Font("random",0,50));
score_field.setHorizontalAlignment(JTextField.CENTER);
score_field.setBackground(Color.white);
score_field.setForeground(Color.green);
add(score_field,BorderLayout.NORTH);
//add buttons layout and levels buttons layout
add(buttons_panel,BorderLayout.CENTER);
add(levels_panel,BorderLayout.WEST);
}
#Override
public void actionPerformed(ActionEvent event) {
//change levels
if (event.getSource() == levels[0] || event.getSource() == levels[1] || event.getSource() == levels[2]) {
if (event.getSource() == levels[0])
current_size = NUM_BUTTONS1;
else if (event.getSource() == levels[1])
current_size = NUM_BUTTONS2;
else if (event.getSource() == levels[2])
current_size = NUM_BUTTONS3;
buttons_panel.removeAll();
//redefine grid Layout to match the new current_size
buttons_panel.setLayout(new GridLayout(current_size, current_size));
for(int i = 0; i < current_size * current_size; i++)
buttons_panel.add(buttons[i]);
newGame(); //changing levels requires starting a new game
}
//select a rectangle on the board
else if (event.getSource() instanceof JButton) {
selection[selection_counter++] = (JButton)event.getSource();
if (selection_counter == 4) {
selection_counter = 0;
columns = findCoordinates(true);
lines = findCoordinates(false);
if (buttonsSelectionCheck()) {
updateBoard();
}
}
}
//update the window
timer_field.setText(hours + ":" + minutes + ":" + seconds);
score_field.setText("Game Score: " + score);
buttons_panel.validate();
repaint();
}
public class MyTimerTask extends TimerTask {
public void run() {
seconds++;
if (seconds == 60) {
minutes++;
seconds = 0;
}
if (minutes == 60) {
hours++;
minutes = 0;
}
timer_field.setText(hours + ":" + minutes + ":" + seconds);
}
}
private void newGame() {
score = 0;
seconds = 0;
minutes = 0;
hours = 0;
selection_counter = 0;
selection[0] = null;
selection[1] = null;
selection[2] = null;
selection[3] = null;
for(int i = 0; i < buttons.length; i++) {
switch((int)(Math.random() * 4)) {
case 0:
buttons[i].setBackground(Color.BLUE);
break;
case 1:
buttons[i].setBackground(Color.RED);
break;
case 2:
buttons[i].setBackground(Color.GREEN);
break;
case 3:
buttons[i].setBackground(Color.YELLOW);
break;
}
}
}
private int[] findCoordinates(boolean choice) {
int[] columns = new int[4];
int[] lines = new int[4];
for (int i = 0; i < selection.length; i++)
for (int j = 0; j < buttons.length; j++)
if (selection[i] == buttons[j]) {
if (choice)
columns[i] = j%current_size;
else
lines[i] = j/current_size;
}
if (choice)
return columns;
else
return lines;
}
public boolean buttonsSelectionCheck() {
c1 = columns[0];
c2 = columns[1];
c3 = columns[2];
c4 = columns[3];
l1 = lines[0];
l2 = lines[1];
l3 = lines[2];
l4 = lines[3];
color1 = selection[0].getBackground();
color2 = selection[1].getBackground();
color3 = selection[2].getBackground();
color4 = selection[3].getBackground();
if (color1 != Color.GRAY && color1 == color2 && color2 == color3 && color3 == color4)
if (c1 == c4 && c2 == c3 && l1 == l2 && l3 == l4 ) {
return true;
}
return false;
}
private void updateBoard() {
int b_column,b_line;
for (int i = 0; i < (current_size * current_size); i++) {
b_column = i%current_size;
b_line = i/current_size;
if (b_column >= c1 && b_column <= c2 && b_line >= l1 && b_line <= l4) {
if (buttons[i].getBackground() != Color.GRAY)
score+=10;
buttons[i].setBackground(Color.GRAY);
}
}
}
}

This line causes the MyTimerTask instance to be executed with a delay of 0 (no delay).
timer.schedule(new MyTimerTask(), 0,1000);
MyTimerTask accesses the field timer_field, which is initialized after the schedule statement.
timer_field = new JTextField();
So the timer_field is still null.
Solution:
// timer.schedule(new MyTimerTask(), 0,1000);
timer_field = new JTextField();
timer_field.setText(hours + ":" + minutes + ":" + seconds);
timer_field.setFont(new Font("random",0,50));
timer_field.setHorizontalAlignment(JTextField.CENTER);
timer_field.setBackground(Color.white);
timer_field.setForeground(Color.green);
timer.schedule(new MyTimerTask(), 0,1000);
So the schedule call should be a bit later.

your inner class MyTimerTask uses timer_field before it's initialised.
you can move these lines:
timer = new Timer();
timer.schedule(new MyTimerTask(), 0,1000);
to the end of the constructor, so that it is after this one which initialises timer_field:
timer_field = new JTextField();

Related

Main method in different class can't detect button press

I'm making a program for practice and it's basically simulating winning/losing Powerball tickets. Anyways, the main class is in launchPowerBall.java and the button that I am trying to detect when clicked is in PowerBallGUI.java. The button works by itself, however, the main in launchPowerBall.java isn't able to detect it even though I set up myself a few setters and getters. Any clue what alternative I can do instead? Because it seems as though even though I run it through a while(true) loop and I keep pressing the button, there seems to be no detection from the main method.
Here's the action listener for the JButton:
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// If the button is pressed, delete text field and replace with new content
setButtonPressed(true);
outputText.setText("");
outputText.setText(outText);
}
});
Here's what I'm trying to do for the main method:
public static void main(String[] args) throws InterruptedException {
// Build the GUI object
PowerBallGUI GUI = new PowerBallGUI();
GUI.buildGUI();
//GUI.setTextArea("banana");
// Build the PowerBall object
PowerBall roll = new PowerBall();
while(true) {
if (GUI.getJButton().getModel().isPressed()) {
System.out.println("TEST");
}
}
}
Here's the three files if you need to see my code:
1) https://gist.github.com/anonymous/e5950413470202cd1ac6d24e238ff693
2) https://gist.github.com/anonymous/773e4e4454a79c057da78eed038fade1
3) https://gist.github.com/anonymous/82335e634c1f84607d3021b4d683cc65
Powerball...
public class PowerBall {
private int[] numbers = {0, 0, 0, 0, 0};
private int[] lotteryNumbers = {0, 0, 0, 0, 0};
private int powerBall;
private int lotteryPowerBall;
private double balance;
private double winnings;
/*** Constructor Methods ***/
public PowerBall() {
powerBall = 0;
balance = 1000;
winnings = 0;
}
/*** Mutator Methods ***/
public void randomize() {
int i;
int highestNumber = 59;
int highestPowerball = 32;
int temp = 0;
for (i = 0; i < numbers.length; i++) {
// Choose a random number
temp = (int)(Math.random() * highestNumber);
numbers[i] = temp;
}
// Choose a random Powerball number
powerBall = (int)(Math.random() * highestPowerball);
// Choose the lottery numbers
for (i = 0; i < lotteryNumbers.length; i++) {
temp = (int)(Math.random() * highestNumber);
lotteryNumbers[i] = temp;
}
lotteryPowerBall = (int)(Math.random() * highestPowerball);
}
public void calculate() {
int matches = 0;
int powerballMatches = 0;
if (balance > 0) {
// Check to see if there are any matches between the two sets of numbers
for (int i = 0; i < numbers.length; i++) {
for (int j = 0; j < lotteryNumbers.length; j++) {
if (numbers[i] == lotteryNumbers[j]) {
matches++;
}
}
}
// Check to see if the two different powerball numbers match
if (powerBall == lotteryPowerBall) {
powerballMatches = 1;
}
// Calculate the balance/winnings if there were any matches
if (matches == 0 && powerballMatches == 0) {
balance = balance - 2;
winnings = winnings - 2;
} else if (matches == 0 && powerballMatches == 1) {
balance = balance + 4;
winnings = winnings + 4;
} else if (matches == 0 && powerballMatches == 0 || matches == 1 && powerballMatches == 0) {
balance = balance - 2;
winnings = winnings - 2;
} else if (matches == 2 && powerballMatches == 1) {
balance = balance + 7;
winnings = winnings + 7;
} else if (matches == 3 && powerballMatches == 0) {
balance = balance + 7;
winnings = winnings + 7;
} else if (matches == 3 && powerballMatches == 1) {
balance = balance + 100;
winnings = winnings + 100;
} else if (matches == 4 && powerballMatches == 0) {
balance = balance + 100;
winnings = winnings + 100;
} else if (matches == 4 && powerballMatches == 1) {
balance = balance + 50000;
winnings = winnings + 50000;
} else if (matches == 5 && powerballMatches == 0) {
balance = balance + 1000000;
winnings = winnings + 1000000;
} else if (matches == 5 && powerballMatches == 1) {
balance = balance + 10000000;
winnings = winnings + 10000000;
}
//System.out.println("There is currently " + matches + " number matches.");
//System.out.println("There is currently " + powerballMatches + " powerball number matches.\n");
} else {
System.out.println("YOU ARE BROKE!");
}
}
/*** Accessor/Observor Methods ***/
public void displayBalance() {
System.out.print("Your balance is at: $");
System.out.printf("%.2f", balance);
}
public void displayWinnings() {
System.out.print("\nYou have currently won: $");
System.out.printf("%.2f", winnings);
System.out.println("\n");
}
public String toString() {
StringBuilder builder = new StringBuilder();
StringBuilder builder2 = new StringBuilder();
if (numbers.length == lotteryNumbers.length) {
for (int i = 0; i < numbers.length; i++) {
if (i < numbers.length - 1) {
builder.append(numbers[i] + ", ");
builder2.append(lotteryNumbers[i] + ", ");
} else {
builder.append(numbers[i] + " + ");
builder2.append(lotteryNumbers[i] + " + ");
}
}
} else {
return "ERROR: Numbers max set of numbers doesn't match Lottery Numbers max set of numbers!\n";
}
return "Your set of numbers were: " + builder + Integer.toString(powerBall) +
"\nThe powerball numbers were: " + builder2 + lotteryPowerBall;
}
}
Launcher
public class launchPowerBall {
public static void main(String[] args) throws InterruptedException {
// Build the GUI object
PowerBallGUI GUI = new PowerBallGUI();
GUI.buildGUI();
//GUI.setTextArea("banana");
// Build the PowerBall object
PowerBall roll = new PowerBall();
while(true) {
if (GUI.getJButton().getModel().isPressed()) {
System.out.println("TEST");
}
}
//System.out.println("TOO LATE!");
//while (true) {
/*roll.randomize();
System.out.println(roll.toString());
roll.calculate();
roll.displayBalance();
roll.displayWinnings();
Thread.sleep(500); */
//}
}
}
GUI
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
public class PowerBallGUI {
private JButton start = new JButton("Launch the Powerball!");
private boolean buttonPressed = false;
private String outText;
/*** Constructor Methods ***/
public PowerBallGUI() {
#SuppressWarnings("unused")
JTextArea outputText = new JTextArea("Press the 'Launch the Powerball' button to start!");
}
/*** Setters ***/
/*** Sets the JTextArea object ***/
public void setTextArea (String str) {
this.outText = str;
}
public void setButtonPressed (Boolean bool) {
this.buttonPressed = bool;
}
/*** Getters ***/
public Boolean getButtonPressed() {
return this.buttonPressed;
}
public JButton getJButton() {
return this.start;
}
/*** Builds the GUI ***/
public void buildGUI() {
// Create the Java Frame itself
JFrame frame = new JFrame("Can YOU win the Powerball? v1.0 (Programmed by: Josh Yang)");
// Sets the default close operation of the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Sets the size of the frame
frame.setSize(800, 500);
// Sets the location of the frame
centerGUI(frame);
// Allows the frame to be seen
frame.setVisible(true);
// Disables frame resizing
//frame.setResizable(false);
// Create the Java Panel itself
JPanel panel = new JPanel();
JPanel contentPanel = new JPanel();
JPanel launchPanel = new JPanel();
// Sets the sides of the Java panels
panel.setSize(800, 150);
// Set the panel background color
panel.setBackground(Color.YELLOW);
contentPanel.setBackground(Color.YELLOW);
launchPanel.setBackground(Color.PINK);
// Add the panel onto the frame
frame.add(panel, "North");
frame.add(contentPanel, BorderLayout.CENTER);
frame.add(launchPanel, BorderLayout.SOUTH);
// Set top panel's preferred size dimensions
panel.setPreferredSize(new Dimension(800, 100));
// Adds components onto the panel
JLabel title = new JLabel("Can YOU win the lottery? v1.0", SwingConstants.CENTER);
title.setFont(new Font("Serif", Font.BOLD, 25));
panel.add(title);
String text = "Basically, we start you off at $1000 and buy tickets in increments of $2 until you win big (if you do, that is)!";
JLabel description = new JLabel();
description.setText(text);
description.setFont(new Font("Serif", Font.PLAIN, 16));
panel.add(description);
// ContentPanel area
JLabel cDescription = new JLabel("Output: ");
contentPanel.add(cDescription);
JTextArea outputText = new JTextArea(17, 60);
outputText.setBackground(Color.PINK);
outputText.setEditable(false);
outputText.setText("Press the 'Launch the Powerball' button to start!");
contentPanel.add(outputText);
start.setLocation(100, 100);
launchPanel.add(start);
// Add an action listener to the JButton
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// If the button is pressed, delete text field and replace with new content
setButtonPressed(true);
outputText.setText("");
outputText.setText(outText);
}
});
frame.revalidate();
//frame.pack();
}
/*** Centers the GUI based on screen size ***/
public static void centerGUI(Window frame) {
// Gets the size of the screen
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - frame.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - frame.getHeight()) / 2);
// Set the frame location based on x and y
frame.setLocation(x, y);
}
}
The simple solution is to take the functionality you're "trying" to execute in the main method and put in the ActionListener...
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// If the button is pressed, delete text field and replace with new content
PowerBall roll = new PowerBall();
roll.randomize();
System.out.println(roll.toString());
roll.calculate();
roll.displayBalance();
roll.displayWinnings();
setButtonPressed(true);
outputText.setText("");
outputText.setText(outText);
}
});
If you "really" want to do more work in the main, you will need to generate some kind of observer pattern which can notified when something occurs.
You could put one on Powerball so it could notify you of a status change or on the GUI which notify you that the start button was pressed

Break ( stop ) button for a looping function in another button function ( Java )

I've been trying to make it so the buttonb ( Stop ) can break the loop, inside of the loop function. I just need the loop to stop or be broke by the buttonb ( stop ) button. Thanks. :) [ I've tried looking, but, to my avail have not found any results that could help me. ]
/*
*
*/
package stopwatch;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
/**
*
* #author C
*/
public class Stopwatch {
/**
* #param args the command line arguments
*/
private static int abc = 0;
private static void print (int x, String b) {
if ( x == 69 ) {
System.out.println(b);
}
if ( b == null ) {
System.out.println(x);
}
}
private static void changea(int val) {
abc = val;
}
public static void main(String[] args) {
JFrame aeeb = new JFrame("Stopwatch : Start");
aeeb.setVisible(true);
aeeb.setSize(50, 150);
JButton button = new JButton("Start");
button.setVisible(true);
aeeb.add(button);
JFrame aeec = new JFrame("Stopwatch : Stop");
aeec.setVisible(true);
aeec.setSize(50, 150);
final JButton buttonb = new JButton("Stop");
buttonb.setVisible(true);
aeec.add(buttonb);
button.addActionListener(new ActionListener() {
int x = 1;
int msec = 0;
int sec = 0;
int min = 0;
int hour = 0;
public void actionPerformed(ActionEvent e)
{
if ( x == 1 ) {
print(69, "Stopwatch is running!");
x = 0;
int xd = 10;
while( xd < 20 ) {
if ( msec == 1000 ) {
sec = sec + 1;
msec = 0;
}
if ( sec == 60 ) {
min = min + 1;
sec = 0;
}
if ( min == 60 ) {
hour = hour + 1;
min = 0;
}
msec++;
if ( msec == 1000 ) {
sec = sec + 1;
msec = 0;
}
if ( sec == 60 ) {
min = min + 1;
sec = 0;
}
if ( min == 60 ) {
hour = hour + 1;
min = 0;
}
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(Stopwatch.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
if ( x == 0 ) {
print(69, "Stopwatch is running already!");
}
}
});
}
}
Use a flag and set it to false when the stop button is pressed.
public class Stopwatch {
...
private boolean isRunning = false;
...
your loop inside of the Start button action:
...
isRunning = true;
...
while(isRunning) {
...
stop button:
final JButton buttonb = new JButton("Stop");
buttonb.setVisible(true);
aeec.add(buttonb);
aeec.addActionListener(new ActionListener(){
isRunning = false;
});
Maybe do something like this:
public class stopwatch{
public boolean isOn = true;
// stuff
// loop:
if(!something.isOn){
break;
}
// rest of loop
}
And for the button press:
Stopwatch.isOn = false;

GUI Calculator with no number buttons

Hello I have this calculator and I want it to be buttonless like make the user input in the textfield but I don't know how to make it work like that. I want to simplify it like this but I don't know how to make it work without the number buttons.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class MP2_2 extends JFrame implements ActionListener {
Container c;
JTextField result;
JPanel p = new JPanel();
JButton b[] = new JButton[16];
String s[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "/", "*", "=", "C"};
//----------------------Me------------------------
String Screen = "", monitor1 = "", monitor2 = "", OperationOnScreen = "";
boolean CommandEmpty = true, switcher = true;
double R = Integer.MIN_VALUE, L = Integer.MIN_VALUE;
//------------------------------------------------
public MP2_2() {
super("MP2_2");
c = getContentPane();
result = new JTextField();
result.setEditable(true);
p.setLayout(new GridLayout(4, 4));
for (int i = 0; i < 16; i++) {
b[i] = new JButton(s[i]);
b[i].addActionListener(this);
p.add(b[i]);
}
c.add(result, BorderLayout.NORTH);
c.add(p);
}//End Constructor
public static void main(String[] args) {
MP2_2 calcu = new MP2_2();
calcu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
calcu.setSize(300, 300);
calcu.setVisible(true);
}
//------------------------------------------------
public void actionPerformed(ActionEvent event) {
for (int i = 0; i <= 9; i++)//Numbers
{
if (event.getSource() == b[i]) {
Screen += i;
result.setText("");
result.setText(Screen);
}
}
for (int i = 10; i <= 14; i++)//Commands
{
if (event.getSource() == b[i]) {
if (result.getText().lastIndexOf(OperationOnScreen) != -1)//prevent exception
{
result.setText(result.getText().substring(0, result.getText().lastIndexOf(OperationOnScreen)) + s[i]);
} else {
result.setText(result.getText() + s[i]);
}
OperationOnScreen = s[i];
if (switcher) {
monitor1 = s[i];
switcher = false;
} else {
monitor2 = s[i];
switcher = true;
}
if (monitor1 != monitor2 && monitor2 != "") {
if (switcher) //execute older,send sign newer
{
Calc(event, monitor1.charAt(0), monitor2);
} else {
Calc(event, monitor2.charAt(0), monitor1);
}
}
if (s[i] != "=") //calc returns 0
{
Calc(event, s[i].charAt(0), s[i]);
}
}
}
if (event.getSource() == b[15]) //Clear
{
Screen = "";
monitor1 = "";
monitor2 = "";
switcher = true;
CommandEmpty = true;
result.setText("");
}
}//end actionPerformed
public void Calc(ActionEvent event, char OpType, String Operator) {
if (Operator == "=") {
Operator = "";
}
if (CommandEmpty && Screen == "") {
return;
} else if (CommandEmpty && Screen != "") {
R = Integer.parseInt(Screen);
result.setText(Screen + Operator);
Screen = "";
CommandEmpty = false;
} else if (!CommandEmpty && Screen != "") {
L = Integer.parseInt(Screen);
R = Operations(R, L, OpType);//calculate
Screen = "";
result.setText("");
result.setText(R + Operator);
}
}//End Calc
public static double Operations(double R, double L, char op) {
switch (op) {
case '+':
return R + L;
case '-':
return R - L;
case '*':
return R * L;
case '/':
return R / L;
}
return 0;
}
}//end class
EDIT: I guess my question wasn't clear sorry. I wanted my program to support inputs from the keyboard also, How do I do this? So I can finally delete the number buttons like in the picture.
When you remove the buttons, you'll need to restore the action of the buttons with a call to result.getText().
Here is the code that works on your number buttons. It sets the value of Screen.
for (int i = 0; i <= 9; i++)//Numbers
{
if (event.getSource() == b[i]) {
Screen += i;
result.setText("");
result.setText(Screen);
}
}
Therefore, when you hit your operation buttons, you will need to set Screen.
Here is your loop for Commands. I added Screen = result.getText(); in the else block. It worked for me.
for (int i = 10; i <= 14; i++)//Commands
{
if (event.getSource() == b[i]) {
if (result.getText().lastIndexOf(OperationOnScreen) != -1)//prevent exception
{
result.setText(result.getText().substring(0, result.getText().lastIndexOf(OperationOnScreen)) + s[i]);
} else {
Screen = result.getText();
result.setText(result.getText() + s[i]);
}

Recursively find connectivity in a 2D Array

I have a game and I'm having trouble implementing the scores.
Prof stated that it must be recursively done without a for-loop. But I'm having trouble thinking of the algorithm that is used. This is the game.
The score system works so it starts with the valve pipe (Pipe.ValvePipe) and then it checks to see how many pipes are connected to it. Is there a certain algorithm/strategy for doing this type of recursion? Thank you in advance.
pipe.java
public class Pipe {
private boolean openAtTop;
private boolean openAtRight;
private boolean openAtBottom;
private boolean openAtLeft;
private boolean isValve;
private static Pipe VALVE_PIPE;
public Pipe(boolean t, boolean r, boolean b, boolean l, boolean valve) {
openAtTop = t; openAtBottom = b; openAtRight = r; openAtLeft = l;
isValve = valve;
}
public boolean isValve() { return isValve; }
public static Pipe ValvePipe() { return new Pipe(false, false, true, false, true); }
public boolean isValid() { return !(!openAtTop&&!openAtBottom&&!openAtLeft&&!openAtRight); }
public static Pipe RandomPipe() {
Pipe p;
do {
p = new Pipe(Math.random() < 0.5, Math.random() < 0.5,
Math.random() < 0.5, Math.random() < 0.5, false);
} while (!p.isValid());
return p;
}
public boolean isOpenAtTop() { return openAtTop; }
public boolean isOpenAtBottom() { return openAtBottom; }
public boolean isOpenAtLeft() { return openAtLeft; }
public boolean isOpenAtRight() { return openAtRight; }
public boolean fitsBelow(Pipe p) {
return (p == null) || (!openAtTop && !p.isOpenAtBottom()) || (openAtTop && p.isOpenAtBottom());
}
public boolean fitsAbove(Pipe p) {
return (p == null) || (!openAtBottom && !p.isOpenAtTop()) || (openAtBottom && p.isOpenAtTop());
}
public boolean fitsToLeftOf(Pipe p) {
return (p == null) || (!openAtRight && !p.isOpenAtLeft()) || (openAtRight && p.isOpenAtLeft());
}
public boolean fitsToRightOf(Pipe p) {
return (p == null) || (!openAtLeft && !p.isOpenAtRight()) || (openAtLeft && p.isOpenAtRight());
}
public String toString() {
String s = "";
if (openAtTop) s+="1"; else s+="0";
if (openAtRight) s+="1"; else s+="0";
if (openAtBottom) s+="1"; else s+="0";
if (openAtLeft) s+="1"; else s+="0";
return s;
}
public int toInt() {
int s = 0;
if (openAtTop) s+=8;
if (openAtRight) s+=4;
if (openAtBottom) s+=2;
if (openAtLeft) s+=1;
return s;
}
}
PipeGameView.java
import java.awt.*;
import javax.swing.*;
// Subclass JFrame so you can display a window
public class PipeGameView extends JPanel {
private PipeGame game; // The model
private BoardPanel tiles;
private JButton[][] buttons;
private JProgressBar timeBar;
private JButton startStop;
private JRadioButton twoMinButton, tenMinButton, noLimitButton;
private JLabel statusLabel;
// This constructor builds the window
public PipeGameView(PipeGame g) {
game = g; // Store the model for access in update()
// Set up the components
tiles = new BoardPanel();
tiles.setLayout(new GridLayout(game.getRows(), game.getRows()));
buttons = new JButton[game.getRows()][game.getRows()];
// Add the buttons to the tile panel
ImageIcon ic = new ImageIcon("Pipes0000.GIF");
for (int r=0; r<game.getRows(); r++) {
for (int c=0; c<game.getRows(); c++) {
buttons[r][c] = new JButton(ic);
tiles.add(buttons[r][c]);
}
}
// Now layout the components using a gridbag layout
GridBagLayout layout = new GridBagLayout();
GridBagConstraints layoutConstraints = new GridBagConstraints();
this.setLayout(layout);
// Add the Start/Stop Button
startStop = new JButton("Start Game");
layoutConstraints.gridx = 0; layoutConstraints.gridy = 0;
layoutConstraints.gridwidth = 1; layoutConstraints.gridheight = 1;
layoutConstraints.fill = GridBagConstraints.BOTH;
layoutConstraints.insets = new Insets(2, 2, 2, 2);
layoutConstraints.anchor = GridBagConstraints.NORTHWEST;
layoutConstraints.weightx = 0.0; layoutConstraints.weighty = 0.0;
layout.setConstraints(startStop, layoutConstraints);
this.add(startStop);
// Add the JRadioButtons
twoMinButton = new JRadioButton("2 minutes");
tenMinButton = new JRadioButton("10 minutes");
noLimitButton = new JRadioButton("No Time Limit");
ButtonGroup group = new ButtonGroup();
group.add(twoMinButton); group.add(tenMinButton); group.add(noLimitButton);
layoutConstraints.gridx = 1;
layout.setConstraints(twoMinButton, layoutConstraints);
this.add(twoMinButton);
layoutConstraints.gridx = 2;
layout.setConstraints(tenMinButton, layoutConstraints);
this.add(tenMinButton);
layoutConstraints.gridx = 3;
layout.setConstraints(noLimitButton, layoutConstraints);
this.add(noLimitButton);
// Add the tiles
layoutConstraints.gridx = 0; layoutConstraints.gridy = 1;
layoutConstraints.gridwidth = 4; layoutConstraints.gridheight = 1;
layoutConstraints.fill = GridBagConstraints.BOTH;
layoutConstraints.insets = new Insets(2, 2, 2, 2);
layoutConstraints.anchor = GridBagConstraints.NORTHWEST;
layoutConstraints.weightx = 0.0; layoutConstraints.weighty = 0.0;
layout.setConstraints(tiles, layoutConstraints);
this.add(tiles);
// Add the label
statusLabel = new JLabel("Time Left: ");
statusLabel.setVisible(false);
layoutConstraints.gridx = 0; layoutConstraints.gridy = 2;
layoutConstraints.gridwidth = 1; layoutConstraints.gridheight = 1;
layoutConstraints.fill = GridBagConstraints.NONE;
layoutConstraints.insets = new Insets(2, 2, 2, 2);
layoutConstraints.anchor = GridBagConstraints.WEST;
layoutConstraints.weightx = 0.0; layoutConstraints.weighty = 0.0;
layout.setConstraints(statusLabel, layoutConstraints);
this.add(statusLabel);
timeBar = new JProgressBar(0, 100);
timeBar.setValue(100);
timeBar.setVisible(false);
layoutConstraints.gridx = 1; layoutConstraints.gridy = 2;
layoutConstraints.gridwidth = 3; layoutConstraints.gridheight = 1;
layoutConstraints.fill = GridBagConstraints.HORIZONTAL;
layoutConstraints.insets = new Insets(2, 2, 2, 2);
layoutConstraints.anchor = GridBagConstraints.EAST;
layoutConstraints.weightx = 5.0; layoutConstraints.weighty = 0.0;
layout.setConstraints(timeBar, layoutConstraints);
this.add(timeBar);
update();
}
// Get methods for the components
public JButton getButton(int r, int c) { return buttons[r][c]; }
public JButton getStartStopButton() { return startStop; }
public JProgressBar getTimeBar() { return timeBar; }
public JRadioButton getTwoMinButton() { return twoMinButton; }
public JRadioButton getTenMinButton() { return tenMinButton; }
public JRadioButton getNoLimitButton() { return noLimitButton; }
public void setGame(PipeGame g) { game = g; }
// This is called whenever the model has changed. Note that this code is not efficient. All ICONS should really
// be loaded upon game start and stored into a static array of ImageIcons. Then, these static icons should be
// used instead of re-creating icons each time.
public void update() {
// Update the look of the buttons
for (int r=0; r<game.getRows(); r++) {
for (int c=0; c<game.getRows(); c++) {
if (game.isOver())
buttons[r][c].setEnabled(false);
else
buttons[r][c].setEnabled(true);
if (game.getPipe(r,c) == null)
buttons[r][c].setSelected(false);
else {
// Determine the portion of the icon's filename that matches the pipe
String currentPipeCodes = "Start";
if (!game.getPipe(r,c).isValve())
currentPipeCodes = game.getPipe(r,c).toString();
buttons[r][c].setSelectedIcon(new ImageIcon("pipes"+ currentPipeCodes +".GIF"));
buttons[r][c].setSelected(true);
}
}
}
// Update the start/stop button
if (game.isOver())
startStop.setText("Start");
else
startStop.setText("Stop");
// Update the radio buttons
if (game.isOver()) {
twoMinButton.setEnabled(true);
tenMinButton.setEnabled(true);
noLimitButton.setEnabled(true);
}
else {
twoMinButton.setEnabled(false);
tenMinButton.setEnabled(false);
noLimitButton.setEnabled(false);
}
// Update the status label
if (game.isOver()) {
statusLabel.setText("Final Score: " + game.getPlacedPipes());
statusLabel.setVisible(true);
}
else {
if (game.getStyle() == 2) {
statusLabel.setVisible(false);
}
else {
statusLabel.setText("Time Left: ");
statusLabel.setVisible(true);
}
}
// Update the timer bar
if (game.isOver() || (game.getStyle() == 2)) {
timeBar.setVisible(false);
}
else {
timeBar.setValue((int)(game.getTimeRemaining() / (float)game.getTimeLimit() * 100));
timeBar.setVisible(true);
}
// Update the cursor
ImageIcon i;
if (game.isOver()) {
tiles.setCursor(Cursor.getDefaultCursor());
}
else {
if (game.getNextPipe().isValve())
i = new ImageIcon("pipesStart.GIF");
else
i = new ImageIcon("pipes"+ game.getNextPipe().toString() +".GIF");
tiles.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(i.getImage(), new Point(0,0), "pipe"));
}
}
}
I didnt go through all your code but as a hint the function would look like this:
getScore( Pipe p ){
if ( p == null ) return 0;
int res = 1; // size of this pipe
res += getScore(leftPipe);
res += getScore(rightPipe);
...
return res;
}
hope this helps
I think you need to includes the row and col to calculate the pipes that are connected to the main starting pipe
public void connectedPipes(int row, int col){
if(row == null) return 0;
int res = 1; // size of this pipe
res += getScore(leftPipe);
res += getScore(rightPipe);
return res;
}

Implementing ActionListener in the Following Code Inside

I'm having some trouble with my age calculating program on Java. It works fine when I preset the birth year, birth month and birth date values but when I try to have the user input their own birthdate into the text field and then try to work with those values, I just reach a dead-end. I tried asking on Yahoo Answers and the hint I got was "The return value of getActionCommand() is a string while the result is a JLabel. Can you compare them?" I'm not exactly sure what to do with that hint.
Here's what I have and the way I attempted to implement the whole "user input" idea. I'm pretty sure my coding is messy and inefficient, so bear with that please. I'd appreciate any help!
//Date: April 11, 2012
//Description: Calculates the age in terms of days depending on your birthdate.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class AgeCalculator extends Frame implements ActionListener {
JButton equal;
JTextField year, month, day;
JLabel result, first, second, third;
JFrame frame;
JPanel panel;
static int totaldaysalive;
static int daysaliveyr;
static int daysalivem;
static int birthyr;
static int birthm;
static int birthd;
static int currentyr = 2012;
public AgeCalculator(){
gui();
}
public void gui(){
frame = new JFrame ("Age Calculator");
panel = new JPanel(new GridBagLayout());
panel.setBackground(Color.LIGHT_GRAY);
GridBagConstraints x = new GridBagConstraints();
equal = new JButton ("Get Result");
x.insets = new Insets(3,0,3,0);
first = new JLabel("Year ");
x.gridx = 0;
x.gridx = 0;
panel.add(first, x);
year = new JTextField(10);
x.gridx = 5;
x.gridy = 0;
x.gridwidth = 3;
panel.add(year, x);
second = new JLabel ("Month ");
x.gridx = 0;
x.gridy = 1;
panel.add(second,x);
month = new JTextField(10);
x.gridx = 5;
x.gridy = 1;
x.gridwidth = 3;
panel.add(month,x);
third = new JLabel ("Day ");
x.gridx = 0;
x.gridy = 2;
panel.add(third,x);
day = new JTextField(10);
x.gridx = 5;
x.gridy = 2;
x.gridwidth = 3;
panel.add(day,x);
x.gridx = 6;
x.gridy = 3;
panel.add(equal,x);
result = new JLabel ("");
x.gridx = 5;
x.gridy = 5;
panel.add(result,x);
frame.add(panel);
frame.setVisible(true);
frame.setSize(350, 350);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Calc e = new Calc();
equal.addActionListener(e);
year.addActionListener(e);
month.addActionListener(e);
day.addActionListener(e);
}
class Calc implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
birthyr = Integer.parseInt(year.getText());
} catch (NumberFormatException a) {
result.setText("Illegal data for first field.");
result.setForeground(Color.red);
return;
}
try {
birthm = Integer.parseInt(month.getText());
} catch (NumberFormatException a) {
result.setText("Illegal data for second field.");
result.setForeground(Color.red);
return;
}
try {
birthd = Integer.parseInt(day.getText());
} catch (NumberFormatException a) {
result.setText("Illegal data for third field.");
result.setForeground(Color.red);
return;
}
if (e.getActionCommand().equals (equal)){
totaldaysalive = ageCalcYr() + ageCalcM() + birthd;
result.setText(Integer.toString(totaldaysalive));
}
}
public int ageCalcYr(){
for (int i = birthyr; i <= currentyr; i++){
if ((i % 4 == 0) && (!(i % 100 == 0) || (i % 400 == 0))){
daysaliveyr = daysaliveyr + 366;
}
else {
daysaliveyr = daysaliveyr + 365;
}
}
return daysaliveyr;
}
public int ageCalcM(){
if (birthm == 1){
daysalivem = daysalivem + 0;
}
else if (birthm == 2){
daysalivem = daysalivem + 30;
}
else if (birthm == 3){
daysalivem = daysalivem + 60;
}
else if (birthm == 4){
daysalivem = daysalivem + 90;
}
else if (birthm == 5){
daysalivem = daysalivem + 120;
}
else if (birthm == 6){
daysalivem = daysalivem + 150;
}
else if (birthm == 7){
daysalivem = daysalivem + 180;
}
else if (birthm == 8){
daysalivem = daysalivem + 210;
}
else if (birthm == 9){
daysalivem = daysalivem + 240;
}
else if (birthm == 10){
daysalivem = daysalivem + 270;
}
else if (birthm == 11){
daysalivem = daysalivem + 300;
}
else if (birthm == 12){
daysalivem = daysalivem + 330;
}
return daysalivem;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
AgeCalculator gui = new AgeCalculator();
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
Fast healing:
if (e.getActionCommand ().equals ("Get Result")) { // equal)) {
totaldaysalive = ageCalcYr () + ageCalcM () + birthd;
result.setText (Integer.toString (totaldaysalive));
}
If you have some time, I can post you 20 improvements.
You extend Frame,
impl. ActionListener, but meanwhile AgeCalculator has a JFrame (which is better in a SwingContext than Frame, which is AWT) and has a seperate Actionlistener which is used.
Remove the declaration, and the the overriding method in the end.
public class AgeCalculator // extends Frame implements ActionListener
There follows a block of visual components and other attributes, the later ones are static - which prohibits using of 2 AgeCalculators on the same JVM. That's surely not a restriction by intent.
Don't make something static to shut up the compiler.
Make everything private, if you aren't sure you want to expose it.
Avoid Attributes where possible.
When will you ever retouch a Label?
JButton equal;
JTextField year, month, day;
JLabel result, ...
...
static int birthd;
static int currentyr = 2012;
Use simplified addition where appropriate:
daysaliveyr += 366;
To calc the days for month, pass the birthyr and the birthm as parameter:
int totaldaysalive = ageCalcYr (birthyr) + ageCalcM (birthm) + birthd;
result.setText (Integer.toString (totaldaysalive));
The livetime of the variable totaldaysalive can be reduced to 2 lines - a very small scope to search for an error, if there is any.
public int ageCalcM (int birthm) {
int daysalivem = 0;
if (birthm == 2) {
daysalivem += 30;
}
else if (birthm == 3) {
daysalivem += 60;
}
In the current state, ageCalcM is a provisorium. Else you could just say daysalivem = (birthm - 1) * 30;
Shorter code:
public int ageCalcM (int birthm) {
if (birthm == 2) {
return 30;
}
else if (birthm == 3) {
return 60;
}
However, such mass manipulation in stupid repetition can be solved with an simple array:
public int ageCalcM (int birthm) {
int[] mdays = {0, 30, 60, 90, ...};
return mdays [birthm];
}
In the main-Method you create an instance 'gui', which is never used. This is all you need:
public static void main (String [] args) {
new AgeCalculator ();
}
Gui, btw. is a bad name, if you already have a method of said name.
Since that method is never used, just move the whole thing into the ctor.
year/month/date don't need the ActionListener.
Other layouts are much better suited.
We need another calender reform to make your program work.
Input should not only be checked to be int, but valid month etc.
The actual date isn't used.
What is left?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class AgeCalculator
{
JTextField year, month, day;
JLabel result;
public AgeCalculator () {
JFrame frame = new JFrame ("Age Calculator");
JPanel panel = new JPanel (new GridBagLayout ());
panel.setBackground (Color.LIGHT_GRAY);
GridBagConstraints x = new GridBagConstraints ();
JButton equal = new JButton ("Get Result");
x.insets = new Insets (3, 0, 3, 0);
JLabel first = new JLabel ("Year ");
// two times gridx = 0 here?
x.gridx = 0;
x.gridx = 0;
panel.add (first, x);
year = new JTextField (10);
x.gridx = 5;
x.gridy = 0;
x.gridwidth = 3;
panel.add (year, x);
JLabel second = new JLabel ("Month ");
x.gridx = 0;
x.gridy = 1;
panel.add (second, x);
month = new JTextField (10);
x.gridx = 5;
x.gridy = 1;
x.gridwidth = 3;
panel.add (month, x);
JLabel third = new JLabel ("Day ");
x.gridx = 0;
x.gridy = 2;
panel.add (third, x);
day = new JTextField (10);
x.gridx = 5;
x.gridy = 2;
x.gridwidth = 3;
panel.add (day, x);
x.gridx = 6;
x.gridy = 3;
panel.add (equal, x);
result = new JLabel ("");
x.gridx = 5;
x.gridy = 5;
panel.add (result, x);
frame.add (panel);
frame.setVisible (true);
frame.setSize (350, 350);
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
Calc e = new Calc ();
equal.addActionListener (e);
}
class Calc implements ActionListener {
public void actionPerformed (ActionEvent e) {
int birthyr;
int birthm;
int birthd;
try {
birthyr = Integer.parseInt (year.getText ());
} catch (NumberFormatException a) {
result.setText ("Illegal data for first field.");
result.setForeground (Color.red);
return;
}
try {
birthm = Integer.parseInt (month.getText ());
} catch (NumberFormatException a) {
result.setText ("Illegal data for second field.");
result.setForeground (Color.red);
return;
}
try {
birthd = Integer.parseInt (day.getText ());
} catch (NumberFormatException a) {
result.setText ("Illegal data for third field.");
result.setForeground (Color.red);
return;
}
if (e.getActionCommand ().equals ("Get Result")) { // equal)) {
int totaldaysalive = ageCalcYr (birthyr) + ageCalcM (birthm) + birthd;
result.setText (Integer.toString (totaldaysalive));
}
}
public int ageCalcYr (int birthyr) {
int currentyr = 2012;
int daysaliveyr = 0;
for (int i = birthyr; i <= currentyr; i++) {
if ((i % 4 == 0) && (! (i % 100 == 0) || (i % 400 == 0))) {
daysaliveyr += 366;
}
else {
daysaliveyr += 365;
}
}
return daysaliveyr;
}
public int ageCalcM (int birthm) {
int[] mdays = {0, 30, 60, 90, 120};
return mdays [birthm];
}
}
public static void main (String [] args) {
new AgeCalculator ();
}
}
Since you're using a button to kick off the calculation, only register an action listener on that button. Inside the action performed method read, parse and calculate the age in days.
I think you want to do equal.addMouseListener(e). Of course you'll have to change Calc to implement MouseListener. You'll probably only have to actually write the mouseClicked(MouseEvent) method. All of the others are for more specific things than what you're after.
That will respond to a click event on your button. I don't think you want any other listeners. If so, they should be KeyListeners or something other than ActionListeners.
On a side note, It's hard for me to see because your indentation is off, but I can't really tell why your int fields are static. I think that's probably unnecessary.

Categories