HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

"Guess my number" game in Java Swing

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
numberjavaswinggameguess

Problem

Also posted at rgcsm.info/blog

```
//Number Guessing Game in Java Swing
//Also posted at

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

class Guess extends JFrame
{
JTextField t1, t2, t3, t4;
JLabel j4;
ButtonListener bl1;
ButtonListener2 bl2;
ButtonListener3 bl3;

//setting random number in rand variable
int rand=(int) (Math.random()*100);
int count=0;

public Guess()
{
//Get the container
Container c = getContentPane();

//Set absolute layout
c.setLayout(null);

//Set Background Color
c.setBackground(Color.WHITE);

//Creating image
JLabel lblpic = new JLabel("");
lblpic.setIcon(new ImageIcon("images.png"));
lblpic.setBounds(0,0,500,350);

//Creating label Guess my number text
JLabel j=new JLabel("Guess my number game");
j.setForeground(Color.RED);
j.setFont(new Font("tunga",Font.BOLD,24));
j.setSize(270,20);
j.setLocation(300,35);

//Creating label Enter a number.....
JLabel j1=new JLabel("Enter a number b/w 1-100");
j1.setFont(new Font("tunga",Font.PLAIN,17));
j1.setSize(270,20);
j1.setLocation(300,60);

//Creating TextField for input guess
t1=new JTextField(10);
t1.setSize(50,30);
t1.setLocation(350,80);

//Creating Label for Display message
j4=new JLabel("Try and guess my number");
j4.setFont(new Font("tunga",Font.PLAIN,17));
j4.setSize(270,20);
j4.setLocation(290,130);

//Creating Text field for best score
t2=new JTextField(10);
t2.setSize(40,20);
t2.setLocation(10,10);

//Creating Label for best score
JLabel j5=new JLabel("Best Score");
j5.setFont(new Font("tunga",Font.PLAIN,17));
j5.setSize(270,20);
j5.setLocation(60,10);

//Creating guess text fi

Solution

Vogel612's answer already covered naming. I'd like to highlight some other things: some because of how Swing works, and some about initialisation.

Initialisation

Initialisation and reset take mostly the same actions but are in two different places: ButtonListener3.actionPerformed and Guess.. Try taking these actions out and creating methods that clarify their intent:

private static final int MAX_NUMBER = 100;
public void start() {
    rand = (int) (Math.random() * MAX_NUMBER) + 1;
    count = 0;
    // set labels here
}

public void restart() {
    // any cleanup goes here
    start();
}


Keep it on the EDT

Swing is a multi-threaded environment, and any manipulation of GUI elements should happen on the Event Dispatch Thread (EDT). For most of an application's lifetime, this is not a direct concern because it primarily runs inside this EDT, but bootstrapping is a special case and requires your intervention.

public static void main(String[] args)
{
    SwingUtilities.invokeLater(
        new Runnable() {
            public void run() {
                Guess guess = new Guess();
                guess.start();
            }
        }
    };
}


Or, since Java 8:

public static void main(String[] args)
{
    SwingUtilities.invokeLater(
        () -> {
            Guess guess = new Guess();
            guess.start();
        }
    );
}


Yes, even running a single method or constructor requires this, and you may get away with it most of the time but, as I learned to my shame, not all of the time. ;)

Layout and Resizing

Not having a layout manager makes it easier to have components right where you want them, but it makes your container ignore resizing. If you've already picked the (only) size you're going to support, you may want to constrain it:

setMinimumSize(getSize());


Randoms in Java

Math.random() returns a value \$\in [0,1[\$, so if you want an integer between min and max, inclusive, you'll need to change a bit:

rand = (int) (Math.random() * (max - min + 1)) + min;


...which, for 1..100 would make:

rand = (int) (Math.random() * 100) + 1;


Because I got 0 on my first run of your game. :p

Seperation of Concerns

Your GUI and your game are intimately connected. Separation could help you maintain your code and make it more robust to changes.

The guessing part can be extracted into a class of its own, which will also take care of your magic numbers:

class GuessingGame {
    int value;
    int tries;
    int topScore = Integer.MAX_VALUE;

    Random random = new Random();

    public void reset() {
        tries = 0;
        value = random.nextInt(getMaximum() - getMinimum() + 1) + getMinimum();
    }

    public Result guess(int guess) {
        tries++;

        if ( guess == value ) {
            if ( topScore > tries ) {
                topScore = tries;
            }
            return Result.EXACT;
        }

        return guess < value ? Result.TOO_HIGH : Result.TOO_LOW;
    }

    public int getNumberOfTries() {
        return tries;
    }

    public int getTopScore() {
        return topScore;
    }

    public int getMinimum() { return 1; }
    public int getMaximum() { return 100; }
}

enum Result {
    TOO_HIGH, TOO_LOW, EXACT;
}

Code Snippets

private static final int MAX_NUMBER = 100;
public void start() {
    rand = (int) (Math.random() * MAX_NUMBER) + 1;
    count = 0;
    // set labels here
}

public void restart() {
    // any cleanup goes here
    start();
}
public static void main(String[] args)
{
    SwingUtilities.invokeLater(
        new Runnable() {
            public void run() {
                Guess guess = new Guess();
                guess.start();
            }
        }
    };
}
public static void main(String[] args)
{
    SwingUtilities.invokeLater(
        () -> {
            Guess guess = new Guess();
            guess.start();
        }
    );
}
setMinimumSize(getSize());
rand = (int) (Math.random() * (max - min + 1)) + min;

Context

StackExchange Code Review Q#48856, answer score: 11

Revisions (0)

No revisions yet.