001:// eightqueen4 : Multi Thread eightqueen(Runnable)
002:
003:import java.awt.* ;
004:import java.awt.event.* ;
005:import javax.swing.* ;
006:import javax.swing.event.* ;
007:
008:public class EightQueen4 extends JFrame
009: implements Runnable {
010:
011: JLabel title; // Eight Queen ...
012: int count=0; // 見付かった解の個数
013: JLabel[][] cell; // 盤
014: int boardSize; // 盤の大きさ
015: boolean trap=true; // 中断フラグ
016: boolean trapOnFound; // 解が見つかったとき停止するか
017: final int trapTime=300; // 停止する際のwait時間
018: int[] pos; // コマの横位置
019: int[] na; // 斜め上がりの利き筋
020: int[] ns; // 斜め下がりの利き筋
021: boolean trapChk=true; // 利きゴマの表示をするか
022: int waitTime=1000; // 表示時間: JSlider で設定
023: ImageIcon queenOn; // コマの絵(黒)
024: ImageIcon queenTry; // コマの絵(灰)
025: ImageIcon queenChk; // コマの絵(赤)
026: ImageIcon queenOff; // 空白の絵
027: JButton gButton; // 開始・停止ボタン
028: final static String gButtongo = " go "; // 開始・停止ボタンの表示文字列
029: final static String gButtonst = "stop"; // 開始・停止ボタンの表示文字列
030:
031: EightQueen4(int board) {
032:
033: addWindowListener(new WindowAdapter() {
034: public void windowClosing(WindowEvent e) { System.exit(0); }
035: });
036: getContentPane().setLayout(new BorderLayout());
037:
038: // 色違いの queen アイコンを読み込み
039: queenOn = new ImageIcon( Toolkit.getDefaultToolkit().getImage( "queen-on.gif" ) ); // 黒
040: queenOff = new ImageIcon( Toolkit.getDefaultToolkit().getImage( "queen-off.gif" ) ); // 空白
041: queenTry = new ImageIcon( Toolkit.getDefaultToolkit().getImage( "queen-try.gif" ) ); // 灰色
042: queenChk = new ImageIcon( Toolkit.getDefaultToolkit().getImage( "queen-chk.gif" ) ); // 赤
043:
044: boardSize = board; // チェス盤の大きさ
045: pos = new int[boardSize]; // 駒の横位置用の配列
046: na = new int[boardSize]; // 斜め上がりの利き筋用の配列
047: ns = new int[boardSize]; // 斜め下がりの利き筋用の配列
048: cell = new JLabel[boardSize][boardSize]; // チェス盤のマス目
049: JPanel backp = new JPanel(new GridLayout(boardSize, boardSize)); // チェス盤
050: for(int i=0; i<boardSize; i++)
051: for(int j=0; j<boardSize; j++) {
052: cell[i][j] = new JLabel( queenOff ) ; // マス目を生成
053: backp.add( cell[i][j] ); // マス目をチェス盤に敷き詰め
054: }
055: getContentPane().add(backp, SwingConstants.CENTER); // チェス盤を Center に貼り付け
056:
057: title =new JLabel(boardSize + "-Queen ", SwingConstants.CENTER); // タイトル N-Queen
058: getContentPane().add(title, BorderLayout.NORTH); // North に貼り付け
059:
060: JRadioButton rbutton = new JRadioButton("解が見付かったら停止", true);
061: trapOnFound = true; // 初期値は、停止を指定
062: rbutton.addItemListener(new ItemListener() {
063: public void itemStateChanged(ItemEvent e) {
064: if(e.getStateChange()==ItemEvent.DESELECTED) trapOnFound = false;
065: else trapOnFound = true;
066: }
067: });
068: JRadioButton cbutton = new JRadioButton("利きゴマを表示", true);
069: trapChk = true; // 初期値は、表示と指定
070: cbutton.addItemListener(new ItemListener() {
071: public void itemStateChanged(ItemEvent e) {
072: if(e.getStateChange()==ItemEvent.DESELECTED) trapChk = false;
073: else trapChk = true;
074: }
075: });
076:
077: final JSlider slide = new JSlider(0, waitTime*2, waitTime); // スライダ
078: slide.addChangeListener(new ChangeListener() {
079: public void stateChanged(ChangeEvent e) {
080: waitTime = slide.getValue();
081: }
082: });
083:
084: gButton = new JButton(gButtongo);
085: gButton.setFont(new Font("Diolog", Font.BOLD, 16));
086: gButton.addActionListener(new ActionListener() {
087: public void actionPerformed(ActionEvent e) { // トグルボタン
088: String s = gButton.getText();
089: if( s.equals(gButtongo) ) { // go であれば
090: trap = false;
091: gButton.setText(gButtonst); // stop を表示
092: }
093: else { // stop であれば
094: trap = true;
095: gButton.setText(gButtongo); // go を表示
096: }
097: }
098: });
099:
100: JPanel southpan = new JPanel(new GridLayout(0,1)); // 縦1列に
101: southpan.add(rbutton); // ラジオボタン
102: southpan.add(cbutton); // ラジオボタン
103: southpan.add(slide); // スライダ
104: southpan.add(gButton); // go/stop ボタン
105: getContentPane().add(southpan, BorderLayout.SOUTH); // South に貼り付け
106: }
107:
108: void flash(int x, int y) { // 利きゴマの表示
109: if(trapChk && waitTime>=5){ // 表示指定 かつ 時間 > 5ミリ
110: cell[x][y].setIcon( queenChk ); // 利きゴマの色
111: sleep(waitTime / 2); // ちら!
112: cell[x][y].setIcon( queenOn ); // もとの色
113: }
114: }
115:
116: void checkAndSet(int n){ // n行以降に置いてみる
117: boolean ok; // 置けるかどうかの判定フラグ
118: if(n>=boardSize){ // 最後の行の次を調べようとしている
119: count++; // 解の個数
120: System.out.print(count + ". "); // 画面に表示
121: for(int i=0; i<boardSize; i++) //
122: System.out.print( pos[i] + " "); //
123: System.out.println(); //
124: title.setText(boardSize +"-Queen "+ count); // タイトルに見つかった個数を表示
125: if(trapOnFound) { // 見つかった時に一時停止
126: trap = true; // 停止フラグを設定
127: gButton.setText(gButtongo); // ボタンの表示を変更
128: sleep(trapTime); // 停止
129: }
130: }
131: else { // 調べる行がある場合
132: for(int k=0; k<boardSize; k++){ // 左端から右端まで
133: ok=true; // 「置ける」と仮設定
134: sleep(0); //
135: if(waitTime>5) { //
136: cell[n][k].setIcon( queenTry ) ; // 仮に置いた状態を表示
137: sleep(waitTime / 5); //
138: } //
139: for(int i=n-1; i>=0; i--){ // 今までに置いた駒について
140: if(pos[i]==k) { ok=false; // 縦の利き筋に駒が置かれている
141: flash(i, pos[i]); //
142: break; } //
143: if((n-k)==na[i]) { ok=false; // 斜め上がりの利き筋
144: flash(i, i-na[i]); //
145: break; } //
146: if((n+k)==ns[i]) { ok=false; // 斜め下がりの利き筋
147: flash(i, ns[i]-i); //
148: break; } //
149: } //
150: if(ok){ // いずれの利き筋にも駒がなかった
151: pos[n] = k; // ここに置く
152: cell[n][k].setIcon( queenOn ) ; // 駒のイメージを設定
153: sleep(waitTime); // ちら! と表示
154: na[n] = n-k; // 斜め上がりの利き筋を記録
155: ns[n] = n+k; // 斜め下がりの利き筋を記録
156: checkAndSet( n+1 ); // 次の行に置けるかどうかの判定
157: } //
158: cell[n][k].setIcon( queenOff) ; // 駒の表示を消す
159: } // for(int k)
160: } // if(n>=boardSize)
161: } // checkAndSet
162:
163: void sleep(int time) { // 一時停止
164: if(time>0) { //
165: try{ Thread.sleep(time);} // time ミリ秒
166: catch(InterruptedException ev) { } //
167: } //
168: while(trap) { // go ボタンが押されるまで停止
169: try{ Thread.sleep(trapTime);} //
170: catch(InterruptedException ev) { } //
171: }
172: }
173:
174: public void run() {
175: checkAndSet( 0 ); // 最上段から開始
176: }
177:
178: public static void main(String args[]) {
179:
180: int board = 8; // パラメタがなければ Eight Queen
181: if(args.length>0) board = Integer.parseInt(args[0]);
182:
183: EightQueen4 frame = new EightQueen4(board); // チェス盤の生成
184: frame.pack();
185: frame.setVisible(true);
186:
187: Thread thread = new Thread( frame ); // 開始
188: thread.start();
189: }
190:}