Reputation: 47
I am currently working on a Hangman game. The game uses a driver and takes in a text file of words, picks a random word and sends it to my ImageBuilder class which creates a gui with text boxes and buttons to submit letters and play the game.
If the user inputs the wrong letter, it makes a method call to my DrawArea class which changes the boolean value to true, which should trigger the drawing to show up on the panel.
I had issues figuring out how to do it and my professor said to create an instance, set the size and add it to the panel in my main gui creator method in my ImageBuilder class. Using her idea, I am getting a null pointer exception because I'm guessing it can't find the instance.
I tried creating the instance in the method that calls the drawings, and that didn't display anything either. My drawings aren't complete, but I'm just trying to get things to display at this point.
Any help on this would be greatly appreciated.
Here is my code:
Game.java:
import java.util.*;
import java.io.*;
public class Game {
/** The main program will perform the following steps
* 1. Take in a text file
* 2. Read through the text file and select a random word
* 3. Create an instance of ImageBuilder and pass the random word through
*/
public static void main(String[] args) throws FileNotFoundException {
ImageBuilder n = new ImageBuilder(grabWord(args[0]));
}
/**
* Opens a file and parses the formatted file
* reads on each line of the file and splits the string into an array
* grabs the ages of the entries and sums them to print to screen
* @param fileName the path to input file
*
*/
private static String grabWord(String fileName)throws FileNotFoundException {
int sum = 0;
ArrayList<String> words = new ArrayList<>();
Scanner fileScan = new Scanner(new File(fileName));
while(fileScan.hasNextLine()){
sum++;
String line = fileScan.nextLine();
words.add(line);
}
Random rand = new Random();
int randNum = rand.nextInt(sum);
System.out.println(randNum);
String test = words.get(randNum-1);
System.out.println(test);
return (test);
}
}
ImageBuilder.java
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
public class ImageBuilder extends JPanel {
// Set Frame Size Variables
private static final int FRAME_WIDTH = 700;
private static final int FRAME_HEIGHT = 800;
//Create frame
private JFrame frame;
private int FIELD_WIDTH = 10;
// Create Panels
private JPanel panel1;
private JPanel panel2;
final JTextField b = new JTextField(FIELD_WIDTH);
// Create Labels
private JLabel underscores;
private JLabel wordLabel;
private JLabel wordToGuessLabel;
private JLabel textLabel;
private JLabel guessText;
private JLabel guessedLettersArea;
// Variable for number of letters in word
private int numOfLetters;
// Text field
private JTextField wordInput;
// Text are for the word
private JTextArea wordResults;
// Create button
private JButton button;
// String for word
private String word;
// Array list for __'s and word
private ArrayList<String> wordDisplay;
// String for guessed letters
private String guessedLetters;
// DrawArea
private DrawArea draw;
private int incorrectGuesses;
public ImageBuilder(String word){
DrawArea draw = new DrawArea();
// Pass the word through
this.word = word;
// Initialize word display array to display __ array
wordArrayCreator();
// Create Guess Text
//JLabel label3 = new JLabel("Guess a letter:");
//Dimension size2 = label3.getPreferredSize();
// Set location and size of label2
//label3.setBounds(140, 70, size2.width, size2.height);
// Call Methods
createAndShowGui();
createButton();
createTextField();
//createPanel();
createGuessArea();
//button.setLayout(null);
panel1.add(textLabel);
panel1.add(wordInput);
panel1.add(button);
panel1.add(guessText);
panel1.add(guessedLettersArea);
// Create Word box
JPanel letterPanel = new JPanel();
// Set frame as visible
frame.setVisible(true);
// Add panel1 to frame
frame.add(panel1);
}
/**
* Creates wordDisplay Array to display word
*
*/
private void wordArrayCreator() {
// Create array list for word, replace each word with string: "__ "
wordDisplay = new ArrayList<>();
for (int i = 0; i <= word.length() - 1; i++) {
String add = "__ ";
wordDisplay.add(add);
}
}
/**
* Creates base layer of gui w/o any
* interactive changes
*/
private void createAndShowGui() {
// Initialize Frame and Panels
frame = new JFrame("Hangman");
panel1 = new JPanel();
//panel2 = new JPanel();
// Allows manual layout for both panels
panel1.setLayout(null);
//panel2.setLayout(null);
// Create label with text
wordLabel = new JLabel("Word to Guess: ");
Dimension size = wordLabel.getPreferredSize();
// Set location and size of label
wordLabel.setBounds(130, 22, size.width, size.height);
// Add label to panel
panel1.add(wordLabel);
panel1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// Initializes frame content
frame.getContentPane();
// Create label for array, replacing "[", "]" and "," with ""
underscores = new JLabel(wordDisplay.toString().replace("[","")
.replace("]","").replace(",",""));
//Dimension size3 = underscores.getPreferredSize();
// Place underscore text label
underscores.setBorder(BorderFactory.createLineBorder(Color.gray));
underscores.setBounds(230, 20, 250, 22);
// Add label of underscores to panel1
panel1.add(underscores);
// Create label for number of letters text
numOfLetters = word.length();
// Create label for the amount of letters to guess
wordToGuessLabel = new JLabel("The word to guess has " + numOfLetters + " letters");
Dimension size1 = wordToGuessLabel.getPreferredSize();
// Set location and size of wordToGuessLabel
wordToGuessLabel.setBounds(230, 45, size1.width, size1.height);
// Initializing draw area and setting size
DrawArea draw = new DrawArea();
draw.setLayout(null);
draw.setPreferredSize(new Dimension(500, 500));
// Adding draw area to panel
panel1.add(draw);
// Add label to panel
panel1.add(wordToGuessLabel);
// Set up settings for frame
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
/**
* Creates label and text box to input
* through action listener
*/
private void createTextField() {
textLabel = new JLabel("Guess a Letter: ");
Dimension size4 = textLabel.getPreferredSize();
// Set location and size of label
textLabel.setBounds(160, 70, size4.width, size4.height);
// Create word input area
wordInput = new JTextField(6);
// Set word input Size and set default text as ""
Dimension size5 = wordInput.getPreferredSize();
wordInput.setBounds(260, 70, size5.width, size5.height);
wordInput.setText("");
wordInput.isEditable();
wordInput.isEnabled();
}
/**
* Creates labels for guessed text and box for
* displaying letters that have been guessed
*/
private void createGuessArea() {
// String for letters that have been guess
guessedLetters = "";
guessText = new JLabel("Guessed Letters: ");
//Dimension size6 = guessText.getPreferredSize();
guessText.setLayout(null);
// Set location and size of label
guessText.setBounds(165, 100, 150, 30);
guessedLettersArea = new JLabel(guessedLetters.replace("[","")
.replace("]","").replace(",",""));
// Set location and size of label
guessedLettersArea.setBounds(275, 105, 150, 22);
guessedLettersArea.setBorder(BorderFactory.createLineBorder(Color.gray));
}
/**
* Creates button to submit guessed letter
*/
private void createButton() {
// Initialize button
button = new JButton("Submit Letter");
button.setLayout(null);
button.setBounds(335, 68, 120, 25);
ActionListener listener = new AddLetterListener();
button.addActionListener(listener);
// Add button to panel1
panel1.add(button);
}
/**
* Action listener for button and text box
* to submit letter. Does logic for if letter has been guessed
* and calls methods to add letters to correct arrays
*/
class AddLetterListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
// Grab text input
String input = (wordInput.getText());
input = input.toLowerCase();
// Checks for at least one letter
if (input.length() < 1) {
JOptionPane.showMessageDialog(frame, "You need to guess one letter.");
wordInput.setText("");
return;
}
// Checks for more than one letter
if (input.length() > 1) {
JOptionPane.showMessageDialog(frame, "You can only guess one letter.");
wordInput.setText("");
return;
}
if (guessedLetters.contains(input)) {
JOptionPane.showMessageDialog(frame, "You have already guessed that letter, try again.");
wordInput.setText("");
return;
}
if (incorrectGuesses == 7) {
wordInput.setEnabled(false);
}
else {
// Checks if word contains input letter
if (word.contains(input)) {
wordInput.setText("");
int i = word.indexOf(input);
// Locates first index
while(i >= 0) {
System.out.println(i);
updateArray(i, input);
updateGuesses(input);
i = word.indexOf(input, i+1);
}
}
else {
updateGuesses(input);
drawingCall();
wordInput.setText("");
return;
}
}
}
}
/**
* Updates the string that contains the guessed letter
* @param letter : the letter that has been guessed
*/
private void updateGuesses(String letter) {
if (!(guessedLetters.contains(letter))) {
guessedLetters = guessedLetters + " " + letter;
guessedLettersArea.setText(guessedLetters);
}
}
/**
* Calls instance of draw and should call method within DrawArea class
*/
private void drawingCall() {
incorrectGuesses++;
System.out.println(incorrectGuesses);
if(incorrectGuesses == 1) {
draw.drawGallows();
System.out.println("Suppose Gallows");
repaint();
}
if(incorrectGuesses == 2) {
draw.drawHead();
System.out.println("Suppose head");
repaint();
}
if(incorrectGuesses == 3) {
draw.drawBody();
System.out.println("Suppose body");
repaint();
}
if(incorrectGuesses == 4) {
draw.drawLeftArm();
System.out.println("Suppose left arm");
repaint();
}
if(incorrectGuesses == 5) {
//drawArea.drawRightArm();
System.out.println("Suppose right arm");
repaint();
}
if(incorrectGuesses == 6) {
draw.drawLeftLeg();
System.out.println("Suppose left leg");
repaint();
}
if(incorrectGuesses == 7) {
draw.drawRightLeg();
System.out.println("Suppose right leg");
repaint();
}
}
/**
* Updates correctly guessed letters in the word array
*/
private void updateArray(int placeOfIndex, String letter) {
wordDisplay.set(placeOfIndex, letter);
underscores.setText(wordDisplay.toString().replace("[","")
.replace("]","").replace(",",""));
}
}
DrawArea.java
import java.awt.*;
import javax.swing.*;
public class DrawArea extends JComponent {
private boolean gallows;
private boolean head;
private boolean body;
private boolean leftArm;
private boolean rightArm;
private boolean leftLeg;
private boolean rightLeg;
public DrawArea() {
}
public void drawGallows() {
gallows = true;
System.out.println("Drawing Gallows");
}
public void drawHead() {
head = true;
System.out.println("Drawing Head");
repaint();
}
public void drawBody() {
body = true;
System.out.println("Drawing body");
repaint();
}
public void drawLeftArm() {
leftArm = true;
System.out.println("Drawing left arm");
repaint();
}
public void drawRightArm() {
rightArm = true;
System.out.println("Drawing right arm");
repaint();
}
public void drawLeftLeg() {
leftLeg = true;
System.out.println("Drawing left leg");
repaint();
}
public void drawRightLeg() {
rightLeg = true;
System.out.println("Drawing right leg");
repaint();
}
public void paintComponent(Graphics g) {
if(gallows){
g.fillRect(400, 400, 100, 100);// Base
//g.fillRect(300, 700, 50, 400);// Pole
//g.fillRect(100, 200, 400, 10);// Top
//g.fillRect(100, 220, 50, 20);// Little Drop
repaint();
}
if(head){
g.drawOval(120, 200, 50, 50);
}
if(body) {
g.fillRect(125, 240, 50, 100);
}
if(leftArm) {
}
if(rightArm) {
}
if(leftLeg) {
}
if(rightLeg) {
}
}
}
Upvotes: 0
Views: 1468
Reputation: 347244
You're shadowing your variables:
public class ImageBuilder extends JPanel {
//...
private DrawArea draw;
public ImageBuilder(String word){
DrawArea draw = new DrawArea();
You've defined draw
as an instance field of ImageBuilder
, but in the constructor, you've re-defined draw
as a local variable, which is only accessible from within the context of the constructor. This means your instance field is null
Remove the local declaration, for example:
public class ImageBuilder extends JPanel {
//...
private DrawArea draw;
public ImageBuilder(String word){
draw = new DrawArea();
Your use of null
layouts is going to cause you no end of issues. I'd highly recommend you make the time to better understand the layout API and make use of it. See Laying Out Components Within a Container for more details
now the drawings won't display. Any input on that?
As I said, null
layouts will come back to haunt you...
private void createAndShowGui() {
//...
// 🤨
// Allows manual layout for both panels
panel1.setLayout(null);
//panel2.setLayout(null);
// Another instances??
// Initializing draw area and setting size
DrawArea draw = new DrawArea();
// Pointless
draw.setLayout(null);
// Pointless
draw.setPreferredSize(new Dimension(500, 500));
// Adding draw area to panel
panel1.add(draw);
//...
}
panel1
has no layout manager, so using setPreferredSize
is pointless, as it relates to the layout management system ... although I'd generally discourage it's use and recommend overriding the classes getPreferredSize
instead.
So. When you do panel1.add(draw)
, draw
has no size or location information associated with it, meaning, Swing won't even bother wasting its time painting it.
Upvotes: 1