Wordy.javaDenna kod är public domain. Om ni hittar fel eller vill ändra något i koden blir jag jätteglad om ni skickar dessa ändringar till jesper [at] fantasi [punkt] se.
/**
* This is the game Wordy. The computer thinks of a random five letter word,
* and your task is to guess it. To begin with, the first letter in the word is
* revealed and as you guess more letters will become visible.
* Letters in your guess that is in the right place, is copied down to the
* next line. Letters that should be in the word, but is in the wrong place,
* is marked with a circle.
*
* ToDo:
* Sound
* The bingo part
* Timeout
* Språkval bör inte köra introt om man är på titelsidan.
* Tio ord, sedan medelpoäng och avslut.
**/
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
//public class Wordy extends JApplet implements ActionListener, ItemListener
public class Wordy extends JFrame implements ActionListener, ItemListener
{
public static final long serialVersionUID = 1;
public final static int FREE = 0;
public final static int CORRECT = 1;
public final static int PLACE = 2;
public final static int WRONG = 3;
public final static Color C_FREE = new Color(50,50,255);
public final static Color C_FREE_L = new Color(100,100,255);
public final static Color C_FREE_D = new Color(0,0,150);
public final static Color C_CORRECT = new Color(50,200,50);
public final static Color C_CORRECT_L = new Color(80,230,80);
public final static Color C_CORRECT_D = new Color(0,150,0);
public final static Color C_PLACE = new Color(230,230,150);
public final static Color C_WRONG = new Color(0,0,200);
public final static Color C_WRONG_L = new Color(50,50,250);
public final static Color C_WRONG_D = new Color(0,0,150);
public final static Color C_TEXT = new Color(255,255,255);
public final static Color C_TYPE = new Color(0,0,0);
public final static ImageIcon[] ASCII = new ImageIcon[30];
private Box[][] playfield = new Box[5][5];
private boolean[] bits = new boolean[5];
private int line;
private int pos;
private int wordPoints;
private String word;
private JLabel score;
private JLabel messageBox;
private JButton button;
private Choice dictionary;
private HashSet selectableWords;
private HashSet otherWords;
private boolean wordsChanged;
private boolean textlock;
public Wordy()
{
/**
* Tell the applet to ignore the system event queue to avoid
* error messages in JDK 1.1 and JFC 1.1
*/
getRootPane().putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
}
public static void main(String[] args)
{
// This is just for debugging...
Wordy w = new Wordy();
w.setTitle("Wordy");
w.init();
}
public void init()
{
Container gameContainer = getContentPane();
gameContainer.setBackground(C_FREE);
gameContainer.setLayout(new BorderLayout());
JPanel game = new JPanel();
game.setLayout(new GridLayout(5, 5));
game.setBackground(C_FREE);
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 5; col++) {
game.add(playfield[row][col] = new Box());
}
}
JPanel upperControl = new JPanel();
upperControl.setLayout(new BorderLayout());
upperControl.add(messageBox = new JLabel(" "), "Center");
upperControl.add(dictionary = new Choice(), "East");
JPanel control = new JPanel();
control.setLayout(new BorderLayout());
control.add(new JLabel(" Score: "), "West");
control.add(score = new JLabel("0", Label.RIGHT), "Center");
control.add(upperControl, "North");
control.add(button = new JButton("Start"), "East");
gameContainer.add(game, "Center");
gameContainer.add(control, "South");
dictionary.addItem("Svenska");
dictionary.addItem("English");
dictionary.select("Svenska");
button.setEnabled(false);
dictionary.setEnabled(false);
button.addActionListener(this);
dictionary.addItemListener(this);
textlock = true;
this.addKeyListener(new WordyKeys());
setSize(278,330);
setVisible(true);
message("Loading...");
loadLetters();
message("Play ball!");
newGame();
readWords();
}
public void loadLetters()
{
for (int i = 0; i < 26; i++) {
ASCII[i] = new ImageIcon((char)(97 + i) + ".gif");
}
ASCII[26] = new ImageIcon("aa.gif");
ASCII[27] = new ImageIcon("ae.gif");
ASCII[28] = new ImageIcon("oe.gif");
ASCII[29] = new ImageIcon("blank.gif");
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == button) {
newWord();
}
}
/**
* Called when someone selects a language from the choser.
*/
public void itemStateChanged(ItemEvent e)
{
newGame();
readWords();
}
/**
* Clear the playfield and display the first letter in a new word.
*/
private void newWord()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
playfield[i][j].clear();
playfield[i][j].repaint();
}
bits[i] = false;
}
selectWord();
bits[0] = true;
playfield[0][0].setForeground(C_TEXT);
playfield[0][0].setText(word.charAt(0));
playfield[0][0].repaint();
line = 0;
pos = 0;
textlock = false;
wordPoints = 500;
message(" ");
button.setEnabled(false);
dictionary.setEnabled(false);
this.requestFocus();
}
/**
* Start a new game. Begin with showing the intro.
*/
private void newGame()
{
textlock = true;
button.setEnabled(false);
dictionary.setEnabled(false);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
playfield[i][j].clear();
playfield[i][j].repaint();
}
}
score.setText("0");
button.setText("Start");
new Thread(new IntroRunner()).start();
}
/**
* Read a dictionary file from disk.
* The dictionary is assumed to only contain five letter words.
* The first character in the file is ignored - There is one dummy
* character (\n) before each word to tell us that another word is comming.
* Selectable words are those that the game will chose from. Other
* words will be considered as good guesses, but the game will never
* pick one as the "secret" word. A line of five '-' separates
* selectable words from other words.
* Other words is the place to put "bad language" and words that may
* offend pepole, like sertain body parts or sevear illneses.
*/
private void readWords()
{
try {
String filename =
new String("wordy." + dictionary.getSelectedItem().toLowerCase() + ".dat");
BufferedReader file = new BufferedReader(new FileReader(filename));
HashSet words = selectableWords = new HashSet();
int ch = file.read();
while (ch != -1)
{
String txt = new String("");
for (int i = 0; i < 5; i++)
txt += (char)file.read();
if (txt.equals("-----"))
words = otherWords = new HashSet();
else
words.add(txt.toUpperCase());
ch = file.read();
}
file.close();
wordsChanged = false;
}
catch (IOException e) {}
}
/**
* Save the dictionary to a file.
* The file name is "wordy.<language>.dat"
*/
private void saveWords()
{
try
{
String filename =
new String("wordy." + dictionary.getSelectedItem().toLowerCase() + ".dat");
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
Iterator it = selectableWords.iterator();
while (it.hasNext())
{
String txt = (String)it.next();
file.write('\n');
for (int i = 0; i < 5; i++)
file.write(txt.charAt(i));
}
file.write('\n');
for (int i = 0; i < 5; i++)
file.write('-');
it = otherWords.iterator();
while (it.hasNext())
{
String txt = (String)it.next();
file.write('\n');
for (int i = 0; i < 5; i++)
file.write(txt.charAt(i));
}
file.close();
wordsChanged = false;
}
catch (IOException e) {}
}
/**
* Pick a word from the selectable ones.
*/
private void selectWord()
{
int which = (int)(Math.random() * selectableWords.size());
Iterator it = selectableWords.iterator();
while (which-- > 0)
{
it.next();
}
word = (String)it.next();
}
/**
* Give the player some points.
*/
private void points(int more)
{
int old = Integer.parseInt(score.getText());
score.setText(old + more + "");
}
/**
* Display a message in the status line.
*/
private void message(String mess)
{
messageBox.setText(mess);
}
/**
* Set the letter in the box currently indicated by line and pos.
*/
private void setLetter(char ch)
{
playfield[line][pos].setForeground(C_TYPE);
playfield[line][pos].setText(Character.toUpperCase(ch));
playfield[line][pos].repaint();
pos++;
if (pos == 5)
{
textlock = true;
String tmp = playfield[line][0].getChar() +
playfield[line][1].getChar() +
playfield[line][2].getChar() +
playfield[line][3].getChar() +
playfield[line][4].getChar();
new Thread(new GuessRunner(tmp.toUpperCase())).start();
}
}
/**
* Remove last letter written.
*/
private void delLetter()
{
if (pos > 0)
{
pos--;
if (bits[pos])
{
playfield[line][pos].setForeground(C_TEXT);
playfield[line][pos].setText(word.charAt(pos));
}
else
playfield[line][pos].setText(' ');
playfield[line][pos].repaint();
}
}
/**
* Compare user guess with the secret word.
*/
private void guess(String user) throws InterruptedException
{
/**
* If the word is not in the dictionary, we ask the user if it
* is a correct word (hopefully the user will answer truthfully).
*/
if (!(selectableWords.contains(user) || otherWords.contains(user)))
{
System.out.println("Is " + user + " a valid word?");
try {
char ch = (char)System.in.read();
while (System.in.read() != '\n');
if (ch != 'n')
{
selectableWords.add(user);
wordsChanged = true;
System.out.println("Added " + user + " to the dictionary");
}
else
System.out.println("Why did you write it then?");
}
catch (IOException ioe) {}
}
/**
* If the word is in the dictionary now, we send it to checkWord.
* When checkWord say 'OK', all's well. The user is politely asked
* if the new words from this session is to be saved for real.
* If the guess is wrong we step down one line. If this was the
* last line, the playfield is moved up one line and a new letter
* is revealed to the user. (Not the last free letter though.)
*/
if ((selectableWords.contains(user) || otherWords.contains(user)) && checkWord(user))
{
message("That's right!");
points(wordPoints);
if (wordsChanged)
{
System.out.println("Do you which to save new words?");
try {
char ch = (char)System.in.read();
while (System.in.read() != '\n');
if (ch != 'n')
{
saveWords();
System.out.println("Saved words");
}
}
catch (IOException ioe) {}
}
button.setText("Next Word");
button.setEnabled(true);
dictionary.setEnabled(true);
}
else
{
line++;
pos = 0;
if (line == 5)
{
int correct = 0;
line = 4;
wordPoints /= 2;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 5; j++)
playfield[i][j].copy(playfield[i + 1][j]);
for (int i = 0; i < 5; i++)
{
playfield[4][i].clear();
if (bits[i])
correct++;
}
repaint();
if (correct < 4)
{
/**
* Reveal another letter to the user
*/
for (int i = 0; i < 5; i++)
if (!bits[i])
{
bits[i] = true;
break;
}
}
}
else
wordPoints -= 100;
for (int i = 0; i < 5; i++)
{
if (bits[i])
{
playfield[line][i].setForeground(C_TEXT);
playfield[line][i].setText(word.charAt(i));
playfield[line][i].repaint();
}
}
textlock = false;
}
}
/**
* Check if the word is correct.
*/
private boolean checkWord(String guess) throws InterruptedException
{
HashSet letters = new HashSet();
int[] stats = new int[5];
int correct = 0;
/**
* We need to have all the letters to be able to see if one
* is in the wrong place.
*/
for (int i = 0; i < 5; i++)
{
letters.add(new Character(word.charAt(i)));
stats[i] = FREE;
}
for (int i = 0; i < 5; i++)
{
char ch = Character.toUpperCase(guess.charAt(i));
if (ch == word.charAt(i))
{
stats[i] = CORRECT;
bits[i] = true;
correct++;
letters.remove(new Character(ch));
}
else
stats[i] = WRONG;
}
for (int i = 0; i < 5; i++)
{
char ch = Character.toUpperCase(guess.charAt(i));
if (letters.contains(new Character(ch)))
{
stats[i] = PLACE;
letters.remove(new Character(ch));
}
}
Thread.sleep(1000);
for (int i = 0; i < 5; i++)
{
playfield[line][i].setStatus(stats[i]);
playfield[line][i].repaint();
Thread.sleep(300);
}
return correct == 5;
}
/**
* This class runs the blopp-thread that shows the guess to the user.
*/
private class GuessRunner implements Runnable
{
private String aWord;
public GuessRunner(String newWord)
{
aWord = newWord;
}
public void run()
{
try {
guess(aWord);
}
catch (InterruptedException e) {}
System.out.println("Guess runner done");
}
public void finalize()
{
System.out.println("Guess runner finalizer");
}
}
/**
* This class runs the Wordy intro.
*/
private class IntroRunner implements Runnable
{
public void run()
{
try {
Thread.sleep(500);
playfield[2][0].setForeground(Color.yellow);
playfield[2][0].setText('W');
playfield[2][0].repaint();
Thread.sleep(500);
playfield[2][1].setForeground(Color.yellow);
playfield[2][1].setText('O');
playfield[2][1].repaint();
Thread.sleep(500);
playfield[2][2].setForeground(Color.yellow);
playfield[2][2].setText('R');
playfield[2][2].repaint();
Thread.sleep(500);
playfield[2][3].setForeground(Color.yellow);
playfield[2][3].setText('D');
playfield[2][3].repaint();
Thread.sleep(500);
playfield[2][4].setForeground(Color.yellow);
playfield[2][4].setText('Y');
playfield[2][4].repaint();
Thread.sleep(1000);
for (int i = 0; i < 5; i++)
{
playfield[2][i].setStatus(CORRECT);
playfield[2][i].setForeground(C_TYPE);
playfield[2][i].repaint();
Thread.sleep(300);
}
}
catch (InterruptedException e) {}
button.setEnabled(true);
dictionary.setEnabled(true);
System.out.println("Intro runner done");
}
protected void finalize()
{
System.out.println("Intro runner finalizer");
}
}
/**
* Listen to the keyboard...
*/
private class WordyKeys extends KeyAdapter
{
public void keyTyped( KeyEvent e )
{
if (!textlock)
{
if ((int)e.getKeyChar() == 8)
delLetter();
else
setLetter(e.getKeyChar());
}
}
}
}
/**
* A box...
*/
class Box extends JLabel
{
public static final long serialVersionUID = 1;
private int status = Wordy.FREE;
private char ch = ' ';
public Box()
{
super();
setForeground(Wordy.C_TEXT);
setBorder(new BevelBorder(BevelBorder.LOWERED, Wordy.C_FREE_L, Wordy.C_FREE_D));
setHorizontalAlignment(SwingConstants.CENTER);
}
public String getChar()
{
return "" + ch;
}
public void setText(char g)
{
ch = g;
switch (g)
{
case 'Å': setIcon(Wordy.ASCII[26]); break;
case 'Ä': setIcon(Wordy.ASCII[27]); break;
case 'Ö': setIcon(Wordy.ASCII[28]); break;
case ' ': setIcon(Wordy.ASCII[29]); break;
default: setIcon(Wordy.ASCII[(int)g - 65]);
}
}
public void setStatus(int s)
{
status = s;
}
public void clear()
{
setText(' ');
status = Wordy.FREE;
setBorder(new BevelBorder(BevelBorder.LOWERED, Wordy.C_FREE_L, Wordy.C_FREE_D));
}
public void copy(Box orig)
{
status = orig.status;
setBorder(orig.getBorder());
setIcon(orig.getIcon());
}
public void paint(Graphics g)
{
switch (status)
{
case Wordy.FREE:
break;
case Wordy.CORRECT:
setBorder(new BevelBorder(BevelBorder.LOWERED, Wordy.C_CORRECT_L, Wordy.C_CORRECT_D));
g.setColor(Wordy.C_CORRECT);
g.fillRect(0,0,size().width,size().height);
break;
case Wordy.PLACE:
g.setColor(Wordy.C_PLACE);
g.fillOval(2,2,size().width - 5,size().height - 5);
break;
case Wordy.WRONG:
setBorder(new BevelBorder(BevelBorder.LOWERED, Wordy.C_WRONG_L, Wordy.C_WRONG_D));
g.setColor(Wordy.C_WRONG);
g.fillRect(0,0,size().width,size().height);
break;
}
setFont(new Font("Helvetica",Font.BOLD, (int)Math.min(size().width * 0.9, size().height * 0.9)));
super.paint(g);
}
}
|