6494
コメント:
|
5560
|
削除された箇所はこのように表示されます。 | 追加された箇所はこのように表示されます。 |
行 1: | 行 1: |
#acl All: | |
行 4: | 行 3: |
ピースを1つ取り除いてできた空白部分を使って | ピースを1つ取り除いてできた空白の箇所を使って |
行 7: | 行 6: |
前回作成したプログラムに書き加えて完成させましょう。 | ---- === 空白の箇所の表現 === |
行 9: | 行 9: |
このページの最後にプログラムの修正が必要な部分のみを示しています。 | どこに空白があるかを表すために、インスタンス変数を使います。 * spxで空白の横方向の位置を、0~3の値で表すものとします。 * spyで空白の縦方向の位置を、0~3の値で表すものとします。 例えば、spx=0, spy=2 のときは 上から3番目の左端が空白。 === 初期化 === 最初は右下隅のピースを取り除いた位置です。 したがって値は . spx = 3 . spy = 3 空白箇所は右下のピースを取り除いたものですから、 配列要素の値は右下のピースの値としておきます。 . ban[spx][spy] = 15 |
行 12: | 行 29: |
=== マウスを使えるようにする === マウスを使えるようにする方法は前に述べた通りです。 |
=== 空白箇所の表示 === paintComponent内に記述。 |
行 15: | 行 32: |
1.import文を追加 . 3行目 |
spx,spyで表された場所は空白であることを示すため、 1色で塗りつぶします。 |
行 18: | 行 35: |
2.クラス宣言にimplements !MouseListenerを追加 . 5行目 |
クリック時の処理の演習ではcx,cyで示された位置を塗りつぶしていましたが、 spx,spyが示す箇所を塗りつぶすように修正します。 |
行 21: | 行 38: |
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は好みの色を指定してください。 長方形の塗りつぶしを使っています。 |
塗りつぶしの色は好みのものを指定してください。 |
行 65: | 行 41: |
変数 spx,spy の値をmousePressedメソッド内で、押された場所に応じて更新します。 | mousePressed内に記述。 |
行 67: | 行 43: |
mousePressedメソッドでは引数(!MouseEvent e)を通して ボタンが押された位置を得ることができます。 . e.getX() でX座標(左からのピクセル値)が得られます。 . e.getY() でY座標(上からのピクセル値)が得られます。 この値を盤の座標値に変換するには 1つのピースの縦横の大きさで割ればよい。<<BR>> ピースの大きさは変数habaに入っているので、 クリックされた盤座標をx,yに得るために次を行います。 . 48,49行目 . x = e.getX() / haba; . y = e.getY() / haba; |
クリック時の処理の演習では クリックされた座標x,yから対応する位置cx,cyを求めました。 |
行 79: | 行 46: |
ボタンが押された位置が盤の外であるときは、以下の処理は行いません。<<BR>> 盤の内部であるかどうかはx,yの値で判定できます。<<BR>> x,yとも負の数にはならないので、4方向のうち2方向の判定だけを行っています。 . 50,51行目 . if(x >= yoko || y >= tate) . return; |
. cx,cyはmousePressedメソッド内でしか使わないので、(インスタンス変数ではなく)メソッド内の変数として宣言します。 このcx,cyとspx,spyの値を比較し、 クリックされた位置のピースが移動可能かどうか判定し、 可能な場合は移動する処理を記述します。 ==== 移動可能かどうかの判定 ==== 空白箇所の上下左右のとなりにあるピースの上でクリックされたときは、 そのピースをスライドして移動できる。 例えば丸で示した位置が空白のとき . {{attachment:idou1.png}} クリックされた位置がA,B,C,Dのどれかであればよい。 空白の位置はspx,spyで、クリックされた位置はcx,cyで表されているので、 これを用いて判定を行う。 例えば、丸の位置が空白部分でAの位置でボタンが押された場合、変数の値は次のようになっています。 . spx は 1 . spy は 2 . cx は 2 . cy は 2 |
行 88: | 行 72: |
○の位置が空白部分で、そのすぐ右のAの位置でボタンが押された場合を考えます。 | 丸の位置が空白部分で、そのすぐ右のAの位置でボタンが押された場合を考えます。 |
行 90: | 行 74: |
. {{attachment:idou1.png}} 空白の位置、ボタンが押された位置を表す変数の値は、図の場合には次のようになっています。 . spx は 1 . spy は 2 . x は 2 . y は 2 次の2つの処理を順に行うよう記述します。 |
次の処理を順に行ないます。 |
行 101: | 行 77: |
1) Aの位置どのピースがあるかはban[x][y]の値として記憶しており、 |
. 3)新しい空白位置に対応する値を代入します。 1)Aの位置どのピースがあるかはban[cx][cy]の値として記憶しており、 |
行 104: | 行 80: |
. ban[spx][spy] = ban[x][y] | . ban[spx][spy] = ban[cx][cy] |
行 106: | 行 82: |
(注意: ban[x][y]にも同じ値が残ったままになっている。) |
|
行 109: | 行 83: |
2)spx,spyの値を新しい空白位置の値であるx,yに修正します。 . spx = x; . spy = y; |
2)spx,spyの値を新しい空白位置の値であるcx,cyに修正します。 . spx = cx . spy = cy |
行 113: | 行 87: |
以上をまとめると次の3行になります。 . 54~56行目 . ban[spx][spy] = ban[x][y] . spx = x; . spy = y; 空白の右隣のAの位置で考えましたが、B,C,Dの位置でも同様の処理でよいことがわかります。 |
3)空白位置に対応する値(15)を代入します。 . ban[spx][spy] = 15 以上をまとめると次のようになります。 . ban[spx][spy] = ban[cx][cy]; . spx = cx; . spy = cy; . ban[spx][spy] = 15; 空白の右隣のAの位置で考えましたが、 B,C,Dの位置でもこの命令でよいことを理解しておくこと。 |
行 120: | 行 98: |
=== 演習 === ピースを移動する処理は、空白箇所の隣でボタンが押されたときだけ行います。 条件が成り立つときだけ、ピースを移動する処理を行いrepaintを指示します。 ボタンが押された位置が空白箇所の隣であるかを判定する条件を <<Color(red:演習(52行目))>> の位置に記述しプログラムを完成させなさい。 ヒント . if( Aの位置か || Bの位置か || Cの位置か || Dの位置か ) ---- 以下のプログラムでは、修正が必要な箇所のみ示しています。 {{{#!java |
=== プログラム === {{{#!java |
行 139: | 行 104: |
public class Game13 extends JPanel implements MouseListener | public class Game6 extends JPanel implements MouseListener |
行 141: | 行 106: |
int haba; int yoko, tate; String fname; |
|
行 148: | 行 110: |
Game13() | Game6() |
行 150: | 行 112: |
ImageIcon ii = new ImageIcon("game0.png"); img = ii.getImage(); |
|
行 151: | 行 115: |
ban = new int[4][4]; shokika(); spx = 3; spy = 3; |
|
行 155: | 行 123: |
... spx = yoko-1; spy = tate-1; |
int x, y; for (x = 0; x < 4; x++) for (y = 0; y < 4; y++) ban[x][y] = x + y*4; |
行 159: | 行 129: |
行 162: | 行 132: |
int dx, dy, sx, sy; for(dy = 0; dy < tate; dy++) for(dx = 0; dx < yoko; dx++) |
int w, h, ax, ay, sx, sy, x, y; w = 100; h = 100; for (x = 0; x < 4; x++) for (y = 0; y < 4; y++) |
行 167: | 行 138: |
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); |
ax = x*100 ; ay = y*100 ; sx = (ban[x][y] % 4)*100 ; sy = (ban[x][y] / 4)*100 ; g.drawImage(img, ax,ay,ax+w,ay+h, sx,sy,sx+w,sy+h, this); |
行 174: | 行 144: |
g.setColor(Color.lightGray); g.fillRect(spx*haba, spy*haba, haba, haba); |
g.setColor(Color.blue); g.fillRect(spx*100, spy*100, 100, 100); |
行 177: | 行 147: |
行 180: | 行 150: |
int x, y; x = e.getX() / haba; y = e.getY() / haba; if(x >= yoko || y >= tate) return; if( 演習 ) |
int x, y, cx, cy; x = e.getX(); y = e.getY(); cx = x / 100; cy = y / 100; if (cx == spx && cy == spy-1 || cx == spx && cy == spy+1 || cy == spy && cx == spx-1 || cy == spy && cx == spx+1) |
行 188: | 行 158: |
ban[spx][spy] = ban[x][y]; spx = x; spy = y; |
ban[spx][spy] = ban[cx][cy]; spx = cx; spy = cy; ban[spx][spy] = 15; |
行 194: | 行 165: |
行 198: | 行 168: |
public void mouseClicked(MouseEvent e) { } }}} |
public void mouseClicked(MouseEvent e) { } public static void main(String[] args) { JFrame f; f = new JFrame(); f.setVisible(true); f.setTitle("15Game"); f.setSize(420, 450); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add( new Game6() ); } } }}} ---- === 演習 === ボタンが押された位置が空白箇所の隣であるかを判定する条件を ? の位置に記述しプログラムを完成させなさい。 |
ピースを動かす
ピースを1つ取り除いてできた空白の箇所を使って 移動するための処理を記述します。
空白の箇所の表現
どこに空白があるかを表すために、インスタンス変数を使います。
- spxで空白の横方向の位置を、0~3の値で表すものとします。
- spyで空白の縦方向の位置を、0~3の値で表すものとします。
例えば、spx=0, spy=2 のときは 上から3番目の左端が空白。
初期化
最初は右下隅のピースを取り除いた位置です。 したがって値は
- spx = 3
- spy = 3
空白箇所は右下のピースを取り除いたものですから、 配列要素の値は右下のピースの値としておきます。
- ban[spx][spy] = 15
空白箇所の表示
paintComponent内に記述。
spx,spyで表された場所は空白であることを示すため、 1色で塗りつぶします。
クリック時の処理の演習ではcx,cyで示された位置を塗りつぶしていましたが、 spx,spyが示す箇所を塗りつぶすように修正します。
塗りつぶしの色は好みのものを指定してください。
ボタンが押されたときの処理
mousePressed内に記述。
クリック時の処理の演習では クリックされた座標x,yから対応する位置cx,cyを求めました。
- cx,cyはmousePressedメソッド内でしか使わないので、(インスタンス変数ではなく)メソッド内の変数として宣言します。
このcx,cyとspx,spyの値を比較し、 クリックされた位置のピースが移動可能かどうか判定し、 可能な場合は移動する処理を記述します。
移動可能かどうかの判定
空白箇所の上下左右のとなりにあるピースの上でクリックされたときは、 そのピースをスライドして移動できる。
例えば丸で示した位置が空白のとき
クリックされた位置がA,B,C,Dのどれかであればよい。
空白の位置はspx,spyで、クリックされた位置はcx,cyで表されているので、 これを用いて判定を行う。
例えば、丸の位置が空白部分でAの位置でボタンが押された場合、変数の値は次のようになっています。
- spx は 1
- spy は 2
- cx は 2
- cy は 2
ピースを移動する処理
丸の位置が空白部分で、そのすぐ右のAの位置でボタンが押された場合を考えます。
次の処理を順に行ないます。
- 1)Aの位置にあるピースをすぐ左の空白位置に移動します。
- 2)空白位置をAの位置に変更します。
- 3)新しい空白位置に対応する値を代入します。
1)Aの位置どのピースがあるかはban[cx][cy]の値として記憶しており、 この値を空白位置である(spx,spy)に移すには
- ban[spx][spy] = ban[cx][cy]
を行えばよい。
2)spx,spyの値を新しい空白位置の値であるcx,cyに修正します。
- spx = cx
- spy = cy
3)空白位置に対応する値(15)を代入します。
- ban[spx][spy] = 15
以上をまとめると次のようになります。
- ban[spx][spy] = ban[cx][cy];
- spx = cx;
- spy = cy;
- ban[spx][spy] = 15;
空白の右隣のAの位置で考えましたが、 B,C,Dの位置でもこの命令でよいことを理解しておくこと。
プログラム
1 import javax.swing.*; 2 import java.awt.*; 3 import java.awt.event.*; 4 5 public class Game6 extends JPanel implements MouseListener 6 { 7 Image img; 8 int[][] ban; 9 int spx, spy; 10 11 Game6() 12 { 13 ImageIcon ii = new ImageIcon("game0.png"); 14 img = ii.getImage(); 15 addMouseListener(this); 16 ban = new int[4][4]; 17 shokika(); 18 spx = 3; 19 spy = 3; 20 } 21 22 void shokika() 23 { 24 int x, y; 25 26 for (x = 0; x < 4; x++) 27 for (y = 0; y < 4; y++) 28 ban[x][y] = x + y*4; 29 } 30 31 public void paintComponent(Graphics g) 32 { 33 int w, h, ax, ay, sx, sy, x, y; 34 w = 100; 35 h = 100; 36 for (x = 0; x < 4; x++) 37 for (y = 0; y < 4; y++) 38 { 39 ax = x*100 ; 40 ay = y*100 ; 41 sx = (ban[x][y] % 4)*100 ; 42 sy = (ban[x][y] / 4)*100 ; 43 g.drawImage(img, ax,ay,ax+w,ay+h, sx,sy,sx+w,sy+h, this); 44 } 45 g.setColor(Color.blue); 46 g.fillRect(spx*100, spy*100, 100, 100); 47 } 48 49 public void mousePressed(MouseEvent e) 50 { 51 int x, y, cx, cy; 52 x = e.getX(); 53 y = e.getY(); 54 cx = x / 100; 55 cy = y / 100; 56 if (cx == spx && cy == spy-1 || cx == spx && cy == spy+1 || 57 cy == spy && cx == spx-1 || cy == spy && cx == spx+1) 58 { 59 ban[spx][spy] = ban[cx][cy]; 60 spx = cx; 61 spy = cy; 62 ban[spx][spy] = 15; 63 repaint(); 64 } 65 } 66 public void mouseEntered(MouseEvent e) { } 67 public void mouseExited(MouseEvent e) { } 68 public void mouseReleased(MouseEvent e) { } 69 public void mouseClicked(MouseEvent e) { } 70 71 public static void main(String[] args) 72 { 73 JFrame f; 74 75 f = new JFrame(); 76 f.setVisible(true); 77 f.setTitle("15Game"); 78 f.setSize(420, 450); 79 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 80 f.add( new Game6() ); 81 } 82 }
演習
ボタンが押された位置が空白箇所の隣であるかを判定する条件を ? の位置に記述しプログラムを完成させなさい。