/******************************/ /* 8/15パズル */ /* coded by Y.Suganuma */ /******************************/ import java.io.*; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.Random; public class Test { public static void main(String args[]) throws IOException { Data dt = new Data(); } } /********************/ /* クラスDataの定義 */ /********************/ class Data extends JFrame implements ItemListener { int game = 0; // ゲームの種類 // =0 : 8パズル // =1 : 15パズル int i_set = 0; // 初期状態の設定方法 // =0 : 入力する // =1 : ランダム int goal = 0; // 目標 // =0 : 周辺を回る // =1 : 上から横並び int g[][]; // 目標状態 int p[][]; // 現在の状態 JComboBox <String> choice1, choice2, choice3; Data dt = this; /******************/ /* コンストラクタ */ /******************/ Data() { // JFrameクラスのコンストラクタの呼び出し super("データの入力"); // レイアウトの変更 Container cp = getContentPane(); cp.setBackground(Color.white); cp.setLayout(null); JPanel jp = new JPanel(); jp.setLayout(new GridLayout(4, 2, 5, 10)); jp.setBackground(Color.white); cp.add(jp); Font f = new Font("TimesRoman", Font.BOLD, 20); // スクロールリスト JLabel fill1 = new JLabel("ゲーム"); fill1.setFont(f); jp.add(fill1); choice1 = new JComboBox <String> (); choice1.setBackground(Color.white); choice1.setFont(f); choice1.addItem("8パズル"); choice1.addItem("15パズル"); jp.add(choice1); choice1.addItemListener(this); JLabel fill2 = new JLabel("初期設定"); fill2.setFont(f); jp.add(fill2); choice2 = new JComboBox <String> (); choice2.setBackground(Color.white); choice2.setFont(f); choice2.addItem("入力"); choice2.addItem("ランダム"); jp.add(choice2); choice2.addItemListener(this); JLabel fill3 = new JLabel("ゴール"); fill3.setFont(f); jp.add(fill3); choice3 = new JComboBox <String> (); choice3.setBackground(Color.white); choice3.setFont(f); choice3.addItem("回転"); choice3.addItem("横並び"); jp.add(choice3); choice3.addItemListener(this); // OK ボタンの設定 JLabel fill4 = new JLabel(" スタート?"); fill4.setFont(f); jp.add(fill4); JButton bt = new JButton("OK"); bt.addMouseListener(new ClickMouse()); bt.setFont(f); jp.add(bt); // Windowサイズを設定 setSize(300, 250); // ウィンドウを表示 setVisible(true); Insets in = getInsets(); jp.setLocation(10, 10); jp.setSize(300-in.left-in.right-20, 250-in.top-in.bottom-20); // イベントアダプタ addWindowListener(new WinEnd()); } /************************/ /* 選択されたときの処理 */ /************************/ public void itemStateChanged(ItemEvent e) { if (e.getItemSelectable() == choice1) { game = choice1.getSelectedIndex(); } if (e.getItemSelectable() == choice2) { i_set = choice2.getSelectedIndex(); } if (e.getItemSelectable() == choice3) { goal = choice3.getSelectedIndex(); } } /********************************/ /* OKボタンが押されたときの処理 */ /********************************/ class ClickMouse extends MouseAdapter { /************************************/ /* マウスがクリックされたときの処理 */ /************************************/ public void mouseClicked(MouseEvent e) { int i1, i2, k, k1, k2, n = 0; /* ゲームの種類 */ // 8パズル if (game == 0) { g = new int [3][3]; p = new int [3][3]; n = 3; } // 15パズル else { g = new int [4][4]; p = new int [4][4]; n = 4; } /* 初期状態と目標状態 */ // 初期状態を入力する場合 Initial initial; if (i_set == 0) initial = new Initial(dt); // 初期状態をランダムに決める場合 // 目標状態の決定 // 回転 else { if (goal == 0) { if (game == 0) { k = 1; for (i1 = 0; i1 < n; i1++) { g[0][i1] = k; k++; } k = 7; for (i1 = 0; i1 < n; i1++) { g[2][i1] = k; k--; } g[1][0] = 8; g[1][1] = 0; g[1][2] = 4; k1 = 1; k2 = 1; } else { k = 1; for (i1 = 0; i1 < n; i1++) { g[0][i1] = k; g[1][i1] = k + 11; k++; } g[1][3] = 5; k = 10; for (i1 = 0; i1 < n; i1++) { g[3][i1] = k; k--; } g[2][0] = 11; g[2][1] = 0; g[2][2] = 15; g[2][3] = 6; k1 = 2; k2 = 1; } } // 横並び else { k = 1; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { g[i1][i2] = k; k++; } } g[n-1][n-1] = 0; k1 = n - 1; k2 = n - 1; } // 初期状態の決定 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) p[i1][i2] = g[i1][i2]; } for (i1 = 0; i1 < 200; i1++) { k = (int)(Math.random() * 4.0); switch (k) { case 0: // 上へ移動 if (k1 > 0) { p[k1][k2] = p[k1-1][k2]; p[k1-1][k2] = 0; k1--; } break; case 1: // 下へ移動 if (k1 < n-1) { p[k1][k2] = p[k1+1][k2]; p[k1+1][k2] = 0; k1++; } break; case 2: // 左へ移動 if (k2 > 0) { p[k1][k2] = p[k1][k2-1]; p[k1][k2-1] = 0; k2--; } break; default: // 右へ移動 if (k2 < n-1) { p[k1][k2] = p[k1][k2+1]; p[k1][k2+1] = 0; k2++; } break; } } // 目標状態の表示 Goal goal_s = new Goal(dt); } } } /************/ /* 終了処理 */ /************/ class WinEnd extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } } /**************************/ /* クラスInitialの定義 */ /* (初期状態の入力) */ /**************************/ class Initial extends JFrame { int err = 0; // エラーの有無 private int n; // 行・列の数 private Data dt; private Initial in = this; JTextField a[][]; JLabel f[]; Error_p ep; /****************************************/ /* コンストラクタ */ /* dt_i : Dataクラスのオブジェクト */ /****************************************/ Initial(Data dt_i) { // JFrameクラスのコンストラクタの呼び出し super("初期状態"); // ゲームの種類とレイアウトの変更 int i1, i2; n = (dt_i.game == 0) ? 3 : 4; dt = dt_i; a = new JTextField [n][n]; f = new JLabel [n-1]; Container cp = getContentPane(); cp.setBackground(Color.white); cp.setLayout(null); JPanel jp = new JPanel(); jp.setBackground(Color.white); cp.add(jp); jp.setLayout(new BorderLayout(5, 10)); JPanel pn = new JPanel(); pn.setBackground(Color.white); pn.setLayout(new GridLayout(n, n+1, 5, 10)); jp.add(pn, BorderLayout.NORTH); Font fn = new Font("TimesRoman", Font.BOLD, 20); // テキストフィールドの設定 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { a[i1][i2] = new JTextField(2); a[i1][i2].setFont(fn); pn.add(a[i1][i2]); } if (i1 < n-1) { f[i1] = new JLabel(); pn.add(f[i1]); } } // OK ボタンの設定 JButton bt = new JButton("OK"); bt.setFont(fn); bt.addMouseListener(new ClickMouse()); pn.add(bt); // メッセージパネルの追加 ep = new Error_p(this); ep.setBackground(Color.white); jp.add(ep, BorderLayout.CENTER); // Windowサイズを設定 if (dt.game == 0) setSize(350, 250); else setSize(400, 280); // ウィンドウを表示 setVisible(true); Insets in = getInsets(); jp.setLocation(10, 10); if (dt.game == 0) jp.setSize(350-in.left-in.right-20, 250-in.top-in.bottom-20); else jp.setSize(400-in.left-in.right-20, 280-in.top-in.bottom-20); // イベントアダプタ addWindowListener(new WinEnd()); } /********************************/ /* OKボタンが押されたときの処理 */ /********************************/ class ClickMouse extends MouseAdapter { /************************************/ /* マウスがクリックされたときの処理 */ /************************************/ public void mouseClicked(MouseEvent e) { int i1, i2, i3, i4, k, k1; err = 0; /* 入力データの処理 */ for (i1 = 0; i1 < n && err == 0; i1++) { for (i2 = 0; i2 < n && err == 0; i2++) { if ((a[i1][i2].getText()).length() <= 0) dt.p[i1][i2] = 0; else dt.p[i1][i2] = Integer.parseInt(a[i1][i2].getText()); k1 = (dt.game == 0) ? 8 : 15; if (dt.p[i1][i2] < 0 || dt.p[i1][i2] > k1) err = 1; else { for (i3 = 0; i3 <= i1 && err == 0; i3++) { k1 = (i3 == i1) ? i2 : n; for (i4 = 0; i4 < k1 && err == 0; i4++) { if (dt.p[i1][i2] == dt.p[i3][i4]) err = 1; } } } } } /* 目標状態 */ ep.repaint(); if (err == 0) { // 回転 if (dt.goal == 0) { if (dt.game == 0) { k = 1; for (i1 = 0; i1 < n; i1++) { dt.g[0][i1] = k; k++; } k = 7; for (i1 = 0; i1 < n; i1++) { dt.g[2][i1] = k; k--; } dt.g[1][0] = 8; dt.g[1][1] = 0; dt.g[1][2] = 4; } else { k = 1; for (i1 = 0; i1 < n; i1++) { dt.g[0][i1] = k; dt.g[1][i1] = k + 11; k++; } dt.g[1][3] = 5; k = 10; for (i1 = 0; i1 < n; i1++) { dt.g[3][i1] = k; k--; } dt.g[2][0] = 11; dt.g[2][1] = 0; dt.g[2][2] = 15; dt.g[2][3] = 6; } } // 横並び else { k = 1; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { dt.g[i1][i2] = k; k++; } } dt.g[n-1][n-1] = 0; } // 目標状態の表示 in.setVisible(false); Goal goal_s = new Goal(dt); } } } /************/ /* 終了処理 */ /************/ class WinEnd extends WindowAdapter { public void windowClosing(WindowEvent e) { in.setVisible(false); } } } /**************************/ /* エラーメッセージの表示 */ /**************************/ class Error_p extends JPanel { Initial in; Error_p(Initial in1) { in = in1; } public void paintComponent (Graphics g) { super.paintComponent(g); // 親クラスの描画(必ず必要) // フォントの設定 Font f = new Font("TimesRoman", Font.BOLD, 20); g.setFont(f); // エラーメッセージの出力 int x = 10; int y = 25; if (in.err == 0) g.drawString(" ", x, y); else { g.setColor(Color.red); g.drawString("*** Error ***", x, y); g.setColor(Color.black); } } } /**********************/ /* クラスGoalの定義 */ /* (目標状態の表示) */ /**********************/ class Goal extends JFrame { int size = 50; // コマの大きさ private Data dt; private Goal gl = this; /****************************************/ /* コンストラクタ */ /* dt_i : Dataクラスのオブジェクト */ /****************************************/ Goal(Data dt_i) { // JFrameクラスのコンストラクタの呼び出し super("ゴール"); // データの設定 dt = dt_i; Container cp = getContentPane(); cp.setBackground(Color.white); cp.setLayout(null); JPanel jp = new JPanel(); jp.setBackground(Color.white); cp.add(jp); jp.setLayout(new BorderLayout(5, 10)); // 描画パネルの追加 Draw_p dp = new Draw_p(dt, this); dp.setBackground(Color.white); jp.add(dp, BorderLayout.CENTER); // 実行ボタンの設定 JButton bt = new JButton("ゲームの実行"); bt.addMouseListener(new ClickMouse()); bt.setFont(new Font("TimesRoman", Font.BOLD, 20)); jp.add(bt, BorderLayout.SOUTH); // Windowの大きさの設定 if (dt_i.game == 0) setSize(3*(size+10)+70, 3*(size+10)+150); else setSize(4*(size+10)+70, 4*(size+10)+150); // ウィンドウを表示 setVisible(true); Insets in = getInsets(); jp.setLocation(10, 10); if (dt.game == 0) jp.setSize(250-in.left-in.right-20, 330-in.top-in.bottom-20); else jp.setSize(310-in.left-in.right-20, 390-in.top-in.bottom-20); // イベントアダプタ addWindowListener(new WinEnd()); } /**********************************/ /* 実行ボタンが押されたときの処理 */ /**********************************/ class ClickMouse extends MouseAdapter { /************************************/ /* マウスがクリックされたときの処理 */ /************************************/ public void mouseClicked(MouseEvent e) { Run run = new Run(dt); } } /************/ /* 終了処理 */ /************/ class WinEnd extends WindowAdapter { public void windowClosing(WindowEvent e) { gl.setVisible(false); } } } class Draw_p extends JPanel { private Data dt; private Goal gl; Draw_p(Data dt_i, Goal gl_i) { dt = dt_i; gl = gl_i; } /********/ /* 描画 */ /********/ public void paintComponent (Graphics g) { super.paintComponent(g); // 親クラスの描画(必ず必要) int i1, i2, x, y; int n = (dt.game == 0) ? 3 : 4; // 四角形を描く x = 20; y = 5; g.setColor(Color.cyan); for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { g.fill3DRect(x, y, gl.size, gl.size, true); x += (gl.size + 10); } x = 20; y += (gl.size + 10); } // 数字を描く x = 20; y = 5; g.setColor(Color.black); g.setFont(new Font("TimesRoman", Font.BOLD, gl.size)); for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (dt.g[i1][i2] > 0) { if (dt.g[i1][i2] < 10) g.drawString(Integer.toString(dt.g[i1][i2]), x+11, y+gl.size-7); else g.drawString(Integer.toString(dt.g[i1][i2]), x-5, y+gl.size-7); } x += (gl.size + 10); } x = 20; y += (gl.size + 10); } } } /********************/ /* クラスRunの定義 */ /* (ゲームの実行) */ /********************/ class Run extends JFrame { int size = 50; // コマの大きさ int count = 0; // コマを動かした回数 int ok = 0; // ゲームの終了 Data dt; private Draw_p_r dp; private Run rn = this; /****************************************/ /* コンストラクタ */ /* dt_i : Dataクラスのオブジェクト */ /****************************************/ Run(Data dt_i) { // Frameクラスのコンストラクタの呼び出し super("ゲーム"); // データの設定 dt = dt_i; setBackground(Color.white); Container cp = getContentPane(); cp.setBackground(Color.white); cp.setLayout(null); JPanel jp = new JPanel(); jp.setBackground(Color.white); cp.add(jp); jp.setLayout(new BorderLayout(5, 10)); // 描画パネルの追加 dp = new Draw_p_r(dt, this); dp.setBackground(Color.white); jp.add(dp, BorderLayout.CENTER); // Windowの大きさの設定 if (dt.game == 0) setSize(3*(size+10)+70, 3*(size+10)+150); else setSize(4*(size+10)+70, 4*(size+10)+150); // ウィンドウを表示 setVisible(true); Insets in = getInsets(); jp.setLocation(10, 10); if (dt.game == 0) jp.setSize(250-in.left-in.right-20, 330-in.top-in.bottom-20); else jp.setSize(310-in.left-in.right-20, 390-in.top-in.bottom-20); // イベントアダプタ addWindowListener(new WinEnd()); addMouseListener(new ClickMouse()); } /************************************/ /* マウスがクリックされたときの処理 */ /************************************/ class ClickMouse extends MouseAdapter { public void mouseClicked(MouseEvent e) { int i1, i2, k1 = -1, k2 = -1, sw, x, xp, y, yp; int n = (dt.game == 0) ? 3 : 4; // マウスの位置 Insets in = getInsets(); xp = e.getX() - in.left; yp = e.getY() - in.top; // クリックされたコマを決定 x = 20; y = 5; for (i1 = 0; i1 < n && k1 < 0; i1++) { for (i2 = 0; i2 < n && k1 < 0; i2++) { if (xp > x && xp < x+size && yp > y && yp < y+size) { k1 = i1; k2 = i2; } else x += (size + 10); } x = 20; y += (size + 10); } // コマの移動 if (k1 >= 0 && k2 >= 0) { sw = 0; if (k1 > 0) { // 上へ移動 if (dt.p[k1-1][k2] == 0) { dt.p[k1-1][k2] = dt.p[k1][k2]; dt.p[k1][k2] = 0; sw = 1; } } if (sw == 0 && k1 < n-1) { // 下へ移動 if (dt.p[k1+1][k2] == 0) { dt.p[k1+1][k2] = dt.p[k1][k2]; dt.p[k1][k2] = 0; sw = 1; } } if (sw == 0 && k2 > 0) { // 左へ移動 if (dt.p[k1][k2-1] == 0) { dt.p[k1][k2-1] = dt.p[k1][k2]; dt.p[k1][k2] = 0; sw = 1; } } if (sw == 0 && k2 < n-1) { // 右へ移動 if (dt.p[k1][k2+1] == 0) { dt.p[k1][k2+1] = dt.p[k1][k2]; dt.p[k1][k2] = 0; sw = 1; } } // ゴールに達したか否かのチェックと描画 if (sw > 0) { count++; ok = 1; for (i1 = 0; i1 < n && ok > 0; i1++) { for (i2 = 0; i2 < n && ok > 0; i2++) { if (dt.g[i1][i2] != dt.p[i1][i2]) ok = 0; } } dp.repaint(); } } } } /************/ /* 終了処理 */ /************/ class WinEnd extends WindowAdapter { public void windowClosing(WindowEvent e) { rn.setVisible(false); } } } class Draw_p_r extends JPanel { private Data dt; private Run rn; Draw_p_r(Data dt_i, Run rn_i) { dt = dt_i; rn = rn_i; } /********/ /* 描画 */ /********/ public void paintComponent (Graphics g) { super.paintComponent(g); // 親クラスの描画(必ず必要) int i1, i2, x, y; int n = (dt.game == 0) ? 3 : 4; // 四角形を描く x = 15; y = 5; g.setColor(Color.cyan); for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { g.fill3DRect(x, y, rn.size, rn.size, true); x += (rn.size + 10); } x = 15; y += (rn.size + 10); } // 数字を描く x = 15; y = 5; g.setColor(Color.black); g.setFont(new Font("TimesRoman", Font.BOLD, rn.size)); for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (dt.p[i1][i2] > 0) { if (dt.p[i1][i2] < 10) g.drawString(Integer.toString(dt.p[i1][i2]), x+13, y+rn.size-7); else g.drawString(Integer.toString(dt.p[i1][i2]), x-5, y+rn.size-7); } x += (rn.size + 10); } x = 15; y += (rn.size + 10); } // ゲームの終了 if (rn.ok > 0) { Insets in = rn.getInsets(); x = 10; if (dt.game == 0) y = 330 - in.top - in.bottom - 30; else y = 390 - in.top - in.bottom - 30; g.setFont(new Font("TimesRoman", Font.PLAIN, 20)); g.drawString("Congratulation!!", x, y-25); g.drawString("Number of Trial : "+Integer.toString(rn.count), x, y); } } }