/******************************/
/* 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);
}
}
}