home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magazyn Internet 2001 November
/
MICD2001_11_NR1.iso
/
Www
/
Anglomaniacy
/
WordSearch.java
< prev
next >
Wrap
Text File
|
2001-09-26
|
34KB
|
1,234 lines
/******************************************************************************
Word Search, Copyright 1999 by Mike Hall. See accompanying documentation and
license agreement.
<applet code="WordSearch.class" width=w height=h>
<param name="screencolors" value="foreground,background,border">
<param name="buttoncolors" value="foreground,background">
<param name="gridcolors" value="foreground,background,found,highlight">
<param name="listcolors" value="foreground,background,found">
<param name="screenfont" value="name,style,size">
<param name="buttonfont" value="name,style,size">
<param name="gridfont" value="name,style,size">
<param name="listfont" value="name,style,size">
<param name="gridsize" value="rows,cols,size">
<param name="files" value="url,url,url...">
</applet>
******************************************************************************/
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.applet.Applet;
/******************************************************************************
The WSWord class defines data for a single word.
******************************************************************************/
class WSWord {
// Fields:
public String list = null; // Text for word list.
public String grid = null; // Text for grid.
public Point endpt1 = null; // Starting grid location.
public Point endpt2 = null; // Ending grid location.
public boolean found = false; // Found flag.
// Constructors:
public WSWord(String s) {
String t;
int i;
char c;
this.list = s.toUpperCase();
t = new String();
for (i = 0; i < s.length(); i++) {
c = s.charAt(i);
if (Character.isLetter(c))
t += c;
}
this.grid = t.toUpperCase();
}
}
/******************************************************************************
The WSButton class defines a button.
******************************************************************************/
class WSButton {
// Fields:
public int x, y; // Screen position.
public int width, height; // Width and height.
private String text; // Text, if a text button.
private Font font; // Font for text.
private Polygon polygon; // Shape if a graphical button.
private Color fgColor = Color.black; // Foreground color.
private Color bgColor = Color.lightGray; // Background color.
private Color bdColor = Color.black; // Border color.
// Constructors:
public WSButton(String s, Font font, int width, int height) {
// Text button.
this.text = s;
this.font = font;
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
}
public WSButton(Polygon p, int width, int height) {
// Graphical button.
this.polygon = p;
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
}
public void setColors(Color fg, Color bg, Color bd) {
this.fgColor = fg;
this.bgColor = bg;
this.bdColor = bd;
}
public boolean inside(int x, int y) {
// Determine if point x, y is on the button.
if (x > this.x && x < this.x + this.width &&
y > this.y && y < this.y + this.height)
return true;
return false;
}
public void draw(Graphics g) {
FontMetrics fm;
int x, y;
// Color background and draw border.
g.setColor(this.bgColor);
g.fillRect(this.x, this.y, this.width, this.height);
g.setColor(this.bdColor);
g.drawRect(this.x, this.y, this.width - 1, this.height - 1);
// Write text or draw shape.
g.setColor(this.fgColor);
if (this.text != null) {
g.setFont(this.font);
fm = g.getFontMetrics();
x = this.x + (this.width - fm.stringWidth(this.text)) / 2;
y = this.y + (this.height + fm.getAscent()) / 2;
g.drawString(this.text, x, y);
}
if (this.polygon != null) {
x = this.x + this.width / 2;
y = this.y + this.height / 2;
g.translate(x, y);
g.fillPolygon(this.polygon);
g.translate(-x, -y);
}
}
}
/******************************************************************************
The WSGrid class defines the grid canvas.
******************************************************************************/
class WSGrid {
// Constants.
static final String LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static final int MAX = 100;
// Fields.
public int x, y; // Screen position.
public int width, height; // Width and height.
public boolean select; // Select flag.
public int startX, startY; // Selection endpoints.
public int endX, endY;
public int size; // Grid cell size.
private int rows, cols; // Grid size.
private Font font; // Font for letters.
private FontMetrics fm; // Font metrics.
private Color fgColor = Color.black; // Foreground color.
private Color bgColor = Color.white; // Background color.
private Color bdColor = Color.black; // Border color.
private Color fdColor = Color.black; // Found word color.
private Color hiColor = Color.black; // Highlighted word color.
private char[][] grid; // Letter grid.
// Constructor.
public WSGrid(int rows, int cols, int size, Font font) {
this.x = 0;
this.y = 0;
this.rows = rows;
this.cols = cols;
this.font = font;
this.size = size;
this.select = false;
// Determine width and height based on rows, cols and font.
this.width = cols * this.size;
this.height = rows * this.size;
}
public void setColors(Color fg, Color bg, Color bd, Color fd, Color hi) {
this.fgColor = fg;
this.bgColor = bg;
this.bdColor = bd;
this.fdColor = fd;
this.hiColor = hi;
}
public void clear() {
int i, j;
this.grid = new char[this.rows][this.cols];
for (i = 0; i < this.rows; i++)
for (j = 0; j < this.cols; j++)
grid[i][j] = ' ';
}
public boolean inside(int x, int y) {
// Determine if point x, y is on the button.
if (x > this.x && x < this.x + this.width &&
y > this.y && y < this.y + this.height)
return true;
return false;
}
public void fill() {
WSWord ws;
int i, j, row, col, r, c;
boolean added;
// Add each word randomly to the grid.
this.clear();
for (i = 0; i < WordSearch.words.size(); i++) {
// Get word and pick a random starting position.
ws = (WSWord) WordSearch.words.elementAt(i);
row = (int) (Math.random() * this.rows);
col = (int) (Math.random() * this.cols);
added = false;
// If word is too long to fit grid, remove it. Otherwise try adding it to
// each cell until we succeed or exhaust all possibilities.
if (ws.grid.length() <= Math.max(this.rows, this.cols)) {
r = row;
c = col;
do {
added = addWord(ws, r, c);
if (!added)
if (++c > this.cols - 1) {
c = 0;
if (++r > this.rows - 1)
r = 0;
}
} while (!added && !(r == row && c == col));
}
// If we couldn't fit it in, remove it from the list.
if (!added) {
WordSearch.words.removeElementAt(i);
i -= 1;
}
}
// Fill in rest of grid with random letters.
for (i = 0; i < this.rows; i++)
for (j = 0; j < this.cols; j++)
if (grid[i][j] == ' ') {
r = (int) (Math.random() * LETTERS.length());
grid[i][j] = LETTERS.charAt(r);
}
}
private boolean addWord(WSWord ws, int r1, int c1) {
int i, r2, c2, dx, dy, count;
boolean fit;
char c;
// Get a random direction to start with.
dy = (int) (Math.random() * 3) - 1;
dx = (int) (Math.random() * 3) - 1;
count = 0;
// Try each direction until we find a fit or exhaust all possibilities.
do {
fit = true;
r2 = r1 + (ws.grid.length() - 1) * dy;
c2 = c1 + (ws.grid.length() - 1) * dx;
if (!(dx == 00 && dy == 0) &&
r2 >= 0 && r2 < this.rows && c2 >= 0 && c2 < this.cols)
for (i = 0; i < ws.grid.length(); i++) {
c = grid[r1 + i * dy][c1 + i * dx];
if (c != ' ' && c != ws.grid.charAt(i))
fit = false;
}
else
fit = false;
if (!fit)
if (++dx > 1) {
dx = -1;
if (++dy > 1)
dy = -1;
}
count++;
} while (!fit && count <= 8);
// If we found a fit, add word and save endpoints.
if (fit) {
for (i = 0; i < ws.grid.length(); i++)
this.grid[r1 + i * dy][c1 + i * dx] = ws.grid.charAt(i);
ws.endpt1 = new Point(c1, r1);
ws.endpt2 = new Point(c2, r2);
}
return fit;
}
public boolean checkSelection() {
WSWord ws;
int x1, y1, x2, y2;
Point p1, p2;
int i;
// Check selection against word list. If endpoints match, mark it as found.
x1 = Math.min(Math.max(this.startX / this.size, 0), this.cols - 1);
y1 = Math.min(Math.max(this.startY / this.size, 0), this.rows - 1);
x2 = Math.min(Math.max(this.endX / this.size, 0), this.cols - 1);
y2 = Math.min(Math.max(this.endY / this.size, 0), this.rows - 1);
p1 = new Point(x1, y1);
p2 = new Point(x2, y2);
for (i = 0; i < WordSearch.words.size(); i++) {
ws = (WSWord) WordSearch.words.elementAt(i);
if ((ws.endpt1.equals(p1) && ws.endpt2.equals(p2)) ||
(ws.endpt1.equals(p2) && ws.endpt2.equals(p1))) {
ws.found = true;
return true;
}
}
return false;
}
public void draw(Graphics g) {
WSWord ws;
int i, j;
int k, l;
int x, y;
int x1, y1, x2, y2;
Polygon p;
Character c;
FontMetrics fm;
// Color background and draw border.
g.setColor(this.bgColor);
g.fillRect(this.x, this.y, this.width, this.height);
g.setColor(this.bdColor);
g.drawRect(this.x, this.y, this.width - 1, this.height - 1);
// Shade found words.
g.setColor(this.fdColor);
for (i = 0; i < WordSearch.words.size(); i++) {
ws = (WSWord) WordSearch.words.elementAt(i);
if (ws.found) {
x1 = this.x + this.size * ws.endpt1.x + this.size / 2;
y1 = this.y + this.size * ws.endpt1.y + this.size / 2;
x2 = this.x + this.size * ws.endpt2.x + this.size / 2;
y2 = this.y + this.size * ws.endpt2.y + this.size / 2;
p = getPolygon(x1, y1, x2, y2);
g.fillPolygon(p);
}
}
// Shade and circle current selection, if any.
if (WordSearch.words.size() > 0 && this.select) {
i = Math.min(Math.max(this.startY / this.size, 0), this.rows - 1);
j = Math.min(Math.max(this.startX / this.size, 0), this.cols - 1);
k = Math.min(Math.max(this.endY / this.size, 0), this.rows - 1);
l = Math.min(Math.max(this.endX / this.size, 0), this.cols - 1);
x1 = this.size * j + this.size / 2;
y1 = this.size * i + this.size / 2;
x2 = this.size * l + this.size / 2;
y2 = this.size * k + this.size / 2;
p = getPolygon(x1, y1, x2, y2);
g.setColor(this.hiColor);
g.fillPolygon(p);
g.setColor(this.fgColor);
g.drawPolygon(p);
g.drawLine(p.xpoints[p.npoints - 1], p.ypoints[p.npoints - 1], p.xpoints[0], p.ypoints[0]);
}
// Write letters.
g.setFont(this.font);
g.setColor(this.fgColor);
fm = g.getFontMetrics();
for (i = 0; i < this.rows; i++)
for (j = 0; j < this.cols; j++) {
c = new Character(this.grid[i][j]);
x = this.x + j * this.size + (this.size - fm.stringWidth(c.toString())) / 2;
y = this.y + i * this.size + (this.size - fm.getHeight()) / 2 + fm.getAscent();
g.drawString(c.toString(), x, y);
}
// Circle found words.
g.setColor(this.fgColor);
for (i = 0; i < WordSearch.words.size(); i++) {
ws = (WSWord) WordSearch.words.elementAt(i);
if (ws.found) {
x1 = this.x + this.size * ws.endpt1.x + this.size / 2;
y1 = this.y + this.size * ws.endpt1.y + this.size / 2;
x2 = this.x + this.size * ws.endpt2.x + this.size / 2;
y2 = this.y + this.size * ws.endpt2.y + this.size / 2;
p = getPolygon(x1, y1, x2, y2);
g.drawPolygon(p);
g.drawLine(p.xpoints[p.npoints - 1], p.ypoints[p.npoints - 1], p.xpoints[0], p.ypoints[0]);
}
}
}
private Polygon getPolygon(int x1, int y1, int x2, int y2) {
Polygon p;
double dx, dy, a, b, angle;
int r;
// Find angles.
dx = x2 - x1;
dy = y2 - y1;
a = 0;
if (dx == 0) {
if (dy < 0)
a = Math.PI / 2;
else if (dy > 0)
a = 3 * Math.PI / 2;
}
else if (dy == 0) {
if (dx > 0)
a = 0;
else
a = Math.PI;
}
else {
a = Math.atan(Math.abs(dy / dx));
if (dx < 0 && dy < 0)
a = Math.PI - a;
if (dx < 0 && dy > 0)
a += Math.PI;
if (dx > 0 && dy > 0)
a = 2 * Math.PI - a;
}
a = a + Math.PI / 2;
b = a + Math.PI;
// Build polygon as a half circle around each endpoint and connect them.
p = new Polygon();
r = (int) Math.round(this.size * Math.sin(Math.PI / 4) / 2);
for (angle = a; angle < a + Math.PI; angle += Math.PI / 30)
p.addPoint((int) Math.round(x1 + r * Math.cos(angle)),
(int) Math.round(y1 - r * Math.sin(angle)));
p.addPoint((int) Math.round(x1 + r * Math.cos(b)),
(int) Math.round(y1 - r * Math.sin(b)));
for (angle = b; angle < b + Math.PI; angle += Math.PI / 30)
p.addPoint((int) Math.round(x2 + r * Math.cos(angle)),
(int) Math.round(y2 - r * Math.sin(angle)));
p.addPoint((int) Math.round(x2 + r * Math.cos(a)),
(int) Math.round(y2 - r * Math.sin(a)));
return p;
}
}
/******************************************************************************
The WSList class defines the word list.
******************************************************************************/
class WSList {
// Fields.
public int x, y; // Screen position.
public int width, height; // Width and height.
public int scroll; // Starting word for list display.
private Font font; // Font for words.
private FontMetrics fm; // Font metrics.
private Color fgColor = Color.black; // Foreground color.
private Color bgColor = Color.white; // Background color.
private Color bdColor = Color.black; // Border color.
private Color fdColor = Color.darkGray; // Found word color.
// Constructor.
public WSList(int width, int height, Font font) {
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
this.scroll = 0;
this.font = font;
}
public void setColors(Color fg, Color bg, Color bd, Color fd) {
this.fgColor = fg;
this.bgColor = bg;
this.bdColor = bd;
this.fdColor = fd;
}
public void draw(Graphics g) {
int i;
int x, y;
Rectangle rect;
FontMetrics fm;
WSWord ws;
// Color background.
g.setColor(this.bgColor);
g.fillRect(this.x, this.y, this.width, this.height);
// Write each word in the list.
g.setFont(this.font);
fm = g.getFontMetrics();
this.scroll = Math.min(Math.max(this.scroll, 0), Math.max(WordSearch.words.size() - this.height / fm.getHeight(), 0));
x = this.x + fm.getMaxAdvance() / 2;
y = this.y + fm.getHeight();
for (i = this.scroll; i < WordSearch.words.size() && y < this.y + this.height; i++) {
ws = (WSWord) WordSearch.words.elementAt(i);
if (ws.found)
g.setColor(this.fdColor);
else
g.setColor(this.fgColor);
g.drawString(ws.list, x, y);
y += fm.getHeight();
}
// Draw border.
g.setColor(this.bdColor);
g.drawRect(this.x, this.y, this.width - 1, this.height - 1);
}
}
/******************************************************************************
Main applet code.
******************************************************************************/
public class WordSearch extends Applet implements Runnable {
// Thread control variables.
Thread loopThread; // Main thread.
// Constants
static final int DELAY = 50; // Milliseconds between screen updates.
static final int INIT = 1; // Game states.
static final int PLAY = 2;
static final int OVER = 3;
// Parameters and defaults.
Color scrnFgColor = Color.black; // Background color.
Color scrnBgColor = Color.white; // Foreground color.
Color scrnBdColor = Color.black; // Border color.
String scrnFontStr = "Helvetica,bold,12"; // Font.
Color bttnFgColor = Color.black; // Button background color.
Color bttnBgColor = Color.lightGray; // Button foreground color.
String bttnFontStr = "Dialog,bold,10"; // Button font.
Color gridFgColor = Color.black; // Grid text color.
Color gridBgColor = Color.white; // Grid background color.
Color gridHiColor = Color.yellow; // Grid highlight color.
Color gridFdColor = Color.lightGray; // Grid found color.
String gridFontStr = "Courier,plain,14"; // Grid font.
Color listFgColor = Color.black; // List text color.
Color listBgColor = Color.white; // List background color.
Color listFdColor = Color.lightGray; // List found color.
String listFontStr = "Helvetica,plain,12"; // List font.
int gridRows = 15; // Grid rows.
int gridCols = 15; // Grid columns.
int gridSize = 20; // Grid cell size.
Vector files = new Vector(); // List if text file URLs.
// Global variables.
static Vector words; // Word list.
Font scrnFont; // Screen font.
Font bttnFont; // Screen font.
Font gridFont; // Grid font.
Font listFont; // List font.
// Display elements.
WSGrid grid;
WSList list;
WSButton newGame;
WSButton solveGame;
WSButton scrollUp;
WSButton scrollDn;
// File data.
int fileNum;
// Game data.
int gap = 4; // Gap between display elements.
int gameState; // Game state.
int scroll; // Scroll direction.
int count; // Number of words found.
long startTime; // Start time of current game.
String timeText; // Elapsed time text.
String statText; // Words found/total text.
String subjText; // Word list subject, from file.
// Values for the off-screen and scratch image.
Dimension offDimension;
Image offImage;
Graphics offGraphics;
// Applet information.
public String getAppletInfo() {
return("Word Search\n\nCopyright 1999 by Mike Hall");
}
public void init() {
Graphics g;
Dimension d;
Font f;
FontMetrics fm;
String s;
StringTokenizer st;
int n;
Polygon p;
int x, y;
int w, h;
// Take credit.
System.out.println("Word Search, Copyright 1999 by Mike Hall.");
// Get colors.
try {
s = getParameter("screencolors");
if (s != null) {
st = new StringTokenizer(s, ",");
scrnFgColor = getColorParm(st.nextToken());
scrnBgColor = getColorParm(st.nextToken());
scrnBdColor = getColorParm(st.nextToken());
}
}
catch (Exception e) {}
try {
s = getParameter("buttoncolors");
if (s != null) {
st = new StringTokenizer(s, ",");
bttnFgColor = getColorParm(st.nextToken());
bttnBgColor = getColorParm(st.nextToken());
}
}
catch (Exception e) {}
try {
s = getParameter("gridcolors");
if (s != null) {
st = new StringTokenizer(s, ",");
gridFgColor = getColorParm(st.nextToken());
gridBgColor = getColorParm(st.nextToken());
gridFdColor = getColorParm(st.nextToken());
gridHiColor = getColorParm(st.nextToken());
}
}
catch (Exception e) {}
try {
s = getParameter("listcolors");
if (s != null) {
st = new StringTokenizer(s, ",");
listFgColor = getColorParm(st.nextToken());
listBgColor = getColorParm(st.nextToken());
listFdColor = getColorParm(st.nextToken());
}
}
catch (Exception e) {}
// Get fonts.
scrnFont = getFontParm(scrnFontStr);
try {
s = getParameter("screenfont");
if (s != null)
if ((f = getFontParm(s)) != null)
scrnFont = f;
}
catch (Exception e) {}
bttnFont = getFontParm(bttnFontStr);
try {
s = getParameter("buttonfont");
if (s != null)
if ((f = getFontParm(s)) != null)
bttnFont = f;
}
catch (Exception e) {}
gridFont = getFontParm(gridFontStr);
try {
s = getParameter("gridfont");
if (s != null)
if ((f = getFontParm(s)) != null)
gridFont = f;
}
catch (Exception e) {}
listFont = getFontParm(listFontStr);
try {
s = getParameter("listfont");
if (s != null)
if ((f = getFontParm(s)) != null)
listFont = f;
}
catch (Exception e) {}
// Get grid size.
try {
s = getParameter("gridsize");
if (s != null) {
st = new StringTokenizer(s, ",");
if ((n = Integer.parseInt(st.nextToken())) > 0)
gridRows = n;
if ((n = Integer.parseInt(st.nextToken())) > 0)
gridCols = n;
if ((n = Integer.parseInt(st.nextToken())) > 0)
gridSize = n;
}
}
catch (Exception e) {}
// Get list of word file URLs.
try {
s = getParameter("files");
if (s != null) {
st = new StringTokenizer(s, ",");
while (st.hasMoreTokens())
files.addElement(st.nextToken());
}
}
catch (Exception e) {}
// Get screen size and build display.
g = getGraphics();
d = size();
// Create and position grid.
grid = new WSGrid(gridRows, gridCols, gridSize, gridFont);
grid.setColors(gridFgColor, gridBgColor, scrnBdColor, gridFdColor, gridHiColor);
grid.clear();
// Create and position list.
g.setFont(listFont);
fm = g.getFontMetrics();
x = grid.x + grid.width + gap;
w = d.width - x;
h = grid.height - 2 * (fm.getHeight() + gap);
list = new WSList(w, h, listFont);
list.x = x;
list.y = grid.y + fm.getHeight() + gap;
list.setColors(listFgColor, listBgColor, scrnBdColor, listFdColor);
// Create and position scroll buttons.
g.setFont(bttnFont);
w = list.width;
h = fm.getHeight();
p = new Polygon();
p.addPoint(0, -h / 2 + 2);
p.addPoint(-fm.getMaxAdvance() / 2, h / 2 - 2);
p.addPoint(fm.getMaxAdvance() / 2, h / 2 - 2);
scrollUp = new WSButton(p, w, h);
scrollUp.x = list.x;
scrollUp.y = grid.y;
scrollUp.setColors(bttnFgColor, bttnBgColor, scrnBdColor);
p = new Polygon();
p.addPoint(0, h / 2 - 2);
p.addPoint(-fm.getMaxAdvance() / 2, -h / 2 + 2);
p.addPoint(fm.getMaxAdvance() / 2, -h / 2 + 2);
scrollDn = new WSButton(p, w, h);
scrollDn.x = list.x;
scrollDn.y = list.y + list.height + gap;
scrollDn.setColors(bttnFgColor, bttnBgColor, scrnBdColor);
// Create and position text buttons.
g.setFont(bttnFont);
fm = g.getFontMetrics();
s = "New Game";
w = fm.stringWidth(s) + fm.getMaxAdvance();
h = 3 * fm.getHeight() / 2;
newGame = new WSButton(s, bttnFont, w, h);
x = 0;
y = d.height - h;
newGame.x = x;
newGame.y = y;
newGame.setColors(bttnFgColor, bttnBgColor, scrnBdColor);
s = "Solve Game";
x = x + w + gap;
w = fm.stringWidth(s) + fm.getMaxAdvance();
solveGame = new WSButton(s, bttnFont, w, h);
solveGame.x = x;
solveGame.y = y;
solveGame.setColors(bttnFgColor, bttnBgColor, scrnBdColor);
// Initialize game data.
fileNum = 0;
scroll = 0;
timeText = "";
statText = "";
subjText = "";
words = new Vector();
grid.fill();
endGame();
gameState = INIT;
}
public Color getColorParm(String s) {
int r, g, b;
// Check if a pre-defined color is specified.
if (s.equalsIgnoreCase("black"))
return(Color.black);
if (s.equalsIgnoreCase("blue"))
return(Color.blue);
if (s.equalsIgnoreCase("cyan"))
return(Color.cyan);
if (s.equalsIgnoreCase("darkGray"))
return(Color.darkGray);
if (s.equalsIgnoreCase("gray"))
return(Color.gray);
if (s.equalsIgnoreCase("green"))
return(Color.green);
if (s.equalsIgnoreCase("lightGray"))
return(Color.lightGray);
if (s.equalsIgnoreCase("magenta"))
return(Color.magenta);
if (s.equalsIgnoreCase("orange"))
return(Color.orange);
if (s.equalsIgnoreCase("pink"))
return(Color.pink);
if (s.equalsIgnoreCase("red"))
return(Color.red);
if (s.equalsIgnoreCase("white"))
return(Color.white);
if (s.equalsIgnoreCase("yellow"))
return(Color.yellow);
// If the color is specified in HTML format, build it from the red, green
// and blue values.
if (s.length() == 7 && s.charAt(0) == '#') {
r = Integer.parseInt(s.substring(1,3),16);
g = Integer.parseInt(s.substring(3,5),16);
b = Integer.parseInt(s.substring(5,7),16);
return(new Color(r, g, b));
}
// If we can't figure it out, default to black.
return(Color.black);
}
public Font getFontParm(String s) {
String t, fontName;
StringTokenizer st;
int n, fontStyle, fontSize;
fontName = "";
fontStyle = -1;
fontSize = -1;
// Parse font name.
st = new StringTokenizer(s, ",");
t = st.nextToken();
if (t.equalsIgnoreCase("Courier"))
fontName = "Courier";
else if (t.equalsIgnoreCase("Dialog"))
fontName = "Dialog";
else if (t.equalsIgnoreCase("Helvetica"))
fontName = "Helvetica";
else if (t.equalsIgnoreCase("Symbol"))
fontName = "Symbol";
else if (t.equalsIgnoreCase("TimesRoman"))
fontName = "TimesRoman";
// Parse font style.
t = st.nextToken();
if (t.equalsIgnoreCase("plain"))
fontStyle = Font.PLAIN;
else if (t.equalsIgnoreCase("bold"))
fontStyle = Font.BOLD;
else if (t.equalsIgnoreCase("italic"))
fontStyle = Font.ITALIC;
else if (t.equalsIgnoreCase("boldItalic"))
fontStyle = Font.BOLD + Font.ITALIC;
// Parse font size.
t = st.nextToken();
if ((n = Integer.parseInt(t)) > 0)
fontSize = n;
// Return the specified font.
if (fontName != "" && fontStyle >= 0 && fontSize >= 0)
return(new Font(fontName, fontStyle, fontSize));
// If we can't figure it out, return a null value.
return (Font) null;
}
public void start() {
if (loopThread == null) {
loopThread = new Thread(this);
loopThread.start();
}
}
public void stop() {
if (loopThread != null) {
loopThread.stop();
loopThread = null;
}
}
public void run() {
long threadTime;
Date date;
String mm, ss;
// Lower this thread's priority and get the current time.
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
threadTime = System.currentTimeMillis();
// This is the main loop.
while (Thread.currentThread() == loopThread) {
// Scroll word list.
list.scroll += scroll;
// Update game time.
if (gameState == PLAY) {
date = new Date(System.currentTimeMillis() - startTime);
mm = (new Integer(date.getMinutes())).toString();
ss = (new Integer(date.getSeconds())).toString();
if (mm.length() < 2)
mm = "0" + mm;
if (ss.length() < 2)
ss = "0" + ss;
timeText = "Time: " + mm + ":" + ss;
statText = "Found: " + count + "/" + words.size();
}
// Update the screen and set the timer for the next loop.
repaint();
try {
threadTime += DELAY;
Thread.sleep(Math.max(0, threadTime - System.currentTimeMillis()));
}
catch (InterruptedException e) {
break;
}
}
}
public boolean mouseDown(Event e, int x, int y) {
// Check buttons.
if (newGame.inside(x, y))
initGame();
if (gameState == PLAY && solveGame.inside(x, y))
solveGame();
if (gameState != INIT && scrollUp.inside(x, y))
scroll = -1;
if (gameState != INIT && scrollDn.inside(x, y))
scroll = 1;
// Check grid.
if (gameState == PLAY && grid.inside(x, y)) {
grid.select = true;
grid.startX = x;
grid.startY = y;
grid.endX = x;
grid.endY = y;
}
return true;
}
public boolean mouseDrag(Event e, int x, int y) {
if (gameState == PLAY && grid.select) {
grid.endX = x;
grid.endY = y;
}
return true;
}
public boolean mouseUp(Event e, int x, int y) {
// Stop any scrolling.
scroll = 0;
// If a selection was being made, check it.
if (gameState == PLAY && grid.select) {
grid.select = false;
if (grid.checkSelection())
if (++count >= words.size()) {
timeText += " Done!";
statText = "Found: " + count + "/" + words.size();
endGame();
}
}
return true;
}
public void initGame() {
setWords();
grid.select = false;
grid.fill();
list.scroll = 0;
count = 0;
startTime = System.currentTimeMillis();
timeText = "";
statText = "";
gameState = PLAY;
}
public void solveGame() {
WSWord ws;
int i;
// Mark all words as found.
for (i = 0; i < words.size(); i++) {
ws = (WSWord) words.elementAt(i);
ws.found = true;
}
count = words.size();
timeText = "Cheated!";
endGame();
}
public void endGame() {
gameState = OVER;
}
public void setWords() {
String s;
URL url;
InputStream in;
DataInputStream ds;
// Clear word list.
words.removeAllElements();
// Get next file URL.
if (fileNum >= files.size())
fileNum = 0;
s = (String) files.elementAt(fileNum);
url = (URL) null;
try {
url = new URL(getDocumentBase(), s);
}
catch (Exception e) {}
fileNum++;
// Open it up and read list of words.
subjText = "";
try {
in = url.openStream();
ds = new DataInputStream(in);
while((s = ds.readLine()) != null)
if (s.startsWith("#"))
subjText = "'" + s.substring(1) + "'";
else
words.addElement(new WSWord(s));
}
catch (IOException e) {}
}
public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
Dimension d = size();
FontMetrics fm;
String s1, s2;
int x, y;
int w, h;
// Create the offscreen graphics context, if no good one exists.
if (offGraphics == null || d.width != offDimension.width || d.height != offDimension.height) {
offDimension = new Dimension(d.width, d.height);
offImage = createImage(d.width, d.height);
offGraphics = offImage.getGraphics();
}
// Color background.
offGraphics.setColor(scrnBgColor);
offGraphics.fillRect(0, 0, d.width, d.height);
// Draw elements.
grid.draw(offGraphics);
list.draw(offGraphics);
scrollUp.draw(offGraphics);
scrollDn.draw(offGraphics);
newGame.draw(offGraphics);
solveGame.draw(offGraphics);
// Display title, messages, etc. as appropriate.
offGraphics.setColor(scrnFgColor);
offGraphics.setFont(scrnFont);
fm = offGraphics.getFontMetrics();
if (gameState == INIT) {
x = (grid.x + grid.width) / 2;
y = (grid.y + grid.height) / 2;
s1 = "Word Search";
s2 = "Copyright 1999 by Mike Hall";
w = Math.max(fm.stringWidth(s1), fm.stringWidth(s2)) + 2 * fm.getMaxAdvance();
h = 5 * fm.getHeight();
offGraphics.setColor(gridFgColor);
offGraphics.fillRect(x - w / 2, y - h / 2, w, h);
offGraphics.setColor(gridBgColor);
offGraphics.drawRect(x - w / 2 + 1, y - h / 2 + 1, w - 3, h - 3);
offGraphics.drawString(s1, x - fm.stringWidth(s1) / 2, y - h / 2 + 2 * fm.getHeight());
offGraphics.drawString(s2, x - fm.stringWidth(s2) / 2, y + h / 2 - fm.getHeight() - fm.getDescent());
}
x = (grid.x + grid.width - fm.stringWidth(subjText)) / 2;
y = grid.y + grid.height + fm.getHeight();
offGraphics.drawString(subjText, x, y);
s1 = timeText;
x = Math.min(d.width - fm.stringWidth(s1), list.x);
offGraphics.drawString(s1, x, y);
s1 = statText;
x = Math.min(d.width - fm.stringWidth(s1), list.x);
y += fm.getHeight();
offGraphics.drawString(s1, x, y);
// Copy the off-screen buffer to the screen.
g.drawImage(offImage, 0, 0, this);
}
}