import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import javax.microedition.lcdui.Image; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Font; import javax.microedition.lcdui.Graphics; import javax.microedition.midlet.MIDlet; import java.util.Hashtable; import java.util.Random; public class hangman extends MIDlet { public void startApp() { Displayable d = null; try { d = new KeyCanvas(); } catch (IOException ex) { ex.printStackTrace(); } d.setCommandListener(new CommandListener() { public void commandAction(Command c, Displayable s) { notifyDestroyed(); } }); Display.getDisplay(this).setCurrent(d); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } } class KeyCanvas extends Canvas { //private Font mFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_MEDIUM); private String mMessage = ""; private String m_letters; private String m_lastletter; private String m_answer; private String m_question; private String m_allletters; private String m_guess; private String m_wrong; private int m_wrongletters; private String m_encoding=""; private int m_state=0; //0=start 1=play 2=next word 3=lose 4=win private String m_init_letters; private String m_init_allletters; private int m_count_games=0; private int m_count_wins=0; private String m_filewords; public Hashtable m_hashLocales; private int m_keysize = 0; private int [] m_key; public KeyCanvas() throws IOException { m_state = 0; m_key = new int[ m_keysize+1]; m_key[ 0] = 0; SelectFileWords(); //LoadEncoding(); LoadLocales(); addCommand(new Command( getlocale( "exit"), Command.EXIT, 0)); } private String decrypt( String s){ String ret=""; if( m_keysize <=0 ){ return s; } int len=s.length(); for(int i=0; i < len; i+=m_keysize){ for(int j=0; j < m_keysize; j++){ int pos=i + m_key[ j]; if( pos < len){ ret = ret + s.charAt( pos); } } } return ret; } private String getlocale( String key){ return (String)m_hashLocales.get( key); } private void SelectFileWords() throws IOException{ Class c = this.getClass(); InputStream is = c.getResourceAsStream( "hangman/hangman.txt"); InputStreamReader reader = new InputStreamReader( is, "UTF-8"); String line = null; // Read a single line from the file. null represents the EOF. while ((line = readLine(reader)) != null) { int pos = line.indexOf( "="); if( pos >= 0){ m_filewords = "hangman/" + line.substring( 0, pos); } break; } reader.close(); } private String readLine(InputStreamReader reader) throws IOException { // Test whether the end of file has been reached. If so, return null. int readChar = reader.read(); if (readChar <= -1) { return null; } StringBuffer string = new StringBuffer(); // Read until end of file or new line while (readChar > -1 && readChar != '\n') { // Append the read character to the string. Some operating systems // such as Microsoft Windows prepend newline character ('\n') with // carriage return ('\r'). This is part of the newline character and // therefore an exception that should not be appended to the string. if (readChar != '\r') { string.append( (char )readChar); } // Read the next character readChar = reader.read(); } return string.toString(); } private void LoadLocales() throws IOException{ m_hashLocales = new Hashtable(); Class c = this.getClass(); InputStream is = c.getResourceAsStream( "hangman/language.txt"); InputStreamReader reader = new InputStreamReader( is, "UTF-8"); String line = null; String key, data; // Read a single line from the file. null represents the EOF. while ((line = readLine(reader)) != null) { int pos = line.indexOf( "="); if( pos >= 0){ key = line.substring( 0, pos); data = line.substring( pos+1); m_hashLocales.put(key, data); } } reader.close(); } protected boolean SetCurrentWord( String line) throws IOException{ int pos=line.indexOf( '='); if( pos == -1){ return false; } m_answer = line.substring( 0, pos); m_question = line.substring( pos+1); return true; } protected int SelectWord( String fname) throws IOException{ Class c = this.getClass(); InputStream is = c.getResourceAsStream( fname); InputStreamReader reader = new InputStreamReader( is, "UTF-8"); String line = null; int count=0; // Read a single line from the file. null represents the EOF. while ((line = readLine(reader)) != null) { // Append the read line to the main form with a linefeed ('\n') count = count + 1; } reader.close(); //select randomly one word Random r = new Random(); int curline = r.nextInt(); curline = curline % count; if( curline < 0) curline = curline + count; InputStreamReader reader2 = new InputStreamReader( getClass().getResourceAsStream(fname), "UTF-8"); int i = 0; // Read a single line from the file. null represents the EOF. while ((line = readLine(reader2)) != null) { if( i == curline){ line = decrypt( line); SetCurrentWord( line); return 1; } i = i + 1; } reader.close(); return 0; } public void paint(Graphics g) { switch( m_state){ case 0: try { paint_state_start(g); } catch (IOException ex) { ex.printStackTrace(); } break; case 1: try { paint_state_play( g); } catch (StringIndexOutOfBoundsException ex) { ex.printStackTrace(); } break; case 2: try { paint_state_nextword(g); } catch (IOException ex) { ex.printStackTrace(); } break; case 3: paint_state_lose( g); break; case 4: try { paint_state_win(g); } catch (IOException ex) { ex.printStackTrace(); } break; } } private void paint_state_start(Graphics g) throws IOException{ m_init_letters = getlocale( "keyboardletters"); m_init_allletters = m_init_letters; String sRemove = "1234567890:#"; for(int i=0; i < sRemove.length(); i++){ for(;;){ int pos = m_init_allletters.indexOf( sRemove.charAt(i)); if( pos < 0) break; m_init_allletters = m_init_allletters.substring( 0, pos) + m_init_allletters.substring( pos+1); } } m_state = 2; paint_state_nextword( g); } private void paint_state_nextword(Graphics g) throws IOException{ m_letters = m_init_letters; m_allletters = m_init_allletters; SelectWord( m_filewords); m_lastletter = ""; int len = m_answer.length(); m_guess = ""; m_wrong = ""; for(int i=0; i < len; i++){ m_guess = m_guess + "-"; } m_wrongletters = 0; m_state = 1; //play paint_state_play( g); } private void paint_state_win(Graphics g) throws IOException{ m_count_games++; m_count_wins++; m_state = 2; paint_state_nextword( g); } private void paint_state_lose(Graphics g){ m_count_games++; //clear the screen g.setColor(255,255,255); g.fillRect(0, 0, getWidth(), getHeight()); //set color to black g.setColor(0,0,0); //get the font height int y=10; int iHeight=g.getFont().getHeight(); String s = m_answer; if( m_wrong.length() > 0){ s = s + " (" + m_wrong + ")"; } s = s + " [" + String.valueOf( m_count_wins) + "/" + String.valueOf( m_count_games) + "]"; y = drawtextmultiline( g, s, 0, y); y = drawtextmultiline( g, m_question, 0, y+iHeight); m_state = 2; } private void paint_state_play(Graphics g){ //clear the screen g.setColor(255,255,255); g.fillRect(0, 0, getWidth(), getHeight()); //set color to black g.setColor(0,0,0); //get the font height int y=0; Font font = g.getFont(); int iHeight=g.getFont().getHeight(); String s = m_guess; if( m_wrong.compareTo( "") != 0){ s = s + " (" + m_wrong + ")"; } s = s + " (" + String.valueOf( m_count_wins) + "/" + String.valueOf( m_count_games) + ")"; y = drawtextmultiline( g, s, 0, y); int x = getWidth() - 3 * font.charWidth( '-'); y = drawtextmultiline( g, mMessage, x, y) + iHeight; y = drawtextmultiline( g, m_question, 0, y) + iHeight; Image im = null; try { String filename = "/hangman/hangman_" + String.valueOf(m_wrongletters) + ".jpg"; im = Image.createImage( filename); } catch (IOException ex) { ex.printStackTrace(); } int xMul = (100 * getWidth()) / im.getWidth(); int yMul = (100 * (getHeight() - y)) / im.getHeight(); if( yMul < xMul){ xMul = yMul; } int cx = (xMul * im.getWidth()) / 100; int cy = (yMul * im.getHeight()) / 100; Image resize = resizeImage( im, cx, cy); g.drawImage(resize, 0, y, Graphics.LEFT | Graphics.TOP); } protected int drawtextmultiline(Graphics g, String text, int x, int y){ Font font = g.getFont(); int fontHeight = font.getHeight(); //change string to char data char[] data = new char[text.length()]; text.getChars(0, text.length(), data, 0); int width = getWidth(); int lineWidth = 0; int charWidth = 0; int xStart = x; char ch; for(int ccnt=0; ccnt < data.length; ccnt++) { ch = data[ccnt]; //measure the char to draw charWidth = font.charWidth(ch); lineWidth = lineWidth + charWidth; //see if a new line is needed if (lineWidth > width) { y = y + fontHeight; lineWidth = 0; x = xStart; } //draw the char g.drawChar(ch, x, y, Graphics.TOP|Graphics.LEFT); x = x + charWidth; } return y; } protected void keyPressed(int keyCode) { char number; if( m_state == 2){ repaint(); return; } if( (keyCode >= 49) && (keyCode <= 57)){ String numbers = "123456789"; number = numbers.charAt(keyCode - 49); int pos = m_letters.indexOf( number + ":"); String letters = ""; String letters2 = m_letters.substring( pos+2); if( pos >= 0){ pos = letters2.indexOf( '#'); if( pos >= 0){ letters = letters2.substring( 0, pos); //Compute the letters that correspond to the key pressed if( m_lastletter.compareTo( "") != 0){ pos = letters.indexOf( m_lastletter); if( pos >= 0){ pos = pos + 1; if( pos >= letters.length()){ pos = 0; } }else{ //different key pos = 0; } }else{ pos = 0; } if( (pos < letters.length()) && (pos >= 0)){ m_lastletter = letters.substring( pos, pos+1); mMessage = m_lastletter; repaint(); } return; } } repaint(); return; } int gameAction = getGameAction(keyCode); switch (gameAction) { case FIRE: OnFire(); break; default: mMessage = String.valueOf( keyCode); break; } } protected void OnFire() { int pos = m_guess.indexOf( m_lastletter); if( pos >= 0){ //Already used return; } char ch = m_lastletter.charAt( 0); pos = m_answer.indexOf( ch); if( pos >= 0){ //correct letter //Maybe there are many letters for(pos=0; pos < m_guess.length();pos++){ if( m_answer.charAt( pos) == ch){ m_guess = m_guess.substring( 0, pos) + m_lastletter + m_guess.substring( pos+1); } } pos = m_allletters.indexOf( m_lastletter); if( pos >= 0){ m_allletters = m_allletters.substring( 0, pos) + "." + m_allletters.substring( pos+1); } remove_lastletter_from_keyboard(); if( m_guess.indexOf( '-') < 0){ m_state = 4; //state=win; } repaint(); return; } pos = m_allletters.indexOf( m_lastletter); if( pos < 0){ return; } //wrong letter m_wrongletters = m_wrongletters + 1; pos = m_allletters.indexOf( m_lastletter); if( pos >= 0){ m_allletters = m_allletters.substring( 0, pos) + "." + m_allletters.substring( pos+1); m_wrong = m_wrong + m_lastletter; } remove_lastletter_from_keyboard(); if( m_wrongletters >= 6){ m_state = 3; //state=lose } repaint(); } private void remove_lastletter_from_keyboard(){ int pos = m_letters.indexOf( m_lastletter); if( pos >= 0){ m_letters = m_letters.substring( 0, pos) + m_letters.substring( pos+1); } } private Image resizeImage(Image src, int cx, int cy) { int srcWidth = src.getWidth(); int srcHeight = src.getHeight(); Image tmp = Image.createImage(cx, srcHeight); Graphics g = tmp.getGraphics(); int ratio = (srcWidth << 16) / cx; int pos = ratio/2; //Horizontal Resize for (int x = 0; x < cx; x++) { g.setClip(x, 0, 1, srcHeight); g.drawImage(src, x - (pos >> 16), 0, Graphics.LEFT | Graphics.TOP); pos += ratio; } Image resizedImage = Image.createImage(cx, cy); g = resizedImage.getGraphics(); ratio = (srcHeight << 16) / cy; pos = ratio/2; //Vertical resize for (int y = 0; y < cy; y++) { g.setClip(0, y, cx, 1); g.drawImage(tmp, 0, y - (pos >> 16), Graphics.LEFT | Graphics.TOP); pos += ratio; } return resizedImage; }//resize image }