//---------------------------------------------------------------------- // フラワーパズル テンヨーのプラパズルNo.○ // // 組み合わせ総数 1641通り // 組み合わせ総数 1797通り(私の計算) // // 制作開始 1996年3月12日 // 制作凍結 1996年3月14日 // 全面変更 1996年4月30日 // 汎用化開始 1996年6月24日 // // 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 Flower extends Applet implements Runnable { int PuzzleType = 0; int BoardOffset = 190; int PieceOffset = 310; int RadiusB = 38; int RadiusP = 22; int SleepingTime = 2000; final int MijinkoIndex = 6; final int MijinkoMaxRotation[] = { 3, 6 }; FillBoard board; ChoiceBoard choice; Solver solver; PiecePolygon polygon; Dimension app_size; Font panelFont = new java.awt.Font( "Helvetica", 0, 20 ); Panel controlPanel; Label counterPanel; ControlButton solvebutton; boolean possible = true; Color backcolor; boolean mouselock = false; Thread mainThread; //------------------------------------------------------------------------ // 初期化 public void init() { app_size = this.size(); String param = null; param = getParameter("PuzzleType"); if( param!=null ) PuzzleType = Integer.valueOf(param).intValue(); param = getParameter("BoardOffset"); if( param!=null ) BoardOffset = Integer.valueOf(param).intValue(); param = getParameter("PieceOffset"); if( param!=null ) PieceOffset = Integer.valueOf(param).intValue(); param = getParameter("RadiusB"); if( param!=null ) RadiusB = Integer.valueOf(param).intValue(); param = getParameter("RadiusP"); if( param!=null ) RadiusP = Integer.valueOf(param).intValue(); param = getParameter("SleepingTime"); if( param!=null ) SleepingTime = Integer.valueOf(param).intValue(); setLayout( new BorderLayout() ); controlPanel = new Panel(); controlPanel.setLayout(new FlowLayout()); counterPanel = new Label( " No. 0 " ); counterPanel.setFont( panelFont ); controlPanel.add( counterPanel ); solvebutton = new ControlButton( this, "Solve", " Solve " ); controlPanel.add( solvebutton ); controlPanel.add( new ControlButton( this, "Next", " Next " ) ); controlPanel.add( new ControlButton( this, "Reset", " Reset " ) ); add( "North", controlPanel ); Label copyright = new Label("Flower Puzzle V0.3" + " " + "Copyright(C)1996 Hirofumi Fujiwara.", Label.CENTER ); add( "South", copyright ); polygon = new PiecePolygon( 7 ); board = new FillBoard( this, BoardOffset, PuzzleType, RadiusB, app_size.width ); choice = new ChoiceBoard( this, RadiusP, app_size.width, PieceOffset ); // // ミジンコの対称数 solver = new Solver( this, MijinkoMaxRotation[PuzzleType] ); backcolor = getBackground(); } //------------------------------------------------------------------------ // 初期状態にする public void Reset() { board.Reset(); choice.Reset(); solver.Reset(); paint( getGraphics() ); } //------------------------------------------------------------------------ public void start() { if( mainThread == null ) { mainThread = new Thread( this ); } } public void run() { try { mainThread.sleep( 50 ); } catch( InterruptedException e ) {} possible = false; while( solver.Findnext() ) { possible = true; if( solver.mode != 2 ) break; try { possible = true; mainThread.sleep( SleepingTime ); // お休みタイム possible = false; } catch( InterruptedException e ) { break; } } mainThread.stop(); mainThread = null; possible = true; } //------------------------------------------------------------------------ // マウスUP public boolean mouseUp( Event e, int x, int y ) { if( mouselock ) return true; mouselock = true; if( board.mouseUp( x, y ) || choice.mouseUp( x, y ) ) { solver.mode = 0; } mouselock = false; return true; } //------------------------------------------------------------------------ // 描画 public void repaint( Graphics g ) { paint( g ); } public void paint( Graphics g ) { Dimension r = size(); g.clearRect( 0, 0, r.width, r.height ); board.paintAll( g ); choice.paintAll( g ); solver.DrawCounter(); } } //-------------------------------------------------------------------------------- // 制御ボタンクラス // // "Solve" "Stop" //-------------------------------------------------------------------------------- class ControlButton extends Button { Flower app; String name; // 構築子 ControlButton( Flower f, String str, String label ) { super(); app = f; name = str; setLabel( label ); setFont( app.panelFont ); } public boolean action( Event evt, Object obj ) { if( ! app.possible ) return false; if( app.mainThread != null ) { app.mainThread.stop(); app.mainThread = null; } if( name.equals("Solve") ) { switch ( app.solver.mode ) { case 0: app.Reset(); app.solver.StartInit(); app.solvebutton.setLabel( "Stop" ); app.solver.mode = 2; // 実行 app.start(); app.mainThread.start(); break; case 2: app.solvebutton.setLabel( "Continue" ); app.solver.mode = 1; // 一時中断 break; case 1: app.solvebutton.setLabel( "Stop" ); app.solver.mode = 2; // 続行 app.start(); app.mainThread.start(); } return true; } if( app.solver.mode > 0 ) { app.solvebutton.setLabel( " Solve " ); } if( name.equals("Next") ) { app.solvebutton.setLabel( "Continue" ); if( app.solver.mode == 0 ) app.solver.StartInit(); app.solver.mode = 1; // 一時中断 app.start(); app.mainThread.start(); } if( name.equals("Reset") ) { app.Reset(); } return true; } } //-------------------------------------------------------------------------------- // 詰め込みボードデータ //-------------------------------------------------------------------------------- class FillBoard { Flower app; int xys0[][] = { // 盤の形状データ { -2, -1 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { -2, 0 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { 2, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 } }; int xys1[][] = { // 盤の形状データ { -1, -2 }, { -1, -1 }, { 0, -1 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 0, 2 }, { 1, 2 }, { 2, 2 } }; int xys[][]; public PickOnBoard picks[]; public int pickn; public PieceOnBoard pieces[]; public int R; // 駒の半径 public int width; // 横幅 public Point boardCenter; // 盤の原点位置 public Point deltaX, deltaY; // 各軸方向の単位ベクトル public int current = -1; // 現在の○の添字 public PieceOnBoard currentpiece; // 現在の○ Point mp; //------------------------------------------------------------------------ // 構築子 public FillBoard( Flower f, int boardoffset, int puztype, int r, int w ) { app = f; picks = new PickOnBoard[40]; pickn = 0; xys = xys0; switch( puztype ) { case 1: xys = xys1; break; case 0: xys = xys0; break; } // 盤面の幾何データ初期化 R = r; width = w; boardCenter = new Point( width/2, boardoffset ); deltaX = new Point( R*2, 0 ); deltaY = new Point( -R, (int)Math.round( R * 1.732 ) ); mp = new Point( 0, 0 ); // ピースデータの初期化 pieces = new PieceOnBoard[xys.length]; for( int i=0; i= R*R ) return -1; return no; } //------------------------------------------------------------------------ // マウスUP public boolean mouseUp( int x, int y ) { int no = pickedPiece( x, y ); if( no == -1 ) return false; SetCurrent( no, true ); return true; } public void SetCurrent( int no, boolean draw ) { if( current != -1 && draw ) { currentpiece.paintMark( app.getGraphics(), false ); } if( pieces[no].pc != -1 ) { // 入っているピースをクリック current = no; currentpiece = pieces[current]; currentpiece.unsetPiece(); current = -1; } else { // ブランク個所をクリック if( current == no ) { // 反転のため解除 current = -1; } else { // 新しい場所 current = no; currentpiece = pieces[current]; if( draw ) currentpiece.paintMark( app.getGraphics(), true ); } } } //------------------------------------------------------------------------ // 全てを表示 public void paintAll( Graphics g ) { for( int i=0; i= sn ); } } //-------------------------------------------------------------------------------- // 選択ボードデータ //-------------------------------------------------------------------------------- class ChoiceBoard { public Flower app; final int xys[][] = { {0,0,0}, {2,0,1}, {4,0,2}, {6,0,3}, {0,2,4}, {2,2,5}, {4,2,6}, {6,2,7}, {8,2,8}, {2,4,9}, {4,4,10},{6,4,11},{8,4,11}, }; final Color colors[] = { Color.green, Color.green, Color.green, Color.magenta, Color.magenta, Color.magenta, Color.cyan, Color.cyan, Color.cyan, Color.yellow, Color.yellow, Color.yellow, Color.yellow, }; public int picks[][] = { // ピースの突起データ { 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 0, 6 }, { 1, 1, 1, 1, 0, 0, 6 }, { 1, 1, 1, 0, 1, 0, 6 }, { 1, 1, 0, 1, 1, 0, 3 }, { 1, 1, 1, 0, 0, 0, 6 }, { 1, 1, 0, 1, 0, 0, 12 }, // ミジンコ { 1, 1, 0, 0, 0, 0, 6 }, { 1, 0, 1, 0, 1, 0, 2 }, { 1, 0, 1, 0, 0, 0, 6 }, { 1, 0, 0, 1, 0, 0, 3 }, { 1, 0, 0, 0, 0, 0, 6 }, }; public PieceChoice pds[]; // 選択されるピースの配列 public int R; // 半径 public int width; public int offset; public Point org; public Point deltaX, deltaY; public int picked = -1; // ピックされてまだ未処理のピース番号 Point mp; //------------------------------------------------------------------------ // 初期化 public ChoiceBoard( Flower a, int r, int w, int off ) { app = a; R = r; width = w; offset = off; org = new Point( (width - R * 12)/2, offset + R * 3 ); deltaX = new Point( R*2, 0 ); deltaY = new Point( -R, (int)Math.round(R * 1.732) ); mp = new Point( 0, 0 ); pds = new PieceChoice[xys.length]; for( int i=0; i= R*R ) return -1; return no; } //------------------------------------------------------------------------ // マウスUP public boolean mouseUp( int x, int y ) { int no = pickedPiece( x, y ); if( no == -1 ) return false; if( app.board.current != -1 ) { // 詰める app.board.setPiece( no ); } else { // 回転する picked = no; repaint( app.getGraphics() ); } return true; } //------------------------------------------------------------------------ // 再描画 public void repaint( Graphics g ) { if( picked == -1 ) return; // 指定ピースを回転する PieceChoice p = pds[picked]; p.piecePaint( g, false ); p.rotate(); p.piecePaint( g, true ); picked = -1; } //------------------------------------------------------------------------ // 全てを表示 public void paintAll( Graphics g ) { for( int i=0; i= 6); for( int k=0; k<6; ++k ) { picks[(k+ang)%6] = cb.picks[figid][rev ? 5-k : k]; } } //------------------------------------------------------------------------ // ピースを塗る void piecePaint( Graphics g, Color fc, Color ec ) { PiecePolygon p = cb.app.polygon; p.Set( cb.R, picks ); p.move( C.x, C.y ); g.setColor( fc ); // 内部塗りつぶし g.fillPolygon( p ); g.setColor( ec ); // 輪郭 g.drawPolygon( p ); } public void piecePaint( Graphics g, boolean t ) { if( t ) { // 描く piecePaint( g, col, Color.black ); } else { // 消す Color bc = cb.app.backcolor; piecePaint( g, bc, bc ); } } public void usedPaint( Graphics g ) { piecePaint( g, Color.lightGray, Color.black ); } } //-------------------------------------------------------------------------------- // 外周ポリゴン作成クラス(表示のために用いられるのみ) //-------------------------------------------------------------------------------- class PiecePolygon extends Polygon { int divn; // 1/6円の分割数 double delta; double th; int ithorn[] = new int[6]; // 刺データ //------------------------------------------------------------------------ // 構築子 public PiecePolygon( int n ) { divn = n; delta = Math.PI/3.0/divn; xpoints = new int[divn*13]; ypoints = new int[divn*13]; npoints = 0; } //------------------------------------------------------------------------ // 設定 public void Set( int r, PickOnBoard thorn[] ) { for( int i=0; i= depth ) { // 答えの次 --no; app.board.pieces[poss[no]].unsetPiece(); // 外す --no; app.board.pieces[poss[no]].unsetPiece(); // 外す ++angs[no]; } loop: while( true ) { int pn = pns[no]; SolvePiece pc = solver.solvetable.table[pn]; PieceChoice ch = app.choice.pds[no]; // 選択されたピース for( ; poss[no]