I'm doing the Guessing Game for Java homework and I am having a logic problem with the nested if else. I am trying to determine two things: is the number to high/low, and if the user is getting hotter/colder. I have a variables intGuess and intOldGuess. I am trying to compare the two for the hotter/colder but I either end up with intOldGuess being 0, or the same as intGuess when it comes time for comparison. Neither are correct of course. Here is what I have so far:
Here is the section I think is giving me trouble:
public void actionPerformed(ActionEvent e)
{
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
try
{
intGuess = Integer.parseInt(txaUserGuess.getText().trim());
if (intGuess < intRandomNum)
{
lblHighLow.setText("Too Low");
if (intGuess > intOldGuess)
{
lblHotCold.setText("Getting Colder");
System.out.println(intOldGuess);
System.out.println(intGuess);
}
Here is the entire code if you need it:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class GuessNumber extends JFrame
{
private JTextField txaUserGuess;
private JLabel lblStart, lblPrompt, lblHighLow, lblHotCold;
private JButton btnGuess, btnQuit, btnAgain;
private int intRandomNum;
Container c = getContentPane();
public static void main(String args[])
{
GuessNumber app = new GuessNumber();
}
public GuessNumber()
{
super("Guessing Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Creates components
btnGuess = new JButton("Guess");
btnQuit = new JButton("Quit");
btnAgain = new JButton("Play Again?");
lblStart = new JLabel("I have a number between 1 and 1000.");
lblPrompt = new JLabel(
"Can you guess my number? Please enter your guess:");
lblHighLow = new JLabel("");
lblHotCold = new JLabel("");
txaUserGuess = new JTextField(5);
setLayout(new FlowLayout());
c.add(lblStart);
c.add(lblPrompt);
c.add(txaUserGuess);
c.add(btnGuess);
c.add(btnQuit);
c.add(btnAgain);
c.add(lblHighLow);
c.add(lblHotCold);
setSize(350, 200);
setVisible(true);
btnAgain.setVisible(false);
RandomNumber();
FirstGuessButtonHandler ghandler = new FirstGuessButtonHandler();
btnGuess.addActionListener(ghandler);
QuitButtonHandler qhandler = new QuitButtonHandler();
btnQuit.addActionListener(qhandler);
AgainButtonHandler ahandler = new AgainButtonHandler();
btnAgain.addActionListener(ahandler);
}
private void RandomNumber()
{
intRandomNum = new Random().nextInt(1000) + 1;
System.out.println(intRandomNum);
}
class QuitButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
class AgainButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
}
}
class FirstGuessButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
try
{
intGuess = Integer.parseInt(txaUserGuess.getText().trim());
if (intGuess < intRandomNum)
{
lblHighLow.setText("Too Low");
if (intGuess > intOldGuess)
{
lblHotCold.setText("Getting Colder");
System.out.println(intOldGuess);
System.out.println(intGuess);
} else if (intGuess < intOldGuess)
{
lblHotCold.setText("Getting Hotter");
}
} else if (intGuess > intRandomNum)
{
lblHighLow.setText("Too High");
} else
{
c.setBackground(Color.GREEN);
lblHighLow.setText("\n\tCorrect!");
txaUserGuess.setEditable(false);
btnAgain.setVisible(true);
btnGuess.setEnabled(false);
}
} catch (NumberFormatException e1)
{
lblHighLow.setText("\n\tEnter a VALID number!");
}
}
}
}
int intGuess = 0, intOldGuess;
is currently contained in the method actionPerformed() these need to be declared as fields (outside methods but in the class body).
Also you may consider writing those as
int intGuess = 0;
int intOldGuess;
for clarity sake (it looks cleaner and will make your code more easily readable)
intOldGuess is local variable to the method. So every time the method gets called, it gets initialized to 0 (default value).
To preserve the value, you might want to create the variable as class field
class FirstGuessButtonHandler implements ActionListener
{
int intOldGuess;
public void actionPerformed(ActionEvent e)
{
int intGuess = 0;
But remember, in above case, you need to maintain the same instance of FirstGuessButtonHandler class, since the class fields are maintained per instance of the class.
Other approach could be to create intOldGuess as static class field too
In this place here:
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
You are defining intOldGuess, but in second line you assign value 0 to it. You probably should keep this variable in class scope and don't assign 0 to it.
Use of local variables should be avoided, if you want to use them without re-initialization.
To retain the value of variables make those variables Reference variable.
You can do this-
class ClassName{
int oldguess;
public void yourMethod(){
int newGuess = 0;
if (intGuess < intRandomNum)
{
lblHighLow.setText("Too Low");
if (intGuess > intOldGuess)
{
lblHotCold.setText("Getting Colder");
System.out.println(intOldGuess);
System.out.println(intGuess);
}
The problem is, that you have the second if nested in the first. The second only ever gets checked, if the first is valid. The second condition can therefore never be true. (It only checks if intGuess is greater than inOldGuess, if intGuess is less than intOldGuess, which can never be.
You need to take the second if out of the first.
Also, you seem to want to store data in intOldGuess, but you declared it as a local variable. You need to set it is a field if you want it to store data between method calls.
The problem lies with how you are keeping state
int intGuess = 0, intOldGuess;
intOldGuess = intGuess;
Here you are declaring local variables, which are recreated each time your function is called.
Related
I keep getting an error that I cannot seem to resolve. It appears on the "showSlide(elementNum);" line.
public class SlideGUI extends JPanel{
fillSlide();
showSlide();
}
private class EventListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if (e.getSource() == nextButton){
elementNum++;
if(elementNum == slides.length){
elementNum = 0; //make index number 0 (the first slide)
}
}
showSlide(elementNum);
}
}
public void fillSlide(){
slides[0] = new Slide("Halong Bay.jpg",new Color(49,57,74),"Halong Bay From Lookout Point");
slides[1] = new Slide("Minion.jpg",new Color(3,28,75),"Minion Balloon");
slides[2] = new Slide("Ice Cream.jpg",new Color(13,54,72),"Chocolate Ice Cream with Yoghurt and Coffee Jelly");
}
public void showSlide(){
imageLabel.setIcon(slides[elementNum].getImage());
captionLabel.setText(slides[elementNum].getCaption());
lowerPanel.setBackground(slides[elementNum].getColour());
upperPanel.setBackground(slides[elementNum].getColour());
moveOnPanel.setBackground(slides[elementNum].getColour());
moveBackPanel.setBackground(slides[elementNum].getColour());
picturePanel.setBackground(slides[elementNum].getColour());
}
}
You call showSlide() with a parameter, but you declared it to have no parameters.
I've been trying to create a scenario where when a button is clicked, a new JFrame is generated with x amount of JLabels and JButtons (x is dependent on user inputs in another part of the program). However, whenever I try to do this, I get the "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException" error
I cannot figure out what the error is. My code's syntax is fine and compiles with no errors. Code that is bolded (not really but has ...) are lines that the error points to. There are also other lines that are pointed to but those are the lines generated by java.
**public class MainUI extends javax.swing.JFrame {**
public MainUI() {
initComponents();
}
private void ViewList(java.awt.event.ActionEvent evt) {
this.dispose();
ListFrame list = new ListFrame();
ArrayList<Type1> miniList1 = DataStorage.getMiniList1();
ArrayList<Type2> miniList2 = DataStorage.getMiniList2();
int counter = 0;
java.awt.Label[] rLabels;
rLabels = new java.awt.Label[miniList1.size() + miniList2.size()];
javax.swing.JButton[] rButtons;
rButtons = new javax.swing.JButton[rLabels.length];
for (int g=0;g<rLabels.length;g++)
{
**rLabels[g].setPreferredSize(new Dimension(150,35));**
rLabels[g].setAlignment(Label.CENTER);
rLabels[g].setLocation(30,30*g);
}
for (int h=0;h<rButtons.length;h++)
{
rButtons[h].setText("Show");
}
for (int i=counter;i<miniList1.size();i++)
{
String name1 = miniList1.get(i).getName();
rLabels[i].setText(name1);
Type1 item1 = miniList1.get(i);
rButtons[i].addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
ItemScreen iScreen = new ItemScreen();
String item1Display = DataStorage.type1ToString(item1);
iScreen.iTitleLabel.setText(name1);
iScreen.iTextLabel.setText(item1Display);
iScreen.setVisible(true);
}
});
counter++;
}
for (int j=counter;j<miniList2.size() + counter;j++)
{
String name2 = miniList2.get(j-counter).getName();
rLabels[j].setText(name2);
Type2 item2 = miniList2.get(j);
rButtons[i].addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
ItemScreen iScreen = new ItemScreen();
String item2Display = DataStorage.type2ToString(item2);
iScreen.iTitleLabel.setText(name2);
iScreen.iTextLabel.setText(item2Display);
iScreen.setVisible(true);
}
});
}
for (int m=0;m<rLabels.length;m++)
{
list.add(rLabels[m]);
}
for (int n=0;n<rLabels.length;n++)
{
list.add(rButtons[n]);
}
list.setVisible(true);
}
ListFrame and ItemScreen are JFrames in my project and DataStorage is another class in my project. Type1 and Type2 are objects. I'm using NetBeans.
When you create an array, it creates n number of empty/uninitialised slots
So when you do something like...
rLabels = new java.awt.Label[miniList1.size() + miniList2.size()];
All you have is an array of null elements...
Before you can modify an object at a given position, you need to initialise the value at the given slot...
for (int g=0;g<rLabels.length;g++)
{
rLabels[g] = new JLabel();
//...
}
This goes for all arrays. Take a look at the Arrays tutorial for more details
we are working on a project trying to make a message in a JOptionPane show up when a button is pressed and certain conditions are met. However whenever the code is activated and a button is pressed, the JOptionPane shows up with no message. Here is the code that creates the GUI
package BlackJack;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class BlckJckUI {
public static void main(String[] args) {
JFrame GUI = new JFrame("Blackjack Advisor");
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setSize(1000,900);
GUI.setVisible(true);
JButton two = new JButton(Two);
two.setSize(300, 100);
two.setLocation(100, 200);
two.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
Arrays array = new Arrays();
Math math = new Math();
math.cardvalue = 2;
array.clicktracker++;
JOptionPane.showMessageDialog(null,array.result);
}
});
GUI.add(two);
This is the code that works out the logic.
package BlackJack;
public class Math {
public int cardvalue;
public Math()
{
Arrays array = new Arrays();
if (array.clicktracker == 1)
{
array.dealer = cardvalue;
array.result = "Please select the first card you have :)";
}
else if (array.clicktracker == 2)
{
array.playerhand.add(cardvalue);
array.result = "Please select the second card you have :)";
}
else if (array.clicktracker >= 3)
{
array.playerhand.add(cardvalue);
if (array.playerhandtotal <= 8)
{
// array.result = result statement
array.result = "You should just hit until you're safe. If the dealer 6 or below,\n"
+ " the chances are that he'll bust and if not, remain low above 17.\n"
+ " As long as you can pull a 17 or higher, you should be safe. Pick \n"
+ "another card or reset.";
This is the code that creates the Array and variables associated with it.
package BlackJack;
import java.util.ArrayList;
public class Arrays{
public String result = null;
ArrayList<Integer> playerhand = new ArrayList<Integer>();
public int dealer = 0;
public int clicktracker = 0;
public int playerhandtotal = 0;
{
for (int element: playerhand)
{
playerhandtotal = element + playerhandtotal;
}
System.out.println(result);
System.out.println(dealer);
System.out.println(clicktracker);
}
}
In your Math constructor, you are changing the result of a different type of array.result than the one you are trying to display.
I would consider passing the Arrays instance into the Math constructor so that you can modify the result from there. Be sure to not reassign the instance though.
public void actionPerformed(ActionEvent e)
{
Arrays array = new Arrays();
Math math = new Math(array);
math.cardvalue = 2;
array.clicktracker++;
JOptionPane.showMessageDialog(null,array.result);
}
...
public Math(Arrays array)
{
if (array.clicktracker == 1)
{
// And so on ...
The problem is that you are creating two separate instances of your Arrays class. Once in the actionPerformed method and also within the constructor of your Math class.
This code you currently have:
Arrays array = new Arrays();
Math math = new Math();
math.cardvalue = 2;
array.clicktracker++;
JOptionPane.showMessageDialog(null,array.result);
will display the result of the Arrays object you created in the actionPerformed method - which is null as the result of this object is initialised to null and never set.
This has been mentioned in other answers and comments and will solve it from producing null but this approach will now always yield the same result as you are still always creating a new instance of your Arrays class in your actionPerformed method.
A better approach would be to separate the logic of the result from the constructor of your Math class into another method and create this instance of your Math class outside of the actionPerformed method. Then within your actionPerformed method call your method which will do the logic for your result.
In UI:
Math math = new Math();
two.addActionListener(new ActionListener ()
{
public void actionPerformed(ActionEvent e)
{
math.cardvalue = 2;
math.array.clicktracker++;
math.calcResult();
JOptionPane.showMessageDialog(null,math.array.result);
}
});
In Math:
public class Math {
public int cardvalue;
public Arrays array;
public Math()
{
array = new Arrays();
}
public void calcResult(){
if (array.clicktracker == 1)
{
//...rest of your logic
}
}
For practice, I am trying to create a fully functional calculator. I copied the ActionListener class of my code below. I feel like my this method for getting the users input, storing it as an integer/double does not work well as it is too basic and does not work in all cases. I was wondering if anyone can help me figure out a way to structure my code, get user input for two numbers and a symbol, and basically create a fully function GUI calculator. My problem is getting user input from my JButton, storing as a number that in way like a calculator does, (press 1 twice == 11) and using it for later calculation.
I appreciate any advice in this regard.
private class TheHandler implements ActionListener{
public void actionPerformed(ActionEvent event){
while(equals!=event.getSource())
if(one==event.getSource()){
result.setText("1");
num1=1;
}
else if(two==event.getSource()){
result.setText("2");
}
else if(three==event.getSource()){
result.setText("3");
}
else if(four==event.getSource()){
result.setText("4");
}
else if(five==event.getSource()){
result.setText("5");
}
else if(six==event.getSource()){
result.setText("6");
}
else if(seven==event.getSource()){
result.setText("7");
}
else if(eight==event.getSource()){
result.setText("8");
}
else if(nine==event.getSource()){
result.setText("9");
}
else if(zero==event.getSource()){
result.setText("0");
}
}
}
You should remove the while at all.
I would suggest to use numeric vars like
long num = 0;
int digit;
Each event should just set digit
...
else if(nine==event.getSource()){
digit = 9;
} else if(zero==event.getSource()){
digit = 0;
}
...
num = num * 10 + digit;
...
result.setText(Long.toString(num));
How about a class member variable to store the current state of the display and use that for set text?
private class TheHandler implements ActionListener{
String display = "";
public void actionPerformed(ActionEvent event){
while(equals!=event.getSource()){
if(one==event.getSource()){
display=display+"1";
}
.....
}
result.setText(display);
}
}
You could more cleanly associate each button with a number like so:
private class TheHandler implements ActionListener{
private Map<Object, String> numbers = new HashMap<Object, String>();
{
numbers.put(zero, "0");
numbers.put(one, "1");
...
}
public void actionPerformed(ActionEvent event){
Object source = event.getSource();
while(equals != source){
String number = numbers.get(source);
if (number != null){
result.setText(number);
}
}
}
}
How can I access all the member field of the class which contains the function initTimer() from within the AbstractActionClass?
Thanks
private void initTimer()
{
Action updateClockAction = new AbstractAction() {
public void actionPerformed(ActionEvent e){
JLabel secLabel = m_GameApplet.GetJpanelStartNetGame().GetJlabelSeconds();
secLabel.setFont(new java.awt.Font("Lucida Handwriting", 1, 36));
secLabel.setForeground(Color.red);
secLabel.setText(Integer.toString(m_TimerSeconds));
if(m_TimerSeconds >0)
{
m_TimerSeconds--;
}
else if (m_TimerSeconds == 0)
{
m_Timer.stop();
m_GameApplet.GetJpanelStartNetGame().GetJlabelSeconds().setText("0");
m_GameApplet.GetJpanelStartNetGame().GetJbuttonFinish().setVisible(false);
//Checking whether time ended for both players and no solution was recieved
if(!m_WasGameDecisived)
{
System.out.println("Tie - No one had a solution in the given time");
//askUserForAnotherRoundLeaveTableOrExitProgram();//////////////////////////////////////////////To implement
}
}
}
};
m_Timer = new Timer(1000, updateClockAction);
}
Try,
ClassName.this.foo
where foo is a class member. For more information, see JLS ยง15.8.4 Qualified this.
Assuming your outer class is called OuterClass, then OuterClass.this.whatever