What is wrong with the .add in my GUI program? - java

I am trying to make a GUI with a Grid layout that presents 3 random non repeatable cards within a file. I named all the cards 1-53.png and am trying to insert it into the panels of left, center, and right. When I try adding the files into my panels, there is an error withe the .add, and I do not know how to fix it.
I have already tried to change the .add and the index. I even tried to turn the int into a component, but nothing works.
public class Question_2 {
static String location = "cards/";
public static void main(String[] args) {
JFrame frmMyWindow = new frmMyWindow("Random Cards");
frmMyWindow.setSize(300, 200);
frmMyWindow.setLocationRelativeTo(null);
frmMyWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmMyWindow.setVisible(true);
}
}
class frmMyWindow extends JFrame {
JLabel lblName, l;
JPanel panelMain, panelLeft, panelCenter, panelRight;
JFrame f;
public frmMyWindow(String Cards) {
super("Random Cards");
lblName = new JLabel("Cards");
panelMain = new JPanel(new GridLayout(1, 3, 10, 10));
setLayout(new BorderLayout(20, 10));
add(lblName, BorderLayout.NORTH);
add(panelMain, BorderLayout.CENTER);
panelLeft = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 10));
panelCenter = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5));
panelRight = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 10));
panelMain.add(panelLeft);
panelMain.add(panelCenter);
panelMain.add(panelRight);
panelLeft.setBorder(new TitledBorder("Card 1"));
panelCenter.setBorder(new TitledBorder("Card 2"));
panelRight.setBorder(new TitledBorder("Card 3"));
int index = (int) Math.round(Math.random() * 53);
int index2 = (int) Math.round(Math.random() * 53);
int index3 = (int) Math.round(Math.random() * 53);
while (index == index2) {
index2 = (int) Math.round(Math.random() * 53);
}
while (index3 == index2 || index3 == index)
;
{
index3 = (int) Math.round(Math.random() * 53);
}
String image = index + ".png";
String image2 = index2 + ".png";
String image3 = index3 + ".png";
panelLeft.add(index);
panelCenter.add(index2);
panelRight.add(index3);
}
}
I want the program to present 3 random cards into the panels, but there is an error with the .add.

The problem is indeed to the add method and how you call it. Container#add method takes as arguments Components. You call it with int arguments.
I even tried to turn the int into a component, but nothing works.
The simplest way (I guess) to "add a number in a container" is to create a JLabel and add to it the number as text. By seeing your first attempt, I guess that you again messed up the methods. Probably in JLabels constructor. You did something like new JLabel(index) where index is an Integer. Which again fails because there is no constructor with int argument. The solution is to create a JLabel AND convert the integer to text:
panelLeft.add(new JLabel(String.valueOf(index)));
After that program can be compiled and run. However some notes are:
Always run your application using SwingUtilities#invokeLater since all Swing applications must run on their own thread.
public static void main(String[] args) {
SwingUtilities.invokeLater(()->{
JFrame frmMyWindow = new frmMyWindow("Random Cards");
frmMyWindow.setSize(300, 200);
frmMyWindow.setLocationRelativeTo(null);
frmMyWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmMyWindow.setVisible(true);
});
}
All class names "should" (well, its the standard convention) start with an Uppercase letter. Rename frmMyWindow to FrmMyWindow.

Related

How can i make the Jbutton in my widgetviewer to implement the proper event

Instructions:
Write a WidgetViewer GUI that has the following widgets:
a button labeled "go up/down"
a label initialized to 0 (we'll call this the left label)
a label initialized to 0 (we'll call this the right label)
a button labeled "go down/up"
When the "go up/down" button is pushed, a random number between 1 and 10 (inclusive)
is generated and added to the left label, and another random number between 1 and 10 (inclusive)
is generated and subtracted from the right label.
When the "go down/up" button is pushed, a random number between 1 and 10 (inclusive) is
generated and subtracted from the left label, and another random number between 1 and 10
(inclusive) is generated and added to the right label.
Error msg:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "Go up/down"
Code:
I cant seem to figure out this error message, it might have a possibility that i am adding a string but im not sure, it may be my logic. But im trying to figure out how i can get the Jbutton called goupdown and godownup to display a random number then add or subtract by 1 if needed.
public class UpAndDown {
public UpAndDown() {
WidgetViewer wv = new WidgetViewer();
JButton goUpDown = new JButton("Go up/down");
JLabel leftLabel = new JLabel("0");
wv.add(goUpDown, 10, 30, 150, 20);
wv.add(leftLabel, 10, 60, 150, 25);
JButton goDownUp = new JButton("Go down/up");
JLabel rightLabel = new JLabel("0");
wv.add(goDownUp, 10, 120, 150, 20);
wv.add(rightLabel, 10, 160, 150, 25);
ButtonIncrement action = new ButtonIncrement(goUpDown);
goUpDown.addActionListener(action);
ButtonIncrement action2 = new ButtonIncrement(goDownUp);
goDownUp.addActionListener(action2);
}
static class ButtonIncrement implements ActionListener {
private final JButton goUpDownBtn;
private final JButton goDownUpBtn;
public ButtonIncrement(JButton buttonToModify) {
goUpDownBtn = buttonToModify;
goDownUpBtn = buttonToModify;
}
#Override
public void actionPerformed(ActionEvent e) {
int rand = (int) (Math.random() * 10);
String val = goUpDownBtn.getText();
//JButton jc = (JButton) e.getSource();
int newVal = Integer.parseInt(val) + rand;
goDownUpBtn.setText(String.valueOf(newVal));
//jc.setText(goDownUpBtn.getText() + " " + val);// get string, convert to int, add rand value. then convert int back to string and set text to string
/*String val2 = goDownUpBtn.getText();
int newVal2 = Integer.parseInt(val2) + rand;
goDownUpBtn.setText(String.valueOf(newVal2));*/
}
}
Write a WidgetViewer GUI that has the following widgets:
a button labeled "go up/down" a label initialized to 0 (we'll call
this the left label) a label initialized to 0 (we'll call this the
right label) a button labeled "go down/up"
When the "go up/down" button is pushed, a random number between 1 and
10 (inclusive) is generated and added to the left label, and another
random number between 1 and 10 (inclusive) is generated and subtracted
from the right label.
When the "go down/up" button is pushed, a random number between 1 and
10 (inclusive) is generated and subtracted from the left label, and
another random number between 1 and 10 (inclusive) is generated and
added to the right label.
So, there's a bunch of important things we need to take away from this.
The values are initially initialised to 0
You need to update a label when a button is triggered
Depending on which button is triggered, will determine which values is added or subtracted to
So, we could simply start with
class IncrementDecrementAction implements ActionListener {
private final JLabel leftLabel;
private final JLabel rightLabel;
private int leftValue = 0;
private int rightValue = 0;
public IncrementDecrementAction(JLabel leftLabel, JLabel rightLabel) {
this.leftLabel = leftLabel;
this.rightLabel = rightLabel;
}
#Override
public void actionPerformed(ActionEvent e) {
int rand = (int) (Math.random() * 10) + 1;
leftValue += rand;
rand = (int) (Math.random() * 10) + 1;
rightValue += rand;
this.leftLabel.setText(Integer.toString(leftValue));
this.rightLabel.setText(Integer.toString(rightValue));
}
}
Okay, but this only solves the problem in one direction, what about down/up?
Well, we could write a second ActionListener which dealt with that, but then you'd need some kind of model to maintain the left and right values so both listeners knew what the current value was. Not an unreasonable idea, but it's an extra two classes to make it work.
Instead, we can take advantage of the ActionEvent's actionCommand support and give each button a specific name, which we can lookup when the action is triggered...
class IncrementDecrementAction implements ActionListener {
private final JLabel leftLabel;
private final JLabel rightLabel;
private int leftValue = 0;
private int rightValue = 0;
public IncrementDecrementAction(JLabel leftLabel, JLabel rightLabel) {
this.leftLabel = leftLabel;
this.rightLabel = rightLabel;
}
#Override
public void actionPerformed(ActionEvent e) {
int leftRandom = (int) (Math.random() * 10) + 1;
int rightRandom = (int) (Math.random() * 10) + 1;
if (e.getActionCommand().equals("upDown")) {
leftValue += leftRandom;
rightValue -= rightRandom;
} else if (e.getActionCommand().equals("downUp")) {
leftValue -= leftRandom;
rightValue += rightRandom;
}
this.leftLabel.setText(Integer.toString(leftValue));
this.rightLabel.setText(Integer.toString(rightValue));
}
}
This basically changes the direction of the calculation based on the source of the event - and it does it without having to now what the source of the event actually was (a button, a menu item, a key binding), it just doesn't care.
You simply set this up by applying the appropriate actionCommand to the appropriate Jbutton, for example...
public class TestPane extends JPanel {
private JLabel leftLabel;
private JLabel rightLabel;
private JButton upDownButton;
private JButton downUpButton;
public TestPane() {
leftLabel = new JLabel("0");
rightLabel = new JLabel("0");
upDownButton = new JButton("Up/down");
downUpButton = new JButton("Down/up");
upDownButton.setActionCommand("upDown");
downUpButton.setActionCommand("downUp");
ActionListener actionListener = new IncrementDecrementAction(leftLabel, rightLabel);
upDownButton.addActionListener(actionListener);
downUpButton.addActionListener(actionListener);
add(leftLabel);
add(rightLabel);
add(upDownButton);
add(downUpButton);
}
}
Now, I went through a dozen or so ideas before getting to this point - my point was to try and keep it as simple as I could without trying to introduce a whole bunch of complexity which might not need to be added - be beware - I don't know what the intention of the exercise is, so I might have gone in the wrong direction from the one your instructor was trying to get you to do
Modified code:
I modified the answer you gave according to the instructions with the WV object to display the GUI and this is the correct version.
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class UpAndDown extends JPanel {
private JLabel leftLabel;
private JLabel rightLabel;
private JButton upDownButton;
private JButton downUpButton;
public UpAndDown() {
WidgetViewer wv = new WidgetViewer();
JButton upDownButton = new JButton("Up/down");
wv.add(upDownButton, 10, 30, 150, 20);
JButton downUpButton = new JButton("Down/up");
wv.add(downUpButton, 10, 120, 150, 20);
JLabel leftLabel = new JLabel("0");
wv.add(leftLabel, 10, 60, 150, 25);
JLabel rightLabel = new JLabel("0");
wv.add(rightLabel, 10, 140, 150, 25);
upDownButton.setActionCommand("upDown");
downUpButton.setActionCommand("downUp");
ActionListener actionListener = new IncrementDecrementAction(leftLabel, rightLabel);
upDownButton.addActionListener(actionListener);
downUpButton.addActionListener(actionListener);
}
static class IncrementDecrementAction implements ActionListener {
private final JLabel leftLabel;
private final JLabel rightLabel;
private int leftValue = 0;
private int rightValue = 0;
public IncrementDecrementAction(JLabel leftLabel, JLabel rightLabel) {
this.leftLabel = leftLabel;
this.rightLabel = rightLabel;
}
public void actionPerformed(ActionEvent e) {
int leftRandom = (int) (Math.random() * 10) + 1;
int rightRandom = (int) (Math.random() * 10) + 1;
if (e.getActionCommand().equals("upDown")) {
leftValue += leftRandom;
rightValue -= rightRandom;
} else if (e.getActionCommand().equals("downUp")) {
leftValue -= leftRandom;
rightValue += rightRandom;
}
this.leftLabel.setText(Integer.toString(leftValue));
this.rightLabel.setText(Integer.toString(rightValue));
}
}
}

Array errors in for each loop java

im working on code for a basic hangman game with a swing UI. i am using a for loop to initiate all the buttons for the letters. however im getting a null pointer exception on line 39. I have looked it over and am not sure why it is not working properly. The bottom 10 or so lines of code is were the problem is being thrown.
import java.awt.Color;
import javax.swing.*;
public class GameUI {
public static void main(String[] args){
GameUI ui = new GameUI();
ui.initializeUI();
}
public void initializeUI(){
//initialize the window
JFrame window = new JFrame();
window.setSize(500,500);
window.setResizable(false);
window.setVisible(true);
//initialize main panel
JPanel wrapper = new JPanel();
wrapper.setLayout(null);
Color BGColor = new Color(240,230,140);
wrapper.setBackground(BGColor);
window.getContentPane().add(wrapper);
//Creates JLAbel title, this is used for the title of the game
JLabel title = new JLabel("Hangman v0.1");
title.setBounds(10, 5, 200, 50);
wrapper.add(title);
//=================================================================
//Creates JButtons for each letter (ERROR OCCURS BELLOW ON FIRST LINE AFTER LOOP BEIGNS)
//=================================================================
char[] alphabet = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
JButton[] letterButtons = new JButton[26];
int counter = 0;
for (char letter:alphabet){
letterButtons[counter].setText("" + letter);
//sets positions for each button
int posY = 50;
int posX = counter*5 + 10;
letterButtons[counter].setBounds(posX, posY, 10, 10);
wrapper.add(letterButtons[counter]);
counter++;
}
}
}
Objects in Java are null by default. Those in an Object array are no different. You need to initialise your JButton array letterButtons prior to attempting to invoke any operations on them
for (int i=0; i < letterButtons.length; i++) {
letterButtons[i] = new JButton();
}
JButton[] letterButtons = new JButton[26]; initializes each array element to null. You have to loop through the array and assign each position a new JButton()

Java swing/awt component to draw chessboard [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I don't have much experienc with swing/awt.
My problem is:
I need to draw something like chessboard (NxN).
In general I need to get access to every cell to make changes (when program is running e.g. I click button and something is happen with cells on that board).
It will be greate if a Component let me to set in cell a Image.
I try to use GridLayout but I get nothing what satisfy me.
Do you have any idea how to simply resolve that problem?
I made a Chess game myself in Java back sometime and found the code I used.
So here is something to start you off:
ChessBoardTest:
public class ChessBoardTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
Image blackBlock=ImageIO.read(new File("c:/bblock.jpg"));
Image whiteBlock=ImageIO.read(new File("c:/wblock.jpg"));
Board board = new Board(whiteBlock,blackBlock);
//add pieces to board
board.addPiece(new ImageIcon("c:/castle.jpg"), "A1");//just one example
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Board.java:
import java.awt.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/*
* #author David Kroukamp
*/
public class Board extends JFrame {
//intialize variables
private Image boardImage1;
private Image boardImage2;
//intialize components
private JPanel centerPanel = new JPanel();
private JPanel southPanel = new JPanel();
private JPanel westPanel = new JPanel();
//initialze arrays to hold panels and images of the board
private JLabel[] labels = new JLabel[64];
private ImagePanel[] panels = new ImagePanel[64];
public Board(Image boardImage1, Image boardImage2) {
this.boardImage1 = boardImage1;
this.boardImage2 = boardImage2;
createAndShowGUI();//call method to create gui
}
private void createAndShowGUI() {
setTitle("Chess board example");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
addComponentsToPane(getContentPane());
setSize(800, 600);
setLocationRelativeTo(null);
setVisible(true);
}
/**
* Adds all the necessary components to the content pane of the JFrame, and
* adds appropriate listeners to components.
*/
private void addComponentsToPane(Container contentPane) {
GridLayout gridLayout = new GridLayout(8, 8);
centerPanel.setLayout(gridLayout);
//call mehod to add labels to south panel
addLabelsToSouthPanel();
//call method to add oanels to west panel
addLabelsToWestPanel();
//call method to add panels and labels to the center panel which holds the board
addPanelsAndLabels();
//add all panels to frame
contentPane.add(centerPanel, BorderLayout.CENTER);
contentPane.add(southPanel, BorderLayout.SOUTH);
contentPane.add(westPanel, BorderLayout.WEST);
}
private void addLabelsToSouthPanel() {
GridLayout gridLayout = new GridLayout(0, 8);
southPanel.setLayout(gridLayout);
JLabel[] lbls = new JLabel[8];
String[] label = {"A", "B", "C", "D", "E", "F", "G", "H"};
for (int i = 0; i < 8; i++) {
lbls[i] = new JLabel(label[i] + "");
southPanel.add(lbls[i]);
}
}
private void addLabelsToWestPanel() {
GridLayout gridLayout = new GridLayout(8, 0);
westPanel.setLayout(gridLayout);
JLabel[] lbls = new JLabel[8];
int[] num = {8, 7, 6, 5, 4, 3, 2, 1};
for (int i = 0; i < 8; i++) {
lbls[i] = new JLabel(num[i] + "");
westPanel.add(lbls[i]);
}
}
private void addPanelsAndLabels() {
//call methd to create panels with backgound images and appropriate names
addPanelsAndImages();
for (int i = 0; i < panels.length; i++) {
labels[i] = new JLabel();
//used to know the postion of the label on the board
labels[i].setName(panels[i].getName());
panels[i].add(labels[i]);
//adds panels created in addPanelsAndImages()
centerPanel.add(panels[i]);
}
}
//this method will create panels with backround images of chess board and set its name according to 1-8 for rows and A-H for coloumns
private void addPanelsAndImages() {
int count = 0;
String[] label = {"A", "B", "C", "D", "E", "F", "G", "H"};
int[] num = {8, 7, 6, 5, 4, 3, 2, 1};
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if ((col + row) % 2 == 0) {//even numbers get white pieces
panels[count] = new ImagePanel(boardImage1);
} else {//odd numbers get black pieces
panels[count] = new ImagePanel(boardImage2);
}
panels[count].setName(label[col] + num[row]);
count++;
}
}
}
//method sets image of a label at a certain position in the board according to the block name i.e D4
public void addPiece(ImageIcon img, String block) {
for (int s = 0; s < labels.length; s++) {
if (labels[s].getName().equalsIgnoreCase(block)) {
labels[s].setIcon(img);
}
}
}
//nested class used to set the background of frame contenPane
class ImagePanel extends JPanel {
private Image image;
/**
* Default constructor used to set the image for the background for the
* instance
*/
public ImagePanel(Image img) {
image = img;
}
#Override
protected void paintComponent(Graphics g) {
//draws image to background to scale of frame
g.drawImage(image, 0, 0, null);
}
}
}
HTH to get you started.
There is actually quite a reasonable example online on roseindia.

Java JLabel setHorizontalAlignment with different results

I want to center an JLabel inside an BorderLayout. For now I use label.setHorizontalAlignment(SwingConstants.CENTER); and label.setVerticalAlignment(SwingConstants.BOTTOM);.
here the full Code:
public class JSector extends JRenderPanel implements WarpGateConstants {
private Sector sector;
private JLabel jLabelSectorName;
private JLabel[] jLabelWarpGate;
public JSector(Sector s) {
super(new BorderLayout());
this.setSector(s);
setBorder(new EmptyBorder(5, 5, 5, 5));
}
#Override
public void paintView(Graphics2D g) {
g.setColor(getBackground());
g.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getWidth() / 3, getHeight() / 3);
g.setColor(getForeground());
g.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getWidth() / 3, getHeight() / 3);
}
private void setSector(Sector s) {
this.sector = s;
drawSectorInfo(s);
}
public Sector getSector() {
return sector;
}
private void drawSectorInfo(Sector s) {
removeAll();
if (jLabelSectorName == null || jLabelWarpGate == null) {
this.jLabelWarpGate = new JLabel[WARPGATE_MAX_VALUE + 1];
this.jLabelWarpGate[WARPGATE_NORTH] = new JLabel("N");
this.jLabelWarpGate[WARPGATE_EAST] = new JLabel("E");
this.jLabelWarpGate[WARPGATE_SOUTH] = new JLabel("S");
this.jLabelWarpGate[WARPGATE_WEST] = new JLabel("W");
for (byte i = 0; i < jLabelWarpGate.length; i++) {
setupLabel(jLabelWarpGate[i], i);
}
this.jLabelSectorName = new JLabel("SectorName");
add(this.jLabelWarpGate[WARPGATE_NORTH], BorderLayout.NORTH);
add(jLabelWarpGate[WARPGATE_EAST], BorderLayout.EAST);
add(jLabelWarpGate[WARPGATE_SOUTH], BorderLayout.SOUTH);
add(jLabelWarpGate[WARPGATE_WEST], BorderLayout.WEST);
add(jLabelSectorName, BorderLayout.CENTER);
}
for (byte i = 0; i < jLabelWarpGate.length; i++) {
WarpGate gate = s.getWarpGate(i);
if (gate != null && gate.exists()) {
jLabelWarpGate[i].setToolTipText("TargetSector: " + gate.getTargetGridPos());
jLabelWarpGate[i].setVisible(true);
} else {
jLabelWarpGate[i].setVisible(false);
}
}
jLabelSectorName.setText(s.getName());
}
private static JLabel setupLabel(JLabel label, byte warpGateID) {
Font font = label.getFont();
font = new Font(font.getName(), Font.BOLD, font.getSize() + 2);
label.setFont(font);
label.setForeground(new Color(255, 150, 0));
label.setBackground(new Color(0, 100, 255, 150));
label.setOpaque(true);
switch (warpGateID) {
case WARPGATE_NORTH:
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setVerticalAlignment(SwingConstants.TOP);
break;
case WARPGATE_EAST:
label.setHorizontalAlignment(SwingConstants.RIGHT);
label.setVerticalAlignment(SwingConstants.CENTER);
break;
case WARPGATE_SOUTH:
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setVerticalAlignment(SwingConstants.BOTTOM);
break;
case WARPGATE_WEST:
label.setHorizontalAlignment(SwingConstants.LEFT);
label.setVerticalAlignment(SwingConstants.CENTER);
break;
}
return label;
}
}
It works good but the West and East Gates have different Vertical positions:
I hope you can help me to solve this problem
EDIT: I think I found the Problem. I set some Lables visible(false) and this causes the problem. But the problem is still there, how do I get these Jlabels on same line.
I found (one) solution that works good for me:
label.setForeground(new Color(255, 255, 255, 0));
this let the Component "appear" but displays nothing => Every JLabel is on the same level
If there are no components in the North or South 'slot' of the BorderLayout, the East and West components will expand to fill that space, causing the center of that component to depend on whether the other components are visible or not.
Three possible solutions come to mind, listed in order of complexity:
Show all of the labels all the time, but replace the contents to make them appear invisible if there's no gate on that edge. You would have to set heights manually to keep them consistent, but that's ok for prototyping.
Use a different LayoutManager (though no particularly good fit comes to mind)
Draw the sector without relying on nested components to represent gates, doing the necessary calculations by hand.
I would probably stick with the first option for now and transition to the third one later on.

Java hangman program gone horribly wrong

I am a beginner at Java, and was required to throw together an application for a Java final project. I wanted to do hangman (Seemed easy at the time). This is EXTREMELY DIFFICULT for me. Here is my code so far. (it's really an abomination of about 10 open source hangman games thrown together). See bottom for my question.
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
public class Hangman implements ActionListener {
JFrame frame;
private String[] wordList = {"computer","java","activity","alaska","appearance","article",
"automobile","basket","birthday","canada","central","character","chicken","chosen",
"cutting","daily","darkness","diagram","disappear","driving","effort","establish","exact",
"establishment","fifteen","football","foreign","frequently","frighten","function","gradually",
"hurried","identity","importance","impossible","invented","italian","journey","lincoln",
"london","massage","minerals","outer","paint","particles","personal","physical","progress",
"quarter","recognise","replace","rhythm","situation","slightly","steady","stepped",
"strike","successful","sudden","terrible","traffic","unusual","volume","yesterday" };
public String mysteryWord;
public int lives;
private boolean finished = false;
private boolean won = false;
private Button a[];
public boolean used[] = new boolean[26];
public static void main (String[] args) {
Hangman gui = new Hangman();
gui.go();
}
class myDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
setBackground(Color.white);
g.setColor(Color.gray);
g.fillRect(50, 200, 150, 20);
g.fillRect(90,20,10,200);
g.fillRect(90,20,60,10);
g.setColor(Color.black);
g.fillRect(145,20,5,25);
g.setColor(Color.green);
if (lives < 6 )
g.drawOval(132,45,30,30);
if (lives < 5 )
g.drawLine(147,75,147,100);
if (lives < 4 )
g.drawLine(147,100,167,133);
if (lives < 3 )
g.drawLine(147,100,127,133);
if (lives < 2 )
g.drawLine(147,75,167,85);
if (lives < 1 )
g.drawLine(147,75,127,85);
StringBuffer guessed = new StringBuffer();
for (int cl = 0; cl < mysteryWord.length(); cl++) {
if (used[(int)mysteryWord.charAt(cl)-65])
guessed.append(mysteryWord.charAt(cl));
else
guessed.append(".");
}
g.drawString(guessed.toString(),75,230);
//currentWordLA.setText("Current word: " + mysteryWord);
if (lives < 1) {
g.setColor(Color.white);
g.fillRect(70, 200, 200, 30);
g.setColor(Color.black);
g.drawString(mysteryWord.toString(),75,230);
Font fff = new Font("Helvetica",Font.BOLD,36);
g.setFont(fff);
g.setColor(Color.red);
g.drawString("You lose!",200,100);
finished = true;
}
if (won) {
Font fff = new Font("Helvetica",Font.BOLD,36);
g.setFont(fff);
// Color red=new Color.red
g.setColor(Color.red);
g.drawString("You Win!",200,100);
finished = true;
}
}
}
public void go() {
///////////////////////DESIGN BEGIN//////////////////////////////////////////////
frame = new JFrame("Hangman");
JPanel topPanel = new JPanel();
myDrawPanel noosePanel = new myDrawPanel();
JPanel bottomPanel = new JPanel();
JPanel scorePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout( new GridLayout( 2, 0) );
bottomPanel.setLayout( new GridLayout( 0, 2) );
scorePanel.setSize(20,100);
noosePanel.setBorder(BorderFactory.createTitledBorder("Your progress."));
topPanel.setBorder(BorderFactory.createTitledBorder("Your arsenal."));
scorePanel.setBorder(BorderFactory.createTitledBorder("Your score."));
frame.add(topPanel);
frame.add(bottomPanel);
bottomPanel.add(scorePanel);
bottomPanel.add(noosePanel);
//Just the stats panel.
JPanel stats = new JPanel();
JLabel currentWordLA = new JLabel("Current word:");
JLabel triedLettersLA = new JLabel("Tried letters:");
JLabel triesLeftLA = new JLabel("Tries remaining:");
JButton restart = new JButton("Reset");
currentWordLA.setFont(new Font("Verdana", Font.PLAIN, 10));
currentWordLA.setForeground(Color.black);
triedLettersLA.setFont(new Font("Verdana", Font.PLAIN, 10));
triedLettersLA.setForeground(Color.black);
triesLeftLA.setFont(new Font("Verdana", Font.PLAIN, 10));
triesLeftLA.setForeground(Color.black);
restart.setFont(new Font("Verdana", Font.PLAIN, 16));
restart.setForeground(Color.red);
stats.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(20,0,0,0);
c.anchor = GridBagConstraints.LINE_START;
stats.add(currentWordLA, c);
c.gridx = 0;
c.gridy = 1;
c.anchor = GridBagConstraints.LINE_START;
stats.add(triedLettersLA, c);
c.gridx = 0;
c.gridy = 2;
c.anchor = GridBagConstraints.LINE_START;
stats.add(triesLeftLA, c);
c.gridx = 0;
c.gridy = 3;
c.anchor = GridBagConstraints.LINE_START;
stats.add(restart, c);
scorePanel.add(stats);
///////////////////////DESIGN END//////////////////////////////////////////////
///////////////////////ALPHABET BEGIN//////////////////////////////////////////
int i;
StringBuffer buffer;
a = new Button[26];
topPanel.setLayout( new GridLayout( 4,0, 10, 10) );
for (i = 0; i <26; i++) {
buffer = new StringBuffer();
buffer.append((char)(i+65));
a[i] = new Button(buffer.toString());
a[i].setSize(100,100);
a[i].addActionListener( this );
topPanel.add(a[i]);
}
///////////////////////ALPHABET END//////////////////////////////////////////
//Just shows the entire window.
frame.setSize(500, 500);
frame.setResizable(false);
frame.setVisible(true);
//////////////////////GAMEPLAY BEGIN////////////////////////////////////////
lives = 6;
mysteryWord = wordGen();
}
//Returns a random word from the wordList bank.
private String wordGen() {
return wordList[0 + (int)(Math.random() * ((63 - 0) + 1)) ]; //Make sure to set these to nonprinted chars eventually
}
public void consultWord(int letter) {
if (finished == false) {
boolean found = false;
boolean www = false;
if (used[letter] = false) {
for (int cl = 0 ; cl < mysteryWord.length(); cl++) {
if (mysteryWord.charAt(cl)==((char)(letter+65))) found = true;
}
if (found == false)
lives = lives - 1;
}
used[letter] = true;
for (int cl = 0; cl < mysteryWord.length(); cl++) {
if (!used[(int)(mysteryWord.charAt(cl)) - 65]) www = true;
}
if (www = false) won = true;
frame.repaint();
}
}
public void actionPerformed( ActionEvent e) {
int i;
for (i = 0; i < 26; i++) {
if (e.getSource() == a[i]) {
consultWord(i); }
}
}
}
At the moment this doesn't work. I run it, and tons of thread exeption errors come up. (It compiles beautifully). The first line it takes me to is
if (used[(int)mysteryWord.charAt(cl)-65])
I'm not sure what the issue is with this line. Also, the original author used the number 65. I tweaked my code and used my own variables so that I understood how it worked. But the number 65 and where it came from, I can't figure out for the life of me. Any ideas?
And I need to know what is causing all the thread exceptions. The GUI builds nicely. It's just all the math and triggers that mess things up. (The GUI I built all by myself! :) )
Exception
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 34
at Hangman$myDrawPanel.paintComponent(Hangman.java:55)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:585)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
This is mostly not a direct answer to your question, but it is relevant to the larger issue of learning to write software ... which is your overall goal. (And there's a real answer at the bottom.)
You write:
(it's really an abomination of about 10 open source hangman games thrown together)
Taking a bunch of existing programs (of dubious quality *) and mashing them together is NOT a good way to create software.
You inherit the problems of functionality and style in the existing code that you have "harvested".
You add a bunch of new functionality and style problems caused by mismatches between the different code bases ... and your conception.
Code reuse can be a good thing, but you need to be disciplined and selective:
Do design your own code ... following the design principles that you have been taught.
Do reuse at the library level, using well-engineered libraries.
Don't reuse by copy-and-pasting.
Don't reuse code (or libraries) that looks like a dog's breakfast. (If the author is sloppy with his/her code style and API design, that's a bad sign for other quality issues.)
(* The fact that you are seeing obscure numbers like 65 embedded in the code is a sign of poor code quality. The author could and should have written that as 'A'.)
In fact, this might be the root of your bug, since it looks like your "mystery" words are in lowercase. 'a' - 'A' is 32, and that is larger than the bounds of your used array.
And this brings us back to my main point. Because, apparently, in your code mashing you have failed to understand the implied invariants of the code you copied ... and broken them. The problematic statement that is throwing the exception is designed to work with uppercase-only words ... but you've changed that.
The 65 is the ASCII character code for the letter 'A'. The line in question is converting from the ASCII ordinal value to something in the range 0-25, which allows the used array to store whether each letter of the alphabet has been checked.
65 is ASCII for 'A', but your words are all in lowercase. So instead of (int)mysteryWord.charAt(cl)-65, you should do (int)mysteryWord.charAt(cl)-'a'
change
if (used[(int)mysteryWord.charAt(cl)-65])
guessed.append(mysteryWord.charAt(cl));
else
guessed.append(".");
}
to
if (used[(int)mysteryWord.charAt(cl)-97])
guessed.append(mysteryWord.charAt(cl));
else
guessed.append(".");
}
The code at line 55, when converting to ASCII, is ending up with a value larger than the size of the used array.

Categories

Resources