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){}
           }
    }
    
    
   }