#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) { } }}}