Source Code
Wordfind.java
/* Code Copyright(C)1998 Gervase Gallant 3430 Forest Ave. Des Moines IA 50311 email: ggallant@dwx.com */
import java.awt.*; import java.applet.*; import java.util.Vector; import java.util.Hashtable;
public class Wordfind extends Applet implements java.awt.event.MouseListener,java.awt.event.ActionListener
{
private Label[] mines = null;
private final int square = 12;
private final int NUM_LABELS = square * square;
private final int NUM_WORDS_IN_PUZZLE = 4;
private Button button = null;
private Panel minepanel = null;
private Vector selectedLabels = new Vector();
private String[] solution = null;
private String wordlist = null;
private Hashtable words = null;
private Hashtable selectedWords = null;
private AudioClip sound = null;
//compass type constants
private final int NORTH = -square; // eg., if square= 12, then -12
private final int SOUTH = square;
private final int WEST = -1;
private final int EAST = 1;
private final int NE = -square + 1;
private final int NW = -square - 1;
private final int SE = square + 1;
private final int SW = square - 1;
private Label[] captions = null;
private Adorn aEmbellish = null;
private final Color SELECTED_COLOR = Color.pink;
private final Color BACKGROUND_COLOR = Color.lightGray;
public void init()
{
setLayout(new BorderLayout()); this.setBackground(Color.pink); //setSize(300,300); minepanel = new Panel(new GridLayout(square,square));
this.setForeground(Color.blue); this.getLabels(); this.getWords(); this.placeWords(); this.addFillers();
Panel buttonpanel = new Panel(new BorderLayout());
button = new Button("Start");
button.addActionListener(this);
buttonpanel.add("South",button);
Panel labelpanel = new Panel(new GridLayout(0,1));
for (int j = 0;j<getCaptions().length; j++){
labelpanel.add(getCaptions()[j]);
}
buttonpanel.add("North",labelpanel);
this.add("Center", minepanel);
this.add("South", buttonpanel);
setLayout(new FlowLayout());
setSize(792,396);
this.showStatus("Ready");
//now get the sound for when someone wins
String s = this.getParameter("SOUND");
if (s !=null){
sound = this.getAudioClip(this.getDocumentBase(),s);
}
}
public void mouseClicked(java.awt.event.MouseEvent e){}
public void mouseEntered(java.awt.event.MouseEvent e){}
public void mouseExited(java.awt.event.MouseEvent e){}
public void mousePressed(java.awt.event.MouseEvent e){
Component c = (Component)e.getSource();
if (c instanceof Label){
Label l = (Label)c;
if (l.getBackground() == BACKGROUND_COLOR){
l.setBackground(SELECTED_COLOR);
}else{
l.setBackground(BACKGROUND_COLOR);
}
// this.addSelectedLabel(new Integer(l.getText()));
if (checkWin()==true){
showWin();
}
}
}
public void mouseReleased(java.awt.event.MouseEvent e){}
public void actionPerformed(java.awt.event.ActionEvent e){
if (e.getSource()==button) {
//probably start button
restart();
}
}
// *******************************************************
private boolean checkWin(){
for (int i=0;i<mines.length;i++){
if ((solution[i]==null)&& (mines[i].getBackground()==SELECTED_COLOR)){
return false;
}
else {
if ((solution[i]!=null)&& (mines[i].getBackground()!=SELECTED_COLOR)){
return false;
}
}
}
return true;
}
//****************************************
private void showWin(){
this.showStatus("You win!");
for (int i = 0;i<mines.length;i++){
if (solution[i]==null) {
mines[i].setText("");
}
}
//now play a sound, if one was specified
if (sound!=null){
sound.play();
}
}
private Label[] getLabels(){
if (mines == null){
mines = new Label[NUM_LABELS];
for (int i = 0;i <NUM_LABELS;i++){
mines[i] = new Label("",1);
mines[i].addMouseListener(this);
mines[i].setName("" + i);
minepanel.setBackground(BACKGROUND_COLOR);
minepanel.add(mines[i]);
}
//set up adornment for these labels
aEmbellish = new Adorn();
aEmbellish.setLabels(mines);
Thread aThread = new Thread(aEmbellish);
aThread.start();
}
return mines; }
private Label[] getCaptions(){
if (captions==null){
captions = new Label[NUM_WORDS_IN_PUZZLE];
for (int i = 0;i <captions.length;i++){
captions[i] = new Label("");
captions[i].setAlignment(Label.RIGHT);
}
}
return captions;
}
//**************************
private void getWords(){
int i = 0;
//words passed in ...or use default
wordlist = this.getParameter("WORDLIST");
if (wordlist ==null){
wordlist = "bison, branch,crashing,demise,gauntlet,hound,listing,memory,queue,rational,stereo,tranquil,weaver,zesty,blister,vanish,idiotic,range,scream,smile,spoof";
}
wordlist = wordlist.toUpperCase();
java.util.StringTokenizer st = new java.util.StringTokenizer(wordlist,",");
words = new Hashtable(st.countTokens());
while (st.hasMoreElements()){
words.put(new String(String.valueOf(i)), st.nextToken());
i++;
}
}
//*****************************
private void placeWords(){
//clear solution
solution = new String[NUM_LABELS];
String selectedWord = new String("");
//prepare selectedWords
selectedWords = new Hashtable(NUM_WORDS_IN_PUZZLE);
for (int i = 0; i<NUM_WORDS_IN_PUZZLE;i++){
boolean flag = false;
//don't add it to the selection if it's already there!!
while(flag==false){
//where to start
int pos = (int)(java.lang.Math.random()*words.size());
selectedWord = (String)words.get(String.valueOf(pos));
if (selectedWords.contains(selectedWord) == false){
flag = true;
}
}
char[] thisword = selectedWord.toCharArray();
//System.out.println(selectedWord + " ************************************");
int looped = 0;
//the direction should be randomly selected:
int[] directions = {NORTH,SOUTH,EAST,WEST,SW,SE,NE,NW};
while (looped < 50){ //presume unfittable word beyond this...
//try to position the word in the solution array
int startpos = (int)(java.lang.Math.random()* (square*square));
int direction = (int)(java.lang.Math.random() * directions.length);
if (this.tryToFit(directions[direction], thisword, startpos)) {
//the word was placed!! So announce it
captionPuzzle(selectedWord);
break; //out of while loop
}
looped++;
}
}
}
//******************************
private void addFillers(){
//add any old filler text to labels with no text
for (int i = 0;i <NUM_LABELS;i++){
if (solution[i]==null){
mines[i].setText(this.getRandomLetter());
//mines[i].setText("-"); //TEST
}else{
mines[i].setText(solution[i]);
}
}
}
// ***********************
private void clearLabels(){
//add any old filler text to labels with no text
for (int i = 0;i <NUM_LABELS;i++){
mines[i].setText("");
mines[i].setBackground(BACKGROUND_COLOR);
}
//now clear the captions
for (int j = 0;j<NUM_WORDS_IN_PUZZLE;j++){
getCaptions()[j].setText("");
}
}
private void addSelectedLabel(Integer i){
selectedLabels.addElement(i);
}
//***********************************
private String getRandomLetter(){
String pick = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int spot = (int)(java.lang.Math.random() * 26);
String ret = pick.substring(spot,spot+1);
return ret; }
//****************************
private synchronized void restart(){
this.showStatus("Ready!");
this.getWords(); this.clearLabels(); this.placeWords(); this.addFillers(); }
//***************************
private boolean tryToFit(int increment, char[] what, int startPos){
int charLength = what.length ;
int newPos = startPos;
for (int i = 0; i<charLength; i++){
try{
// at this position
if ((solution[newPos]==null)||(solution[newPos].equals(String.valueOf(what[i])))){
//solution matrix must be null or same as the character
//dont worry about boundary on last char...
if ((!isBoundaryOK(newPos,increment)) || (i== charLength )){
return false;
}
//check another position in increment direction newPos = newPos + increment ;
}
else{
// oh oh, roadblock! try another direction...
return false;
}
}catch (Exception e){
return false; //end of the road!
}
}
// if we got this far, we can position the char array in this direction
int charPos = startPos;
for (int q = 0; q<charLength; q++ ){
solution[charPos] = String.valueOf(what[q]);
charPos = charPos + increment ;
} return true ; }
//***************************************
private void captionPuzzle(String what){
if (selectedWords !=null){
selectedWords.put(what,what);
}
//find an empty spot in the captions labels
for (int i = 0;i<getCaptions().length; i++){
if (getCaptions()[i].getText().length()==0){
getCaptions()[i].setText(what);
return;
}
}
}
/* this routine checks to see that a char the boundary of the grid
doesn't try to write itself in the wrong place
ie, xxxh
tabx
xxxx
*note how the word bath is written if moving EAST
You can call this routine for all but the LAST char
*/
private boolean isBoundaryOK(int newPos,int direction){
switch (direction){
case NORTH:
if (newPos <square){
return false;
}
return true;
case SOUTH:
if (newPos + square >(square * square)){
return false;
}
return true;
case EAST:
//System.out.println("East" + newPos + " " + square);
if ( java.lang.Math.IEEEremainder(newPos+1,square)== 0){
return false;
}
case WEST:
//System.out.println("West" + newPos + " " + square);
if ( java.lang.Math.IEEEremainder(newPos,square)== 0){
return false;
}
return true;
case NE:
if (newPos <square){//same as north
return false;
}
//System.out.println(" NE:" + newPos + " " + square);
if ( java.lang.Math.IEEEremainder(newPos+1,square)== 0){ //same rule as East
return false;
}
//System.out.println("true");
return true;
case SE:
if (newPos + square >(square * square)){//same as south
return false;
}
//System.out.println("SE:" + newPos + " " + square);
if ( java.lang.Math.IEEEremainder(newPos+1,square)== 0){ //same rule as East
return false;
}
//System.out.println("true");
return true;
case SW:
if (newPos + square >(square * square)){ //Same as south
return false;
}
//System.out.println("SW " + newPos + " " + square);
if ( java.lang.Math.IEEEremainder(newPos,square)== 0){//like west
return false;
}
//System.out.println("true");
return true;
case NW:
if (newPos <square){//same as north
return false;
}
//System.out.println("NW " + newPos + " " + square);
if ( java.lang.Math.IEEEremainder(newPos,square)== 0){ //like west rule
return false;
}
//System.out.println("true");
return true;
default:
break ;
}
return false;
}
}
Adorn.java
//causes the letters to change color...
import java.lang.*;
import java.awt.Color;
public class Adorn extends Object implements Runnable{
private java.awt.Label[] labelArray = null;
private Color[] foreColors = {Color.magenta,Color.red,Color.cyan,Color.black};
public void setLabels(java.awt.Label[] l){
this.labelArray = l;
}
public void run(){
while (true){
try{
int myColor = (int)(java.lang.Math.random() * foreColors.length );
Color thisColor = foreColors[myColor];
int currentLabel = (int)(java.lang.Math.random() * labelArray.length );
labelArray[currentLabel].setForeground(thisColor);
synchronized(this){ //lock it while doing this..
String text = labelArray[currentLabel].getText();
labelArray[currentLabel].setText(text);
}
Thread.currentThread().sleep(1000);
} catch (Exception e){}
}
}
}