-1

I have question about my homework the coin program.

We need write a small GUI program which could flip the coin and can show the current money.

I wrote almost everything, but I still have some problem to update two JLabel status and it seems like the two bet buttons and reset the button are work fine, after I use System.out.println to testing, but the label just not update as the same time when we click the button.

Here is my codes, which contain four class: coin.java, player.java, coinpanel.java and coinPanelMain.java.

  1. player.java:

    public class Player {

    /**
     * @param ownMoney is currently the player own money
     * @param coin is new Coin object;
     */
    private int currMoney;
    private Coin coin; 
    
    /**
     * no-args parameter
     * default constructor 
     */
    public Player(){
        currMoney = 10;
        coin = new Coin();
    }
    /**
     * a bet method that takes in a bet and the side of coin
     * it will filp the coin and change the player's money 
     * depend on whether the player won or lost the bet 
     */
    public void bet(){
        coin.flip();
        System.out.println("filp over");
        if(coin.getFace().equals ("Heads")){
            currMoney ++;
        }
        else if(coin.getFace().equals("Tails")){
            currMoney --;
        }
        System.out.println("filp over2");
    }
    /**
     * a getter for getting current money
     * @return currMoney 
     */
    public int getCurrMon(){
        System.out.println("money is" + currMoney);
        return currMoney;
    }
    /**
     * a reset method make current money return to 10;
     * @return currMoney to 10
     */
    public void reset(){
    
        currMoney = 10;
    }
    

    }

  2. coinPanel.java

    import javax.swing.; import java.awt.event.; import java.awt.; /*

    • the coin panel class displays the result of the coin game.
    • it contain three button, current money and current flip
    • once user click reset button, the current money will return to 10. * * */

public class CoinPanel extends JPanel {

private Player player = new Player();
private Coin coin = new Coin();
private JLabel label3 = new JLabel("Enter a bet");
private JTextField text;
private  int value = 0;

public  int getVal(){
    return value;
}
public CoinPanel(){

    JLabel label= new JLabel("Current Money:"+player.getCurrMon());
    JLabel label2 = new JLabel("Current Flip:" + coin.getFace());

    JLabel label4 = new JLabel("");

    text = new JTextField(30);
    //JTextField text = new JTextField(30);
    //String betNum = text.getText();
    //int betNumber = Integer.parseInt(betNum);


    JButton headsBt = new JButton("Bet Heads");
    JButton tailsBt = new JButton("Bet Tails");
    JButton reset = new JButton("Reset");


    setLayout(new GridLayout(5,1,10,10));
    add(label);
    add(label2);

    add(headsBt);
    add(tailsBt);
    add(text);

    add(reset);
    add(label3);




    headsBt.addActionListener(new BetButtonListener());
    tailsBt.addActionListener(new BetButtonListener());
    reset.addActionListener(new RESETButtonListener());



}

public class RESETButtonListener implements ActionListener{
    public void actionPerformed(ActionEvent e){
        player.reset();
        System.out.println("reset button");
    }
}

public class BetButtonListener implements ActionListener{
    public void actionPerformed(ActionEvent e){
        //value = Integer.parseInt(text.getText());
        player.bet();

        int value = Integer.parseInt(text.getText());

    //catch (NumberFormatException e){
        if(value > player.getCurrMon()){
            label3.setText("You are out of money");
            repaint();
        }
            }

}

}

thank you very much. I am really really appreciate your help!

After re-edit code followed by instruction here is some error display as following, the application could not run. And I don't know why. the error is:

"

money is10
face isTails
Exception in thread "main" java.lang.NullPointerException
    at java.awt.Container.addImpl(Unknown Source)
    at java.awt.Container.add(Unknown Source)
    at CoinPanel.<init>(CoinPanel.java:48)
    at CoinPanelMain.main(CoinPanelMain.java:17)

" above question was solved. I forget initialized the label3 in the class..

Sorry for bring you too many questions... whatever the user input in text field (i mean the number), the current money label always increase 2 or decrease 2. I think it supposed change as the user input?

JavaLeave
  • 225
  • 1
  • 5
  • 14
  • 4
    If you would like help with questions like this you should read stackoverflow's FAQ. That would point out that you are supposed to only post RELVANT code bits, not dump your entire program with a vague problem description. – thatidiotguy Oct 17 '12 at 18:33
  • did you try a repaint() method? – Roman C Oct 17 '12 at 18:37
  • 1
    Look at string comparison. And narrow down the problem. – Lews Therin Oct 17 '12 at 18:37
  • hi everybody, i edit my question, only left some relevant code above. My questions are : 1. i think bet method in player class have some problem, which is could not update the current money add or minus user input bet. 2. the coinPanel class two labels(current money & current face ) could not update after i click the two button. – JavaLeave Oct 17 '12 at 18:55

2 Answers2

4

Swing is pretty clever when it comes to it's repaint, but some times, it can be a little too clever.

My expectation is that after calling something like Label#setText a repaint request would be raised and the label would be updated, but this doesn't always happen.

You may need to prompt Swing for a repaint...

if(value > player.getCurrMon()) {
    label3.setText("You are out of money");
    repaint();
}

It's unlikely in your case, but you may need to proceed the repaint request with a call to invalidate() to encourage the container hierarchy to update it's layout.

Also...

int value = Integer.parseInt(text.getText());

Should be wrapped in a NumberFormatException to make sure that the user is actually entering a number. Failing to do so will result in you program not updating as you expect it to

Extended Answer

So, in your rest method, you need to update all the various ui elements...

public void actionPerformed(ActionEvent e){
    player.reset();
    System.out.println("reset button");

    label3.setText(""); // assuming no new messages..
    label.setText("Current Money:"+player.getCurrMon());
    text.setEnabled(true);

    invalidate();
    repaint();

}

In you bet button you have a number of issues...

There's no connection between what the user entered and what is being deducted, there's also no check to see if the player can cover the bet...

    try {
        int value = Integer.parseInt(text.getText());

        if (value > player.getCurrMon()) {
            label3.setText("You don't have enough money to cover the bet");
        } else {
            player.bet();

            label.setText("Current Money:"+player.getCurrMon());

            if(player.getCurrMon() == 0){
                label3.setText("You are out of money");
                text.setEnabled(false);
            } else if (player.getCurrMon() < 0) {
                label3.setText("We'll be sending the boys around shortly");
                text.setEnabled(false);
            }
       }
    } catch (NumberFormatException exp) {
        label3.setText(text.getText() + " is an invalid bet");
    }
    invalidate();
    repaint();

UPDATED

Firstly...label needs to be defined as an instance field, like label3 in your CoinPanel

private JLabel label3 = new JLabel("Enter a bet");
private JLabel label;

Then in the constructor, you only need to initialize it...

public CoinPanel(){

    label= new JLabel("Current Money:"+player.getCurrMon());

UPDATED

Basically, we need to check which button was pressed and change the "face" bet accordingly

public class BetButtonListener implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        try {
            int value = Integer.parseInt(text.getText());

            if (value > player.getCurrMon()) {
                label3.setText("You don't have enough money to cover the bet");
            } else {
                String face = "Heads";
                if (e.getSource().equals(tailsBt)) {
                    face = "Tails"
                }
                player.bet(face, value);

                label.setText("Current Money:" + player.getCurrMon());

                if (player.getCurrMon() == 0) {
                    label3.setText("You are out of money");
                    text.setEnabled(false);
                } else if (player.getCurrMon() < 0) {
                    label3.setText("We'll be sending the boys around shortly");
                    text.setEnabled(false);
                }
            }
        } catch (NumberFormatException exp) {
            label3.setText(text.getText() + " is an invalid bet");
        }
        invalidate();
        repaint();
    }

}

Note, I may have switched the parameters to the bet method. The order is only important to how you've declared the method, so you might need to switch my parameters

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • hi. thank you! this is what i wanna ask, too. this method i am not sure i am correct or not. since i don't know where i should write update money method. in player.java or in betlistener class. – JavaLeave Oct 17 '12 at 19:19
  • Update the UI only from the UI code. The player is a model, is has nothing to do with the UI other then to feed information to it. If I was writing it, I would have the player fire some kind of change event when it updates (probably a property changed event) which the UI could listen to. This decouples the UI from the player and reduces the reliance they have on each other, but that might be overkill for the assignment – MadProgrammer Oct 17 '12 at 19:22
  • Focus on areas of responsibility. Money belongs to the player, the UI is just information. If the player leaves, they take there money with them, if a new player arrives, they bring there money with them. Obviously, there's probably going to be a "pool" into which beats go into, but you've not listed that ;) – MadProgrammer Oct 17 '12 at 19:24
  • the bet method description is takes in a bet and the side of the coin that the player is betting on. It should flip the coin and change the player's money depending on whether the player won or lost the bet. Also seem like the reset button could not update the label, too. – JavaLeave Oct 17 '12 at 19:26
  • From the sounds of, the `bet` method should be separate from the player (and the UI IMHO), this allows you to implement different games that the player can play. At the moment, the reset method doesn't do anything to update the UI (it makes no calls to any UI components) – MadProgrammer Oct 17 '12 at 19:40
  • How can i deal with reset method? Is method problem or the ui problem? – JavaLeave Oct 17 '12 at 20:12
  • Neither, you've not coded any changes – MadProgrammer Oct 17 '12 at 20:17
  • i attached the full code here, would you mind help me to solve the update label problem? both current money and current face could not update ...so struggle ! – JavaLeave Oct 17 '12 at 20:59
  • can you help me for my code? It take me a long time, still didn't solve the problem. Thank you! – JavaLeave Oct 17 '12 at 22:06
  • sorry..i forget add the label3 in the coinpanel class.it should be run fine now! thanks a lot!! – JavaLeave Oct 17 '12 at 22:37
  • also, i wonder is there any possible that when user hits enter on the text field, the coin is flipped using the user's bet? – JavaLeave Oct 17 '12 at 22:41
  • I've added a bit extra, but what's a line 48 of `CoinPanel`? – MadProgrammer Oct 17 '12 at 22:44
  • i figured out the line 48, but i found another problem, whatever user input the number is (4,5 or 10) the current money will only add or minus 2. Should i change in player class bet method or in betbuttonlistener class ? – JavaLeave Oct 17 '12 at 22:48
  • yeah, I did mention that. You need to be able to pass the bet amount to the player...`player.bet(value)`, then in the `bet` method you would either subtract or add the value based on the win condition (instead of `currMoney++` or `currMoney--`) – MadProgrammer Oct 18 '12 at 00:03
  • i am still confused about this part. i take in a int input in my bet method. so my bet method looks like "public void bet(int input)", but what should i deal with betbuttonlistener – JavaLeave Oct 18 '12 at 01:54
  • In your `BetButtonListener` method, you should pass the `value` you got from the `text` field, `player.bet(value)` – MadProgrammer Oct 18 '12 at 01:58
  • it's probably better for passing two variable? one for face status another is money status? player.bet(value,face) like this? – JavaLeave Oct 18 '12 at 02:17
  • You need to pass in the amount of the bet and the coin face they bet on, so yes – MadProgrammer Oct 18 '12 at 02:27
  • since i am using one button listener to recall two button (bet heads & bet tails), and i just write a betbuttonlistener constructor. but in my actionperformed method, there have a if else method to determined which button that user click, i don't know how to write that if method... – JavaLeave Oct 18 '12 at 02:35
  • Good spot, there are two. You could compare the event source (`e.getSource()`) with each instance of the button ... `if (e.getSource().equals(headsBt)) {...}` or you could set the buttons `actionCommand`, `headsBt.setAction("BetHeads")` and compare that in the event handler, `if (e.getActionCommand().equals("BetHeads")` – MadProgrammer Oct 18 '12 at 02:45
  • i'm using the default constructor to identify two buttons. but i don't know what to write after if statement i mean what is "if(...){...}", the point is what i need to write in "{...}" – JavaLeave Oct 18 '12 at 02:55
2
  • This here is a problem:

    if(coin.getFace() == "Heads"){
        currMoney ++;
     }
    else if(coin.getFace() == "Tails"){
        currMoney --;
    }
    

do not compare String using ==. Use equals(..) method for String comparison:

if(coin.getFace().equals("Heads")){
    currMoney ++;
}
else if(coin.getFace().equals("Tails")){
     currMoney --;
}

I would also suggest using Switch block when comparing multiple Strings thus also reducing the risk of comparing the String using == (Java 7 only though thank you Mad):

switch(coin.getFace()) {

    case "Heads": 
          currMoney ++;
      break;
    case "Tails":  
           currMoney --;
      break;
}
  • You add an ActionListener to your JTextField this is definitely not good (remove this line):

    text.addActionListener(new BetButtonListener());
    
  • Also I cant see it not updating as long as the JPanel instance is created on the Event-Dispatch-Thread, but as @Mad said (+1 to him and for the try catch) calling invalidate() will make sure it does.

UPDATE:

as per comment:

try catch block will surround a method call that could possible throw an Exception:

int i=...;
try {
//call a method that can throw NumberFormatExecption
i=...;
}catch(NumberFormatException nfe) {
System.err.println(nfe.getMessage());
}

Read these for more on TRY and CATCH blocks

David Kroukamp
  • 36,155
  • 13
  • 81
  • 138