/* This simple extension of the java.awt.Frame class contains all the elements necessary to act as the main window of an application. */ import pilot.java.dev.*; import java.awt.*; import java.io.*; import java.util.*; public class Boggle extends Frame { void compressWords() { int i,l1,l2,j,count=0; String s,ps=null; byte[] b=new byte[25]; StringBuffer sb = new StringBuffer(20000); int c1,c2,c3; try { CreatePDB pdb = new CreatePDB("Dictionary",(short)0,(short)1,0,"Data","Dict", 4000,0); String three=null,pthree=null; // WordCount = 30000; for (i=0;i<676*26;i++) { if (index3[i] != 0) { c1 = i/676; c2 = (i-c1*676)/26; c3 = (i-c1*676-c2*26); sb.append((char)(c1+'a')); sb.append((char)(c2+'a')); sb.append((char)(c3+'a')); } } pdb.addRecord(new PDBRecord(0,new String(sb.toString()))); sb.setLength(0); for (i=0;i 2) { //worth it to compress count += j+1; b[j] |= ((byte)(j-2)<<5); } else { j = 0; b[j] |= 0xe0; } } else { j = 0; b[j] |= 0xe0; } sb.append(new String(b,0,j,Lengths[i]-j)); ps = s; } sb.append((char)0xff); c1 = ((int)three.charAt(0)-'a')*676; c2 = ((int)three.charAt(1)-'a')*26; c3 = ((int)three.charAt(2)-'a'); pdb.addRecord(new PDBRecord(c1+c2+c3,sb.toString())); pdb.writePDB("dict.pdb"); Status.setText("#bytes saved: "+count); } catch (Exception e) { Status.setText("Error writing dict.cmp"); } finally { } } void Compress_Action(Event event) { // to do: place event handler code here. FileDialog fd = new FileDialog(this,"Select dictionary file",FileDialog.LOAD); fd.setFile("dict"); fd.show(); String fn = fd.getDirectory()+fd.getFile(); if (!dictReady) { dictReady = true; readAllData(); } Compressor c = new Compressor(this); } void Input_Action(Event event) { // to do: place event handler code here. Status.setText(""); if (!dictReady) { dictReady = true; readAllData(); } Letters = ""; Puzzle.setText(""); String s = Input.getText(); char c; int r=0; StringTokenizer st = new StringTokenizer(s); while (st.hasMoreTokens()) { s = st.nextToken(); if (s.length() != 5) { Status.setText("Error in input"); return; } for (int i=0;i<5;i++) { c = Character.toLowerCase(s.charAt(i)); Letters += c; Puzzle.appendText(" "+c); } Puzzle.appendText("\n"); r++; } if (r != 5) { Status.setText("Error in input"); return; } PuzzleGenerator g = new PuzzleGenerator(this); } void New_Action(Event event) { // to do: place event handler code here. Status.setText(""); if (!dictReady) { dictReady = true; readAllData(); } generateGame(); PuzzleGenerator g = new PuzzleGenerator(this); } static Enumeration Sort(Hashtable h) { int n=h.size(); Vector v = new Vector(n); Enumeration e = h.elements(); String t; while (e.hasMoreElements()) { v.addElement(e.nextElement()); } int incr = n/2; while (incr >= 1) { for (int i=incr;i= incr && t.compareTo((String)v.elementAt(j-incr)) < 0) { v.setElementAt(v.elementAt(j-incr),j); j -= incr; } v.setElementAt(t,j); } incr /= 2; } return v.elements(); } void readAllData() { File f=null; FileInputStream fis=null; DataInputStream dis=null; int len,i,j,k,count=0; try { fis = new FileInputStream("index"); dis = new DataInputStream(fis); WordCount = dis.readInt(); Lengths = new int[WordCount]; Words = new int[WordCount]; for (i=0;i<26*26;i++) index2[i] = dis.readInt(); for (i=0;i<26*26*26;i++) { index3[i] = dis.readInt(); if (index3[i] == 0) count++; } Status.setText("Unused keys: "+count); dis.close(); f = new File("dict"); fis = new FileInputStream("dict"); dis = new DataInputStream(fis); len = (int)f.length(); dict = new byte[len]; dis.readFully(dict,0,len); dis.close(); j = 0; k = 0; String s; for (i=0;i b) { idx++; continue WordLoop; } if (c < b) return 2; } b = dict[c2]; if (b == '\n') return 0; return 1; } return 2; } int worthContinuing(int wi) { int c1,c2,c3,i; c1 = word[0]-'a'; c2 = word[1]-'a'; i = c1*26+c2; if (index2[i] != 0) if (wi >= 3) { c3 = word[2]-'a'; i = i*26+c3; return index3[i]; } else return index2[i]; return 0; } void genWords() { Hashtable table = new Hashtable(1000); int score=0; int wi=0; int idx=0; boolean more=true; int flags[] = new int[25]; int stack[] = new int[25]; int start = 0,result,sc; boolean check=true; char c; String s,s2; String blanks = " "; stack[idx] = 0; flags[0] = 1 | used; WordList.setText(""); while (more) { if (check) { c = Letters.charAt(stack[idx]); word[wi++] = (byte)c; if (c == 'q') word[wi++] = 'u'; result = checkWord(wi); if (result == 0) { s = new String(word,0,0,wi); if (!table.contains(s)) { table.put(s,s); } } else if (result == 2) { wi--; if (Letters.charAt(stack[idx]) == 'q') wi--; flags[stack[idx]] = 0; idx--; } } check = true; switch (flags[stack[idx]] & ~used) { case 1: flags[stack[idx]] = 2 | used; if (stack[idx] > 4 && (flags[stack[idx]-5] & used) == 0 ) { stack[idx+1] = stack[idx]-5; idx++; flags[stack[idx]] = 1 | used; continue; } case 2: flags[stack[idx]] = 3 | used; if (stack[idx] % 5 != 4 && (flags[stack[idx]+1] & used) == 0 ) { stack[idx+1] = stack[idx]+1; idx++; flags[stack[idx]] = 1 | used; continue; } case 3: flags[stack[idx]] = 4 | used; if (stack[idx] < 20 && (flags[stack[idx]+5] & used) == 0 ) { stack[idx+1] = stack[idx]+5; idx++; flags[stack[idx]] = 1 | used; continue; } case 4: flags[stack[idx]] = 5 | used; if (stack[idx] % 5 != 0 && (flags[stack[idx]-1] & used) == 0 ) { stack[idx+1] = stack[idx]-1; idx++; flags[stack[idx]] = 1 | used; continue; } case 5: flags[stack[idx]] = 6 | used; if (stack[idx] > 4 && stack[idx] % 5 != 4 && (flags[stack[idx]-4] & used) == 0 ) { stack[idx+1] = stack[idx]-4; idx++; flags[stack[idx]] = 1 | used; continue; } case 6: flags[stack[idx]] = 7 | used; if (stack[idx] < 20 && stack[idx] % 5 != 4 && (flags[stack[idx]+6] & used) == 0 ) { stack[idx+1] = stack[idx]+6; idx++; flags[stack[idx]] = 1 | used; continue; } case 7: flags[stack[idx]] = 8 | used; if (stack[idx] < 20 && stack[idx] % 5 != 0 && (flags[stack[idx]+4] & used) == 0 ) { stack[idx+1] = stack[idx]+4; idx++; flags[stack[idx]] = 1 | used; continue; } case 8: flags[stack[idx]] = 0 | used; if (stack[idx] > 4 && stack[idx] % 5 != 0 && (flags[stack[idx]-6] & used) == 0 ) { stack[idx+1] = stack[idx]-6; idx++; flags[stack[idx]] = 1 | used; continue; } case 0: if (idx > 0) { wi--; if (Letters.charAt(stack[idx]) == 'q') wi--; flags[stack[idx]] = 0; idx--; check = false; continue; } //check next starting point start++; wi = 0; if (start == 25) more = false; else { for (int i=0;i<25;i++) flags[i] = 0; idx = 0; stack[0] = start; flags[start] = 1 | used; } break; } } Enumeration e = Sort(table); StringBuffer sb = new StringBuffer(table.size()*7); while (e.hasMoreElements()) { s = (String)e.nextElement(); sc = (int)Math.pow(2,s.length()-4); s2 = ""+sc; sb.append(blanks.substring(s2.length())+sc+" "+s+"\n"); score += sc; } Status.setText("#words: "+table.size()+",score="+score); WordList.setText(sb.toString()); } void generateGame() { int i,j,t; Random r; r = new Random(); for (i=0;i<25;i++) Board[i] = i; for (i=0;i<25;i++) { j = r.nextInt(); if (j < 0) j = -j; j = j % 25; if (i != j) { t = Board[i]; Board[i] = Board[j]; Board[j] = t; } } Letters = ""; Puzzle.setText(""); for (i=0;i<25;i++) { j = r.nextInt(); if (j < 0) j = -j; j = j % 6; Letters += Character.toLowerCase(Cubes[Board[i]].charAt(j)); Puzzle.appendText(" "+Character.toUpperCase(Letters.charAt(i))); if ((i % 5) == 4) Puzzle.appendText("\n"); } } void ImportDictionary_Action(Event event) { // to do: place event handler code here. new processDictionary(this); } void About_Action(Event event) { //{{CONNECTION // Action from About Create and show as modal (new AboutDialog(this, true)).show(); //}} } void Exit_Action(Event event) { //{{CONNECTION // Action from Exit Create and show as modal (new QuitDialog(this, true)).show(); //}} } public Boggle() { //{{INIT_CONTROLS setLayout(null); addNotify(); resize(insets().left + insets().right + 405,insets().top + insets().bottom + 479); openFileDialog1 = new java.awt.FileDialog(this, "Open",FileDialog.LOAD); //$$ openFileDialog1.move(37,277); Status = new java.awt.TextField(); Status.setEditable(false); Status.reshape(insets().left + 71,insets().top + 13,314,22); add(Status); label1 = new java.awt.Label("Status:",Label.RIGHT); label1.reshape(insets().left + 9,insets().top + 13,55,21); add(label1); WordList = new java.awt.TextArea(); WordList.reshape(insets().left + 210,insets().top + 44,189,428); add(WordList); Puzzle = new java.awt.TextArea(); Puzzle.reshape(insets().left + 11,insets().top + 47,186,225); Puzzle.setFont(new Font("Courier", Font.BOLD, 24)); add(Puzzle); Input = new java.awt.TextArea(); Input.reshape(insets().left + 10,insets().top + 313,184,135); Input.setFont(new Font("Courier", Font.BOLD, 12)); add(Input); setTitle("A Basic Application"); //}} //{{INIT_MENUS mainMenuBar = new java.awt.MenuBar(); menu1 = new java.awt.Menu("File"); menu1.add("Import Dictionary"); menu1.addSeparator(); menu1.add("Compress"); menu1.add("Exit"); mainMenuBar.add(menu1); menu2 = new java.awt.Menu("Game"); menu2.add("New"); menu2.add("Quit"); menu2.addSeparator(); menu2.add("Input"); menu2.addSeparator(); menu2.add("Generate"); mainMenuBar.add(menu2); menu3 = new java.awt.Menu("Help"); mainMenuBar.setHelpMenu(menu3); menu3.add("About"); mainMenuBar.add(menu3); setMenuBar(mainMenuBar); //$$ mainMenuBar.move(4,277); //}} } public Boggle(String title) { this(); setTitle(title); } public synchronized void show() { move(50, 50); super.show(); } public boolean handleEvent(Event event) { if (event.id == Event.WINDOW_DESTROY) { hide(); // hide the Frame dispose(); // free the system resources System.exit(0); // close the application return true; } return super.handleEvent(event); } public boolean action(Event event, Object arg) { if (event.target instanceof MenuItem) { String label = (String) arg; if (label.equalsIgnoreCase("Compress")) { Compress_Action(event); return true; } else if (label.equalsIgnoreCase("Input")) { Input_Action(event); return true; } else if (label.equalsIgnoreCase("New")) { New_Action(event); return true; } else if (label.equalsIgnoreCase("Import Dictionary")) { ImportDictionary_Action(event); return true; } else if (label.equalsIgnoreCase("About")) { About_Action(event); return true; } else if (label.equalsIgnoreCase("Exit")) { Exit_Action(event); return true; } } return super.action(event, arg); } static public void main(String args[]) { (new Boggle()).show(); } //{{DECLARE_CONTROLS java.awt.FileDialog openFileDialog1; java.awt.TextField Status; java.awt.Label label1; java.awt.TextArea WordList; java.awt.TextArea Puzzle; java.awt.TextArea Input; //}} //{{DECLARE_MENUS java.awt.MenuBar mainMenuBar; java.awt.Menu menu1; java.awt.Menu menu2; java.awt.Menu menu3; //}} static final int used = 0x10; static byte[] word=new byte[25]; static int WordCount; static int Lengths[]; static int Words[]; static boolean dictReady = false; static byte[] dict; static int index2[] = new int[26*26]; static int index3[] = new int[26*26*26]; static int Board[] = new int[25]; /* 5x5 grid */ static String Letters; static String Cubes[] = /* 25 6-sided cubes */ { "QBZJXK", /* 0 */ "HHLRDO", /* 1 */ "TELPCI", /* 2 */ "TTOTEM", /* 3 */ "AEAEEE", /* 4 */ "TOUOTO", /* 5 */ "NHDTHO", /* 6 */ "SSNSEU", /* 7 */ "SCTIEP", /* 8 */ "YIFPSR", /* 9 */ "OVWRGR", /* 10 */ "LHNROD", /* 11 */ "RIYPRH", /* 12 */ "EANDNN", /* 13 */ "EEEEMA", /* 14 */ "AAAFSR", /* 15 */ "AFAISR", /* 16 */ "DORDLN", /* 17 */ "MNNEAG", /* 18 */ "ITITIE", /* 19 */ "AUMEEG", /* 20 */ "YIFASR", /* 21 */ "CCWNST", /* 22 */ "UOTOWN", /* 23 */ "ETILIC" /* 24 */ }; } class processDictionary extends Thread { public processDictionary(Boggle boggle) { super(); m_boggle = boggle; start(); } public void run() { FileDialog fd = new FileDialog(m_boggle,"Select dictionary file",FileDialog.LOAD); fd.setFile("*.*"); fd.show(); String fn = fd.getDirectory()+fd.getFile(); FileInputStream fis=null; DataInputStream dis=null; FileOutputStream fos=null; DataOutputStream dos=null; FileOutputStream fosi=null; DataOutputStream dosi=null; int index2[] = new int[26*26]; int index3[] = new int[26*26*26]; File f; long len; String w; int c1,c2,c3; int count=0,i,i2,i3; int idx=1;//start at 1 so 0 can be used as empty try { f = new File(fn); len = f.length(); byte b[] = new byte[(int)len]; fis = new FileInputStream(f); dis = new DataInputStream(fis); fosi = new FileOutputStream("index"); dosi = new DataOutputStream(fosi); dis.readFully(b,0,(int)len); String fulldict = new String(b,0); StringTokenizer st = new StringTokenizer(fulldict,"\n\r"); fos = new FileOutputStream("dict"); dos = new DataOutputStream(fos); int hi=0,phi=0; String his=""; while (st.hasMoreTokens()) { w = st.nextToken().toLowerCase(); if (w.length() > 25) continue; if (w.length() >= 4) { count++; dos.writeBytes(w+"\n"); c1 = Character.toLowerCase(w.charAt(0))-'a'; c2 = Character.toLowerCase(w.charAt(1))-'a'; c3 = Character.toLowerCase(w.charAt(2))-'a'; i3 = c1*676+c2*26+c3; i2 = c1*26+c2; if (index3[i3] == 0) index3[i3] = count; if (index2[i2] == 0) index2[i2] = count; if (count % 1000 == 0) m_boggle.Status.setText("#words so far: "+count); if (i3 > 0) if (index3[i3]-phi > hi) { hi = index3[i3]-phi; his = ""+c1+c2+c3; } phi = index3[i3]; } } dos.close(); m_boggle.Status.setText("Number words output: "+count+","+his+":"+hi); dosi.writeInt(count); for (i=0;i<26*26;i++) dosi.writeInt(index2[i]); for (i=0;i<26*26*26;i++) dosi.writeInt(index3[i]); dosi.close(); } catch (Exception e) { } } Boggle m_boggle; } class PuzzleGenerator extends Thread { public PuzzleGenerator(Boggle boggle) { super(); m_boggle = boggle; start(); } public void run() { m_boggle.genWords(); } Boggle m_boggle; } class Compressor extends Thread { public Compressor(Boggle boggle) { super(); m_boggle = boggle; start(); } public void run() { m_boggle.compressWords(); } Boggle m_boggle; }