Reputation: 11
I'm trying to code a simple GUI dice game in Java called HighLow. Basically, the user starts with an initial balance of £50 and they have a choice of three different betting amounts and if they choose Low the dice must land on either 2, 3, 4, 5 or 6 and pays 1:1 and if they choose High the dice must land on either 8, 9, 10, 11 or 12 and pays 1:1. If they choose Sevens the dice must land on seven and pays 4:1. There are two dice so the value of both should be added. This is not the point of my question but just thought I'd clear that up so you understand the point of the game.
I'm totally new to panels, event handling and everything like that so I'm currently learning but I'm having some difficulty trying to work this out. I have five classes: Dice.java consists of a getFaceValue() and throwDie() method to simulate the random throw of a die. DiceFace.java creates dice with pips/dots on them. DiceFaceViewer.java is the frame class. DiceFaceComponent is the component for two dice and GamePanel is the panel where all the JButtons and JComboBox etc are located.
This is what I have done so far: created a frame, stuck the panel with the buttons etc in, and added the dice images to the frame. What I want is for the dice to be repainted onto the frame with a random face whenever I click the 'Throw Dice' button. All it is doing right now is generating a random face if I open and close the window.
Dice
import java.util.Random;
public class Dice {
// Instance variables
private int faceValue;
private int sides;
private Random generator;
public Dice(int s) {
generator = new Random();
sides = s;
faceValue = generator.nextInt(sides) + 1;
}
// Simulates the throw of a die landing on a random face.
public int throwDie() {
return faceValue = (int)(Math.random() * sides) + 1;
}
// Returns the current face value of the die
public int getFaceValue() {
return faceValue;
}
// Set face value of die
public void setValue(int v) {
faceValue = v;
}
}
DiceFace
import java.awt.*;
import java.awt.geom.*;
public class DiceFace {
// Holds the seven possible dot positions on a standard die
private Ellipse2D.Double[] dots = new Ellipse2D.Double[7];
private Rectangle box;
private int xLeft;
private int yTop;
private int side;
private int diceValue;
public DiceFace(int s, int x, int y, int v) {
side = s; // Dimension of dice face
xLeft = x; // xPos
yTop = y; // yPos
diceValue = v; // Pip value
}
public void draw(Graphics2D g2) {
box = new Rectangle(xLeft, yTop, side, side);
makeDots();
// Black background
g2.setColor(Color.BLACK);
g2.fill(box);
// White dots on black
g2.setColor(Color.WHITE);
// Draw dots
if (diceValue == 1)
g2.fill(dots[0]);
else if (diceValue == 2) {
g2.fill(dots[1]); g2.fill(dots[2]);
}
else if (diceValue == 3) {
g2.fill(dots[0]); g2.fill(dots[1]); g2.fill(dots[2]);
}
else if (diceValue == 4) {
g2.fill(dots[1]); g2.fill(dots[2]);
g2.fill(dots[3]); g2.fill(dots[4]);
}
else if (diceValue == 5) {
g2.fill(dots[0]); g2.fill(dots[1]);
g2.fill(dots[2]); g2.fill(dots[3]); g2.fill(dots[4]);
}
else if (diceValue == 6) {
g2.fill(dots[1]); g2.fill(dots[2]); g2.fill(dots[3]);
g2.fill(dots[4]); g2.fill(dots[5]); g2.fill(dots[6]);
}
}
public void makeDots() {
int w = side/6; // Dot width
int h = side/6; // Dot height
dots[0] = new Ellipse2D.Double(xLeft + (2.5 * side)/6,
yTop + (2.5 * side)/6, h, w);
dots[1] = new Ellipse2D.Double(xLeft + (3.75 * side)/6,
yTop + (3.75 * side)/6, h, w);
dots[2] = new Ellipse2D.Double(xLeft + (1.25 * side)/6,
yTop + (1.25 * side)/6, h, w);
dots[3] = new Ellipse2D.Double(xLeft + (1.25 * side)/6,
yTop + (3.75 * side)/6, h, w);
dots[4] = new Ellipse2D.Double(xLeft + (3.75 * side)/6,
yTop + (1.25 * side)/6, h, w);
dots[5] = new Ellipse2D.Double(xLeft + (1.25 * side)/6,
yTop + (2.5 * side)/6, h, w);
dots[6] = new Ellipse2D.Double(xLeft + (3.75 * side)/6,
yTop + (2.5 * side)/6, h, w);
}
}
DiceFaceViewer
import java.awt.*;
import javax.swing.*;
public class DiceFaceViewer {
public static void main(String[] args) {
// Create frame
JFrame frame = new JFrame();
// Set frame attributes
frame.getContentPane().setPreferredSize(new Dimension(360, 320));
frame.pack();
frame.setTitle("High Low");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
// Set location of frame to centre screen
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = frame.getSize().width;
int h = frame.getSize().height;
int x = (dim.width-w)/2;
int y = (dim.height-h)/2;
frame.setLocation(x, y);
DiceFaceComponent component = new DiceFaceComponent();
frame.add(component);
// Add panel to frame
GamePanel panel = new GamePanel();
frame.add(panel, BorderLayout.NORTH);
frame.setVisible(true);
}
}
DiceFaceComponent
import java.awt.*;
import javax.swing.*;
public class DiceFaceComponent extends JComponent {
// Instance variables
private int faceValue1;
private int faceValue2;
public DiceFaceComponent() {
faceValue1 = new Dice(6).getFaceValue();
faceValue2 = new Dice(6).getFaceValue();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
DiceFace dice1 = new DiceFace(75, 66, 160, faceValue1); // s, x, y, v
dice1.draw(g2);
repaint();
DiceFace dice2 = new DiceFace(75, 219, 160, faceValue2);
dice2.draw(g2);
repaint();
}
}
GamePanel
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GamePanel extends JPanel {
private int balance = 50;
public GamePanel() {
// Components
JRadioButton highButton = new JRadioButton("High");
JRadioButton lowButton = new JRadioButton("Low");
JRadioButton sevensButton = new JRadioButton("Sevens");
// Button group
ButtonGroup bg = new ButtonGroup();
bg.add(highButton);
bg.add(lowButton);
bg.add(sevensButton);
add(highButton);
add(lowButton);
add(sevensButton);
// Array to hold bet amounts
String betAmounts[] = {"£10", "£5", "£1"};
// Bets combo box
JComboBox bets = new JComboBox(betAmounts);
add(bets);
// Balance
JLabel bal = new JLabel(" Balance: £" + balance);
add(bal);
// Throw dice button
final JButton throwButton = new JButton("Throw Dice");
add(throwButton, FlowLayout.RIGHT);
class Action implements ActionListener {
Dice dice = new Dice(6);
public void actionPerformed(ActionEvent e) {
dice.throwDie();
dice.getFaceValue();
}
}
throwButton.addActionListener(new Action());
}
}
Upvotes: 0
Views: 1576
Reputation: 347314
Don't call repaint from within any paint
method. This will cause the repaint manager to schedule a another repaint event, eventually consuming your CPU and stalling your programming.
Instead call repaint
for the actions listener that is updating the dive's face value.
There is also no connection between the dice and the dice DiceFaceComponent
, it will never know what values it should be drawing.
Also, in your DiceFace
class, I wouldn't bother recreating the "dots" on each draw, it just a waste. Create them in the constructor instead.
The same goes for the paintComponent
method, don't bother recreating the DiceFace, simply create two references when you construct the class and update their face values as needed.
I would use the Dice
as the base model that ties all the various elements together. By using something like a ChangeListerner
, it would be possible for the Dice
to notify the various components that a change has occurred allowing them to update the screen
Upvotes: 1