/*
* BoggleGUI.java
*
* @author PaulKube and Michael Green
* see http://www-cse.ucsd.edu/~kube/100/boggle/
*/
package cs310;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.*;
import java.awt.event.*;
import java.io.*;
/** A GUI for the game of Boggle.
*
* BoggleGUI defines and implements methods to do these things:
*
* 1. Draw the boggle board
* 2. Manage the computer and human players' word lists
* 3. Update the scoreboard
*
* BoggleGUI requires class BogglePlayer, to define these instance methods:
*
* public void buildLexicon(Set wordList)
* public void setBoard(String[] letterArray)
* public SortedSet getAllValidWords(int minimumWordLength)
* public boolean isInLexicon(String wordToCheck)
* public java.util.List isOnBoard(String wordToCheck)
* public String[] getCustomBoard()
*
*
* @author Michael Green
* @author Paul Kube
*
* Copyright (C) 2002 Michael Green
* Copyright (C) 2002 Paul Kube
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. See
* http://www.gnu.org/copyleft/gpl.html
*/
public class BoggleGUI extends JFrame {
public static String WORDLISTFILENAME;
public static int DICEROWS = 4; // default
public static int DICECOLS = 4; // default
public static int MINIMUMWORDLENGTH = 4; // default
private BogglePlayer computerPlayer;
private BoggleBoard theBoard;
private ScoreArea humanArea, computerArea;
private WordEntryField wordEntryField;
public BoggleGUI() {
super( "Welcome to B00GLE!");
// create a BogglePlayer computer player to use
computerPlayer = new BogglePlayer();
// Read word list from file and initialize computerPlayer's Lexicon
initLexicon();
/* Intialize graphics panelsur option) any later version. See
* http://www.gnu.org/copyleft/gpl.html
*/
public class BoggleGUI extends JFrame {
public static String WORDLISTFILENAME;
public static int DICEROWS = 4; // default
public static int DICECOLS = 4; // default
public static int MINIMUMWORDLENGTH = 4; // default
private BogglePlayer computerPlayer;
private BoggleBoard theBoard;
private ScoreArea humanArea, computerArea;
private WordEntryField wordEntryField;
public BoggleGUI() {
super( "Welcome to B00GLE!");
// create a BogglePlayer computer player to use
initPanels();
// Establish menu bar options and listeners for them
setUpMenuBar();
// WindowClosing listener: for JDK 1.2 compatibility
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}});
// Trust contained components to set their sizes; top level frame packs
pack();
}
/**
* Get ready for a new game, given a letter list specification of
* the Boggle board.
*/
public void newGame(String[] letterList) {
// Tell theBoard about the board layout
theBoard.setBoard(letterList);
// Tell computerPlayer about the board layout
computerPlayer.setBoard(letterList);
// Prepare score areas
humanArea.setReady();
computerArea.setReady();
// Clear board highlighting
theBoard.unHighlightAllDice();
// Allow edits to text area and set focus
wordEntryField.setReady();
// redraw the whole thing so it looks as nice as can be
repaint();
}
/**
* Consider a word entered by the human player.
*/
public void checkAndAddWordHuman(String wordToCheck) {
// clear any board highlighting
theBoard.unHighlightAllDice();
// if empty word, the computer gets to take its turn
if(wordToCheck.length() == 0) {
wordEntryField.setUnready();
computerPlay();
return;
}
// check that word is:
// (1) at least minimum length, (2) on the board, (3) in the lexicon,
// (4) not already entered by the player
if(wordToCheck.length() < MINIMUMWORDLENGTH) {
chideUser(wordToCheck, "Less Than " + MINIMUMWORDLENGTH + " Letters");
return;
}
java.util.List letterLocations;
// letterLocations = theBoard.getLocationsForWord(wordToCheck);
// String wordOnBoard = theBoard.getWordFromLocations(letterLocations);
// if(!wordToCheck.equalsIgnoreCase(wordOnBoard)) { // double check
// we just trust the computer player to check this
letterLocations = computerPlayer.isOnBoard(wordToCheck);
if(letterLocations == null) {
chideUser(wordToCheck, "Not On Board");
return;
}
if(!computerPlayer.isInLexicon(wordToCheck)) {
chideUser(wordToCheck, "Not In Lexicon");
return;
}
if(humanArea.containsWord(wordToCheck)) {
chideUser(wordToCheck, "Duplicate Word");
return;
}
// OK, this word passed our rigorous suite of tests. Add it
humanArea.addWord(wordToCheck);
// Highlight locations on board
theBoard.highlightDice(letterLocations);
wordEntryField.clear(); //clear the wordEntryField text
}
public void chideUser(String attemptedWord, String complaint) {
JOptionPane.showMessageDialog(this,
attemptedWord + ": " + complaint + "!!!",
complaint,
JOptionPane.ERROR_MESSAGE);
wordEntryField.clear(); //clear the wordEntryField text
}
/**
* Let the computer player take its turn.
*/
public void computerPlay() {
computerArea.setName("Thinking!");
computerArea.paintImmediately(computerArea.getVisibleRect());
SortedSet allWords = computerPlayer.getAllValidWords(MINIMUMWORDLENGTH);
Iterator allWordsIterator = allWords.iterator();
computerArea.setName("Computer");
while(allWordsIterator.hasNext()) {
String newWord = allWordsIterator.next();
java.util.List wordPath = computerPlayer.isOnBoard(newWord);
// Add word to appropriate score area & highlight appropriate dice
computerArea.addWord(newWord);
theBoard.highlightDice(wordPath);
// pause for a tenth of a second
// try {Thread.sleep(100); } catch (Exception e) {}
}
theBoard.unHighlightAllDice(); // leave board unhighlighted when done
}
/**
* Read word list from file with name WORDLISTFILENAME, and pass a Set
* containing those words to the computer player to intialize its lexicon.
*/
private void initLexicon() {
boolean EOF = false;
ArrayList wordsFromFile = new ArrayList ();
System.err.print("Reading word list from file " + WORDLISTFILENAME + "...");
try {
// Open File
BufferedReader input = new BufferedReader( new FileReader(WORDLISTFILENAME));
String nextWord;
while((nextWord = input.readLine()) != null)
wordsFromFile.add(nextWord.toLowerCase());
//Close the file
input.close();
} catch (FileNotFoundException fnfex ) {
JOptionPane.showMessageDialog(null,
"Unable to find word list file " + WORDLISTFILENAME, "Error",
JOptionPane.ERROR_MESSAGE);
}
catch( IOException e) {
JOptionPane.showMessageDialog(null,
"Error Opening File", "Error",
JOptionPane.ERROR_MESSAGE);
}
System.err.println(" Read " + wordsFromFile.size() + " words.");
System.err.print("Building player's lexicon... ");
computerPlayer.buildLexicon(wordsFromFile);
System.err.println("done.");
}
private void initPanels() {
Container contentPane = getContentPane();
humanArea = new ScoreArea("Me");
computerArea = new ScoreArea("Computer");
theBoard = new BoggleBoard(DICEROWS,DICECOLS,computerPlayer);
wordEntryField = new WordEntryField();
contentPane.add(wordEntryField,BorderLayout.SOUTH);
contentPane.add(humanArea, BorderLayout.WEST);
contentPane.add(theBoard, BorderLayout.CENTER);
contentPane.add(computerArea, BorderLayout.EAST);
}
private void setUpMenuBar() {
//Set Up Menu Bar
JMenuBar menu = new JMenuBar();
// Game Menu
JMenu gameMenu = new JMenu("Game");
gameMenu.setMnemonic('G');
menu.add(gameMenu);
JMenuItem newRandom = new JMenuItem("New Random");
gameMenu.add(newRandom);
newRandom.setMnemonic('N');
newRandom.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e) {
newGame(theBoard.getRandomBoard());
}});
JMenuItem customGame = new JMenuItem("New Custom");
gameMenu.add(customGame);
customGame.setMnemonic('C');
customGame.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e) {
newGame(computerPlayer.getCustomBoard());
}});
JMenuItem quitGame = new JMenuItem("Quit");
gameMenu.add(quitGame);
quitGame.setMnemonic('Q');
quitGame.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e) {
System.exit(0);
}});
// Help menu
JMenu helpMenu = new JMenu("Help");
menu.add(helpMenu);
helpMenu.setMnemonic('H');
JMenuItem aboutGame = new JMenuItem("About...");
helpMenu.add(aboutGame);
aboutGame.setMnemonic('A');
aboutGame.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e) {
JOptionPane.showMessageDialog(BoggleGUI.this,
"It's ABOUT time you got to work",
"About Game",
JOptionPane.PLAIN_MESSAGE);
}});
setJMenuBar(menu);
}
/**
* A class defining the visual appearance of a Boggle board, and
* defining some related methods.
*/
static class BoggleBoard extends JPanel {
public static final Color BACKGROUNDCOLOR = new Color(255, 219, 13);
private DiePanel theDice[][];
private Vector diceBag; // used for drawing dice for a random game
private int rows, cols;
private BogglePlayer theComputer;
BoggleBoard(int rows, int cols, BogglePlayer theComputer ) {
this.rows = rows; this.cols = cols;
this.theComputer = theComputer;
// create some dice to use when getting a random game
initDiceBag();
// create a JPanel with rowsXcols GridLayout to hold the DiePanels
JPanel innerPanel = new JPanel();
innerPanel.setLayout(new GridLayout(rows,cols,1,1));
innerPanel.setBackground(BACKGROUNDCOLOR);
// Create Individual DiePanels, and add them
theDice = new DiePanel[rows][cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
theDice[row][col] = new DiePanel();
innerPanel.add(theDice[row][col]);
}
}
innerPanel.setBorder(BorderFactory.createMatteBorder(10,10,10,10,
BACKGROUNDCOLOR));
this.add(innerPanel);
}
// fill the diceBag with the 16 "official" Boggle dice for the 4X4 game
private void initDiceBag() {
diceBag = new Vector(16);
diceBag.add(new Die("A", "O", "B", "B", "O", "J"));
diceBag.add(new Die("W", "H", "G", "E", "E", "N"));
diceBag.add(new Die("N", "R", "N", "Z", "H", "L"));
diceBag.add(new Die("N", "A", "E", "A", "G", "E"));
diceBag.add(new Die("D", "I", "Y", "S", "T", "T"));
diceBag.add(new Die("I", "E", "S", "T", "S", "O"));
diceBag.add(new Die("A", "O", "T", "T", "W", "O"));
diceBag.add(new Die("H", "Qu", "U", "M", "N", "I"));
diceBag.add(new Die("R", "Y", "T", "L", "T", "E"));
diceBag.add(new Die("P", "O", "H", "C", "S", "A"));
diceBag.add(new Die("L", "R", "E", "V", "Y", "D"));
diceBag.add(new Die("E", "X", "L", "D", "I", "R"));
diceBag.add(new Die("I", "E", "N", "S", "U", "E"));
diceBag.add(new Die("S", "F", "F", "K", "A", "P"));
diceBag.add(new Die("I", "O", "T", "M", "U", "C"));
diceBag.add(new Die("E", "H", "W", "V", "T", "R"));
}
/**
* Return an array of Strings showing the sequence of faces on
* a randomly generated board.
*/
public String[] getRandomBoard() {
// Get random faces from randomy selected dice to fill the letterList
int diceBagSize = diceBag.size();
int boardSize = rows * cols;
String[] letterList = new String[(rows * cols)];
// we try to handle any size board with a fixed diceBag
for (int i = 0; i 0) WORDLISTFILENAME = args[0];
if(args.length > 1) DICEROWS = Integer.parseInt(args[1]);
if(args.length > 2) DICECOLS = Integer.parseInt(args[2]);
if(args.length > 3) MINIMUMWORDLENGTH = Integer.parseInt(args[3]);
System.err.println("Starting " + DICEROWS + "x" + DICECOLS + " game," +
" words from " + WORDLISTFILENAME +
", min word length " + MINIMUMWORDLENGTH + ".");
(new BoggleGUI()).setVisible(true);
}
}