//---------------------------------------------------------------------- // NonogramApplet.java //---------------------------------------------------------------------- // ののぐらむ(お絵書きロジック、アートロジック、etc) // // Copyright(C) 1996 Hirofumi Fujiwara // 本プログラムは、改造も含め、その商用利用は禁止します。 //---------------------------------------------------------------------- import java.awt.*; import java.applet.*; import java.lang.*; import java.io.*; import java.util.*; import java.net.*; //================================================================================ // ののぐらむ(アプレット) //================================================================================ public class NonogramApplet extends Applet { Nonogram app; // アプリケーション(ののぐらむ) Problem problem; // 問題の一時保存 String prob; // 問題ファイル名 boolean first = true; Font btnfont = new Font( "Helvetica", 0, 20 ); //---------------------------------------- // 初期化 //---------------------------------------- public void init() { problem = new Problem( this ); prob = getParameter("problem"); System.out.println( "-- java/try/test check Sat Feb 14 18:30:25 JST 1998 --" ); if( prob != null ) { problem.loadprob( prob ); } setLayout( new BorderLayout() ); Button btn = new Button( "Start" ); btn.setFont( btnfont ); add( "Center", btn ); } //---------------------------------------- // ストップ //---------------------------------------- public void stop() { app.sizeFrame.hide(); app.hide(); } //---------------------------------------- // ボタンが押された時の処理 //---------------------------------------- public boolean action( Event evt, Object obj ) { if( "Start".equals(obj) ) { if( app == null ) { app = new Nonogram( this ); app.makePanels(); } app.show(); if( prob != null && first ) { first = false; app.showforced( "Play" ); app.playPanel.setprob( problem ); } } return true; } } //================================================================================ // 問題データの保存 //================================================================================ class Problem { NonogramApplet applet; boolean valid; String filename; int width; int height; int vdepth; int hdepth; int vlines[][]; int hlines[][]; //---------------------------------------- // 構築子 //---------------------------------------- Problem( NonogramApplet ap ) { applet = ap; valid = false; } //---------------------------------------- // リサイズ //---------------------------------------- void resize( Nonogram app ) { app.bdwidth = width; app.bdheight = height; app.playPanel.vdepth = vdepth; app.playPanel.hdepth = hdepth; } //---------------------------------------- // 問題のロード //---------------------------------------- void loadprob( String fname ) { valid = false; filename = fname; URL url; DataInputStream file; try { System.err.println( "problem file : getCodeBase()" ); url = new URL( applet.getCodeBase(), filename ); file = new DataInputStream( url.openStream() ); } catch( MalformedURLException e ) { applet.showStatus( "file name error : " + filename ); return; } catch( IOException e ) { applet.showStatus( "file open error : " + filename ); return; } int w, h, wd, hd; w = h = 20; wd = hd = 10; int vals[] = new int[100]; int valn = 0; int idx = 0; String line; try { nextline: for(;;) { line=file.readLine(); String tk; if( line == null ) break; if( '#' == line.charAt(0) ) continue; if( ';' == line.charAt(0) ) continue; // System.out.println( line ); StringTokenizer st = new StringTokenizer(line); try { tk = st.nextToken(); if( tk.equals("size") ) { tk = st.nextToken(); width = (Integer.valueOf(tk)).intValue(); tk = st.nextToken(); height = (Integer.valueOf(tk)).intValue(); continue nextline; } if( tk.equals("depth") ) { // tk = st.nextToken(); // vdepth = (Integer.valueOf(tk)).intValue(); // tk = st.nextToken(); // hdepth = (Integer.valueOf(tk)).intValue(); continue nextline; } if( tk.equals("begin") ) { vlines = new int[width][0]; hlines = new int[height][0]; continue nextline; } if( tk.equals("end") ) { break nextline; } // System.out.println( "["+idx+"]"+line ); valn = 0; if( ! tk.equals( "-" ) ) { while( tk != null ) { // System.out.println( valn+")"+tk ); vals[valn] = (Integer.valueOf(tk)).intValue(); ++valn; if( ! st.hasMoreTokens() ) break; tk = st.nextToken(); } } if( idx < width ) { vlines[idx] = new int[valn]; for( int i=0; imaxval ) i = maxval; tf.setText( String.valueOf( i ) ); return i; } public boolean action( Event e, Object o ) { if( e.target instanceof Button ) { // テキストフィールド if( "OK".equals( o ) ) { boardresize(); return true; } if( "Cancel".equals( o ) ) { hide(); return true; } } return true; } } //================================================================================ // 共通パネル(ヒントテーブルつき) //================================================================================ abstract class CommonPanel extends Panel { Nonogram app; // パネルのサイズ(このサイズに追随させる) Dimension size = new Dimension(0,0); HintTable vHint, hHint; // 垂直(上)、水平(左)ヒントテーブル int uvw, uvh; // 見える範囲 int unit; int gap = 3; int vdepth = 5; // 深さ int hdepth = 5; // 深さ abstract void paint(); abstract void resizeWindow(); void makeHints( boolean pl ) { vHint = new HintTable( app, this, size, 'v', pl ); hHint = new HintTable( app, this, size, 'h', pl ); } void findviewunit() { int n; int unit = app.unit; n = (size().width - hdepth*unit - gap*2 - 40)/unit; if( n > app.bdwidth ) n = app.bdwidth; else { n = (n / 5) * 5; if( n < 5 ) n = 5; } uvw = n; n = (size().height - vdepth*unit - gap*2 - 40)/unit; if( n > app.bdheight ) n = app.bdheight; else { n = (n / 5) * 5; if( n < 5 ) n = 5; } uvh = n; } void findpreviewunit() { int n; int unit = app.unit; n = (app.size().width - hdepth*unit - gap*2 - 40 - 20)/unit; if( n > app.bdwidth ) n = app.bdwidth; else { n = (n / 5) * 5; if( n < 5 ) n = 5; } uvw = n; n = (app.size().height - vdepth*unit - gap*2 - 40 - 100 )/unit; if( n > app.bdheight ) n = app.bdheight; else { n = (n / 5) * 5; if( n < 5 ) n = 5; } uvh = n; } } //================================================================================ // 遊びキャンバス //================================================================================ class PlayCanvas extends Canvas { PlayPanel panel; // 親パネル Image fullCanvas; Graphics fg; int uvw, uvh; // 枠単位単位でのビューサイズ int ufw, ufh; // 枠単位単位でのフルサイズ int vw, vh; // ドット単位でのビューサイズ int fw, fh; // ドット単位でのフルサイズ Font font; boolean dragging; boolean dragh, dragv; // h方向、v方向のドラッグ int dragvalue; int previx, previy; // 直前のマウス位置 //----------------------------- PlayCanvas // 構築子 //---------------------------------------- PlayCanvas( PlayPanel p ) { panel = p; resize(); } //----------------------------- PlayCanvas // サイズ変更 //---------------------------------------- void resize() { int unit = panel.unit; fw = (ufw=panel.vHint.ufw) * unit + 1; fh = (ufh=panel.hHint.ufh) * unit + 1; fullCanvas = null; fg = null; dragging = false; } //----------------------------- PlayCanvas // ウィンドウのサイズが変更された //---------------------------------------- void resizeWindow() { int unit = panel.unit; vw = (uvw=panel.vHint.uvw) * unit + 1; vh = (uvh=panel.hHint.uvh) * unit + 1; resize( vw, vh ); resize(); } //----------------------------- PlayCanvas // 移動した //---------------------------------------- void moved() { paint(); } //----------------------------- PlayCanvas // フルサイズ画面の描画 //---------------------------------------- void paintFull() { int i, j; int unit = panel.unit; fg.setColor( Color.white ); fg.fillRect( 0, 0, fw, fh ); for( i=0; i<=ufw; ++i ) { fg.setColor( (i%5==0) ? Color.darkGray : Color.lightGray ); fg.drawLine( unit*i, 0, unit*i, unit*ufh ); } for( i=0; i<=ufh; ++i ) { fg.setColor( (i%5==0) ? Color.darkGray : Color.lightGray ); fg.drawLine( 0, unit*i, unit*ufw, unit*i ); } for( i=0; i 0 ) { vals[nvals++] = len; len = 0; } } if( len > 0 ) { vals[nvals++] = len; } if( vHint.hints[i].length != nvals ) verror = true; else { for( int k=0; k 0 ) { vals[nvals++] = len; len = 0; } } if( len > 0 ) { vals[nvals++] = len; } if( hHint.hints[i].length != nvals ) herror = true; else { for( int k=0; k= 0 ) { if( ++vHint.activeline >= app.bdwidth ) { vHint.activeline = -1; hHint.activeline = 0; } } else if( hHint.activeline >= 0 ) { if( ++hHint.activeline >= app.bdheight ) { hHint.activeline = -1; vHint.activeline = 0; } } } //----------------------------- CheatPanel // アクティブ行を文字データとして返す //---------------------------------------- String getLine() { String str = ""; if( vHint.activeline >= 0 ) { int x = vHint.activeline; for( int i=0; i 0 ) str += " "+v; } } else if( hHint.activeline >= 0 ) { int y = hHint.activeline; for( int i=0; i 0 ) str += " "+v; } } return str; } //----------------------------- CheatPanel // 送信データを作成する //---------------------------------------- String makesolvedata() { String SendData = ""; SendData += "size " + app.bdwidth + " " + app.bdheight + "\n"; // depth の部分は、将来不要になる筈。 int vd = 1; for( int i=0; i 30 ) unit = 30; if( unit < 3 ) unit = 3; changed = true; } if( changed || offunit!=unit ) { offunit = unit; int cw = offwidth *unit+1; int ch = offheight*unit+1; resize( cw, ch ); makepanel.validate(); offImage = app.applet.createImage( cw, ch ); og = offImage.getGraphics(); og.clearRect( 0, 0, cw, ch ); } } //---------------------------------------- // 表示 //---------------------------------------- public void paint( Graphics g ) { resizing(); // サイズ調整 for( int x=0; x 1 ) { boolean marked = false; for( int i=0; i<2 && !marked ; ++i ) { for( int x=0; x=1; --x ) { for( int y=0; y=1; --y ) for( int x=0; x 0 ) { str += ( (str.length()!=0) ? " " : "") + len; len = 0; } } if( len > 0 ) { str += ( (str.length()!=0) ? " " : "") + len; } if( str.length() == 0 ) str = "-"; SendData += str + "\n"; } for( int i=0; i 0 ) { str += ( (str.length()!=0) ? " " : "") + len; len = 0; } } if( len > 0 ) { str += ( (str.length()!=0) ? " " : "") + len; } if( str.length() == 0 ) str = "-"; SendData += str + "\n"; } SendData += "end\n"; return SendData; } //-------------------------------------- MakePanel // ヒントデータを作成するために奥行きを伸ばす //------------------------------------------------ void prolongdepth() { int vdepth = 1; int hdepth = 1; for( int i=0; i 0 ) { ++d; len = 0; } } if( len > 0 ) { ++d; } if( vdepth < d ) vdepth = d; } for( int i=0; i 0 ) { ++d; len = 0; } } if( len > 0 ) { ++d; } if( hdepth < d ) hdepth = d; } app.playPanel.vdepth = vdepth; app.playPanel.hdepth = hdepth; app.playPanel.resize(); } //------------------------------ MakePanel // ヒントデータを作成する //---------------------------------------- void sethintdata() { int vals[] = new int[100]; int nvals; app.cheatPanel.vHint.resizeHint(); app.cheatPanel.hHint.resizeHint(); app.playPanel.vHint.resizeHint(); app.playPanel.hHint.resizeHint(); for( int i=0; i 0 ) { vals[nvals++] = len; len = 0; } } if( len > 0 ) { vals[nvals++] = len; } app.cheatPanel.vHint.setValues( i, nvals, vals ); app.playPanel.vHint.setValues( i, nvals, vals ); } for( int i=0; i 0 ) { vals[nvals++] = len; len = 0; } } if( len > 0 ) { vals[nvals++] = len; } app.cheatPanel.hHint.setValues( i, nvals, vals ); app.playPanel.hHint.setValues( i, nvals, vals ); } } //------------------------------ MakePanel // 解答の最初のデータを移す //---------------------------------------- void copyfirstanswer() { clearTable(); if( app.answer.anscount < 1 ) return; for( int i=0; i= 0 ) { int ln = panel.hHint.activeline; panel.incactive(); panel.hHint.setValues( ln, valnum, vals ); } else if( panel.vHint.activeline >= 0 ) { int ln = panel.vHint.activeline; panel.incactive(); panel.vHint.setValues( ln, valnum, vals ); } backData(); panel.paint(); } } //================================================================================ // ヒントテーブル(縦・横) //================================================================================ class HintTable { Nonogram app; char dir; // 'v' or 'h' boolean play; // true:playpanel, false:cheatpanel CommonPanel panel; ScrollableHintTable hinttable; Scrollbar hbar, vbar; boolean hadd, vadd; // 親パネルに加えられているか int hints[][]; int maxdepth; // depth最大値(1以上) boolean marked[][]; int uvw, uvh; // 見える範囲の枠数 int ufw, ufh; // 全体の枠数 int hval, vval; // スクロールバーの位置 int hmax, vmax; // スクロールバー最大位置 int activeline; // アクティブ行 //---------------------------------------- // 構築子 // hb, vb : 水平垂直バーの生成 //---------------------------------------- HintTable( Nonogram a, CommonPanel pn, Dimension ps, char d, boolean pl ) { app = a; panel = pn; play = pl; dir = d; hbar = vbar = null; int unit = app.unit; if( dir == 'v' ) { activeline = -1; ufw = app.bdwidth; ufh = panel.vdepth; uvw = panel.uvw; uvh = ufh; hinttable = new ScrollableHintTable( this, panel, d, play ); panel.add( hinttable ); hinttable.resize( unit*uvw+1, unit*uvh+1 ); // 水平スクロールバーの生成 hbar = new Scrollbar( Scrollbar.HORIZONTAL ); hmax = ufw-uvw; hval = 0; hbar.setValues( hval, uvw, 0, hmax ); // 垂直スクロールバーの生成 vbar = new Scrollbar( Scrollbar.VERTICAL ); vval = vmax = ufh-uvh; vbar.setValues( vval, uvh, 0, vmax ); } if( dir == 'h' ) { activeline = 0; ufw = panel.hdepth; ufh = app.bdheight; uvw = ufw; uvh = panel.uvh; hinttable = new ScrollableHintTable( this, panel, d, play ); panel.add( hinttable ); hinttable.resize( unit*uvw+1, unit*uvh+1 ); // 水平スクロールバーの生成 hbar = new Scrollbar( Scrollbar.HORIZONTAL ); hval = hmax = ufw-uvw; hbar.setValues( hval, uvw, 0, hmax ); // 垂直スクロールバーの生成 vbar = new Scrollbar( Scrollbar.VERTICAL ); vmax = ufh-uvh; vval = 0; vbar.setValues( vval, uvh, 0, vmax ); } resizeHint(); } //---------------------------------------- // ウィンドウのサイズが変更された //---------------------------------------- void resizeWindow() { int unit = app.unit; if( dir == 'v' ) { uvw = panel.uvw; hinttable.resize( unit*uvw+1, unit*uvh+1 ); // 水平スクロールバー hmax = ufw-uvw; hval = 0; hbar.setValues( hval, uvw, 0, hmax ); // 垂直スクロールバー vmax = ufh-uvh; } if( dir == 'h' ) { uvh = panel.uvh; hinttable.resize( unit*uvw+1, unit*uvh+1 ); // 水平スクロールバー hmax = ufw-uvw; // 垂直スクロールバー vmax = ufh-uvh; vval = 0; vbar.setValues( vval, uvh, 0, vmax ); } hinttable.resize(); if( hbar != null ) { if( hmax > 0 ) { if( !hadd ) { panel.add( hbar ); hadd = true; } hbar.show( true ); hbar.setValues( hval, uvw, 0, hmax ); } else { if( hadd ) { panel.remove( hbar ); hadd = false; } } } if( vbar != null ) { if( vmax > 0 ) { if( !vadd ) { panel.add( vbar ); vadd = true; } vbar.show( true ); vbar.setValues( vval, uvh, 0, vmax ); } else { if( vadd ) { panel.remove( vbar ); vadd = false; } } } } //---------------------------------------- // 移動した //---------------------------------------- void moved() { if( hbar!=null && hbar.isVisible() ) { hval = hbar.getValue(); } if( vbar!=null && vbar.isVisible() ) { vval = vbar.getValue(); } paint(); } //---------------------------------------- // クリア変更 //---------------------------------------- void clear() { clearHint(); hinttable.clear(); paint(); } //---------------------------------------- // ヒントテーブルのリサイズ //---------------------------------------- void resizeHint() { hints = new int[dir=='v'? ufw:ufh][]; marked = play ? new boolean[dir=='v'? ufw:ufh][] : null; clearHint(); } //---------------------------------------- // ヒントテーブルのクリア //---------------------------------------- void clearHint() { for( int i=0; i= ufw ) return; if( panel.vdepth < n ) { uvh = ufh = panel.vdepth = n; hinttable.fullCanvas = null; // OFFイメージ消去 panel.resizeWindow(); } hints[x] = new int[n]; if( play ) { marked[x] = new boolean[n]; } for( int i=0; i= ufh ) return; if( panel.hdepth < n ) { uvw = ufw = panel.hdepth = n; hinttable.fullCanvas = null; // OFFイメージ消去 panel.resizeWindow(); } hints[y] = new int[n]; if( play ) { marked[y] = new boolean[n]; } for( int i=0; i 0 ) { hbar.show( true ); hbar.setValues( hval, uvw, 0, hmax ); } else { hbar.show( false ); } } if( vbar != null ) { if( vmax > 0 ) { vbar.show( true ); vbar.setValues( vval, uvh, 0, vmax ); } else { vbar.show( false ); } } // ヒントテーブルのサイズ変更 resizeHint(); hinttable.resize(); paint(); } //---------------------------------------- // ペイント //---------------------------------------- public void paint() { hinttable.paint( hinttable.getGraphics() ); } } //================================================================================ // ヒントテーブル(スクロールキャンバス) //================================================================================ class ScrollableHintTable extends Canvas { Nonogram app; CommonPanel panel; // 親パネル boolean play; // true:playpanel, false:cheatpanel HintTable hintTable; char dir; Image fullCanvas; Image fullCanvasWhite; Image fullCanvasActive; Image clipCanvasActive; Graphics fg, fgw, fga; int vw, vh; // ドット単位でのビューサイズ int fw, fh; // ドット単位でのフルサイズ Font font; //---------------------------------------- // 構築子 //---------------------------------------- ScrollableHintTable( HintTable ht, CommonPanel p, char d, boolean pl ) { hintTable = ht; panel = p; app = ht.app; dir = d; play = pl; resize(); } //---------------------------------------- // テーブルサイズ変更 //---------------------------------------- void resize() { fw = hintTable.ufw * app.unit + 1; fh = hintTable.ufh * app.unit + 1; vw = hintTable.uvw * app.unit + 1; vh = hintTable.uvh * app.unit + 1; fullCanvas = null; font = null; fg = null; } //---------------------------------------- // OFFイメージの生成 //---------------------------------------- void createImages() { if( fullCanvas != null ) return; fullCanvas = app.applet.createImage( fw, fh ); fg = fullCanvas.getGraphics(); fullCanvasWhite = app.applet.createImage( fw, fh ); fgw = fullCanvasWhite.getGraphics(); fullCanvasActive = app.applet.createImage( fw, fh ); fga = fullCanvasActive.getGraphics(); int unit = panel.unit; int w, h; if( dir == 'h' ) { h = unit; w = unit*hintTable.ufw; } else { h = unit*hintTable.ufh; w = unit; } clipCanvasActive = app.applet.createImage( w, h ); paintAll(); } //---------------------------------------- // クリア(フルサイズ画面の枠の描画) //---------------------------------------- void clear() { int unit = panel.unit; fgw.setColor( Color.white ); fgw.fillRect( 0, 0, fw, fh ); fga.setColor( Color.cyan ); fga.fillRect( 0, 0, fw, fh ); fgw.setColor( Color.lightGray ); fga.setColor( Color.lightGray ); for( int i=0; i<=hintTable.ufw; ++i ) { fgw.drawLine( unit*i, 0, unit*i, unit*hintTable.ufh ); fga.drawLine( unit*i, 0, unit*i, unit*hintTable.ufh ); } for( int i=0; i<=hintTable.ufh; ++i ) { fgw.drawLine( 0, unit*i, unit*hintTable.ufw, unit*i ); fga.drawLine( 0, unit*i, unit*hintTable.ufw, unit*i ); } fgw.setColor( Color.darkGray ); fga.setColor( Color.darkGray ); if( dir == 'v' ) { for( int i=0; i<=hintTable.ufw; i+=5 ) { fgw.drawLine( unit*i, 0, unit*i, unit*hintTable.ufh ); fga.drawLine( unit*i, 0, unit*i, unit*hintTable.ufh ); } } if( dir == 'h' ) { for( int i=0; i<=hintTable.ufh; i+=5 ) { fgw.drawLine( 0, unit*i, unit*hintTable.ufw, unit*i ); fga.drawLine( 0, unit*i, unit*hintTable.ufw, unit*i ); } } addImages(); } //---------------------------------------- // フルサイズ画面の描画(枠) // 白とアクティブを重ねる // activelineの変更の度に呼び出す。 //---------------------------------------- void addImages() { createImages(); fg.drawImage( fullCanvasWhite, 0, 0, fw, fh, this ); if( hintTable.activeline >= 0 ) { int unit = panel.unit; int x, y; if( dir == 'h' ) { x = 0; y = unit*hintTable.activeline; } else { x = unit*hintTable.activeline; y = 0; } Graphics cg = clipCanvasActive.getGraphics(); cg.drawImage( fullCanvasActive, -x, -y, this ); fg.drawImage( clipCanvasActive, x, y, this ); } } void paintAll() { clear(); for( int x=0; x