#acl All:
== ピースを動かす ==
ピースを1つ取り除いてできた空白部分を使って
移動するための処理を記述します。
前回作成したプログラムに書き加えて完成させましょう。
このページの最後にプログラムの修正が必要な部分のみを示しています。
----
=== マウスを使えるようにする ===
マウスを使えるようにする方法は前に述べた通りです。
1.import文を追加
. 3行目
2.クラス宣言にimplements !MouseListenerを追加
. 5行目
3.addMouseListener(this)を追加
. コンストラクタ内に記述します。
. 16行目
4.マウスイベントに対する5つのメソッドを記述
. public void mousePressed(!MouseEvent e)
. public void mouseEntered(!MouseEvent e)
. public void mouseExited(!MouseEvent e)
. public void mouseReleased(!MouseEvent e)
. public void mouseClicked(!MouseEvent e)
. 44行目以下
----
=== 変数の宣言と初期化 ===
空白部分の位置を変数 spx,spy を使って表すことにします。
. int型の変数で、空白の位置は横spx、縦spyであることを表します。
インスタンス変数として宣言します。
. 12行目
. int spx, spy;
初期化
. 最初は右下隅のピースを取り除いた位置です。
. shokikaメソッド内で初期化します。
. 前回作成したshokikaメソッドの中に追加すること。
. 22,23行目
. spx = yoko-1;
. spy = tate-1;
----
=== 空白部分の表示 ===
spx,spyで示された位置は空白であることを示す表示を行います。
. この処理はpaintComponent内に追加します。
forループを使って各位置の画像を表示したあとで、空白の位置は1色で塗りつぶします。
ループ内でspx,spyの位置にも何か表示されますが、その後すぐに塗りつぶすことになります。
(後で述べるように、ban[spx][spy]に入っているのは古い値であって正しい値ではありません。)
. 40,41行目
. g.setColor(Color.lightGray);
. g.fillRect(spx*haba, spy*haba, haba, haba);
colorは好みの色を指定してください。
長方形の塗りつぶしを使っています。
----
=== ボタンが押されたときの処理 ===
変数 spx,spy の値をmousePressedメソッド内で、押された場所に応じて更新します。
mousePressedメソッドでは引数(!MouseEvent e)を通して
ボタンが押された位置を得ることができます。
. e.getX() でX座標(左からのピクセル値)が得られます。
. e.getY() でY座標(上からのピクセル値)が得られます。
この値を盤の座標値に変換するには
1つのピースの縦横の大きさで割ればよい。<
>
ピースの大きさは変数habaに入っているので、
クリックされた盤座標をx,yに得るために次を行います。
. 48,49行目
. x = e.getX() / haba;
. y = e.getY() / haba;
ボタンが押された位置が盤の外であるときは、以下の処理は行いません。<
>
盤の内部であるかどうかはx,yの値で判定できます。<
>
x,yとも負の数にはならないので、4方向のうち2方向の判定だけを行っています。
. 50,51行目
. if(x >= yoko || y >= tate)
. return;
==== ピースを移動する処理 ====
○の位置が空白部分で、そのすぐ右のAの位置でボタンが押された場合を考えます。
. {{attachment:idou1.png}}
空白の位置、ボタンが押された位置を表す変数の値は、図の場合には次のようになっています。
. spx は 1
. spy は 2
. x は 2
. y は 2
次の2つの処理を順に行うよう記述します。
. 1)Aの位置にあるピースをすぐ左の空白位置に移動します。
. 2)空白位置をAの位置に変更します。
1)
Aの位置どのピースがあるかはban[x][y]の値として記憶しており、
この値を空白位置である(spx,spy)に移すには
. ban[spx][spy] = ban[x][y]
を行えばよい。
(注意:
ban[x][y]にも同じ値が残ったままになっている。)
2)spx,spyの値を新しい空白位置の値であるx,yに修正します。
. spx = x;
. spy = y;
以上をまとめると次の3行になります。
. 54,56行目
. ban[spx][spy] = ban[x][y]
. spx = x;
. spy = y;
空白の右隣のAの位置で考えましたが、B,C,Dの位置でも同様の処理でよいことがわかります。
----
=== 演習 ===
ピースを移動する処理は、空白箇所の隣でボタンが押されたときだけ行います。
このための条件を
<>(52行目)
の位置に記述しプログラムを完成させなさい。
----
以下のプログラムでは、修正が必要な箇所のみ示しています。
{{{#!java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Game13 extends JPanel implements MouseListener
{
int haba;
int yoko, tate;
String fname;
Image img;
int[][] ban;
int spx, spy;
Game13()
{
addMouseListener(this);
}
void shokika()
{
...
spx = yoko-1;
spy = tate-1;
}
public void paintComponent(Graphics g)
{
int dx, dy, sx, sy;
for(dy = 0; dy < tate; dy++)
for(dx = 0; dx < yoko; dx++)
{
sx = ...;
sy = ...;
g.drawImage(img,
dx*haba, dy*haba, (dx+1)*haba, (dy+1)*haba,
sx*haba, sy*haba, (sx+1)*haba, (sy+1)*haba,
this);
}
g.setColor(Color.lightGray);
g.fillRect(spx*haba, spy*haba, haba, haba);
}
public void mousePressed(MouseEvent e)
{
int x, y;
x = e.getX() / haba;
y = e.getY() / haba;
if(x >= yoko || y >= tate)
return;
if( 演習 )
{
ban[spx][spy] = ban[x][y];
spx = x;
spy = y;
repaint();
}
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
public void mouseClicked(MouseEvent e) { }
}}}