welcome: please sign in
location: "ピースを動かす"の差分
30と44のリビジョン間の差分 (その間の編集: 14回)
2010-01-12 02:32:38時点のリビジョン30
サイズ: 6582
編集者: masahiko
コメント:
2012-01-12 07:09:21時点のリビジョン44
サイズ: 5495
編集者: masahiko
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 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
行 140: 行 104:
public class Game13 extends JPanel implements MouseListener public class Game6 extends JPanel implements MouseListener
行 142: 行 106:
 int haba;
 int yoko, tate;
 String fname;
行 149: 行 110:
 Game13()  Game6()
行 151: 行 112:
  ImageIcon ii = new ImageIcon("game0.png");
  img = ii.getImage();
行 152: 行 115:
  ban = new int[4][4];
  shokika();
  spx = 3;
  spy = 3;
行 156: 行 123:
  ...
  spx = yoko-1;
  spy = tate-1;
  盤の表現の演習
行 160: 行 125:
 
行 163: 行 128:
  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++)
行 168: 行 134:
    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 = 盤の表示の演習 ;
    ay = 盤の表示の演習 ;
    sx = 盤の表示の演習 ;
    sy = 盤の表示の演習 ;
    g.drawImage(img, 画像を表示するの演習, this);
行 175: 行 140:
  g.setColor(Color.lightGray);
  g.fillRect(spx*haba, spy*haba, haba, haba);
  g.setColor(Color.blue);
  g.fillRect(spx*100, spy*100, 100, 100);
行 178: 行 143:
 
行 181: 行 146:
  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
= クリック時の処理の演習;
  cy = クリック時の処理の演習
;
  if ( 今回の演習 )
行 189: 行 153:
   ban[spx][spy] = ban[x][y];
   spx = x;
   spy = y;
   ban[spx][spy] = ban[cx][cy];
   spx = cx;
   spy = cy;
   ban[spx][spy] = 15;
行 195: 行 160:
 
行 199: 行 163:
 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の値を比較し、 クリックされた位置のピースが移動可能かどうか判定し、 可能な場合は移動する処理を記述します。

移動可能かどうかの判定

空白箇所の上下左右のとなりにあるピースの上でクリックされたときは、 そのピースをスライドして移動できる。

例えば丸で示した位置が空白のとき

  • idou1.png

クリックされた位置が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                 盤の表現の演習
      25         }
      26         
      27         public void paintComponent(Graphics g)
      28         {
      29                 int w, h, ax, ay, sx, sy, x, y;
      30                 w = 100;
      31                 h = 100;
      32                 for (x = 0; x < 4; x++)
      33                         for (y = 0; y < 4; y++)
      34                         {
      35                                 ax = 盤の表示の演習 ;
      36                                 ay = 盤の表示の演習 ;
      37                                 sx = 盤の表示の演習 ;
      38                                 sy = 盤の表示の演習 ;
      39                                 g.drawImage(img, 画像を表示するの演習, this);
      40                         }
      41                 g.setColor(Color.blue);
      42                 g.fillRect(spx*100, spy*100, 100, 100);
      43         }
      44         
      45         public void mousePressed(MouseEvent e)
      46         {
      47                 int x, y, cx, cy;
      48                 x = e.getX();
      49                 y = e.getY();
      50                 cx = クリック時の処理の演習;
      51                 cy = クリック時の処理の演習;
      52                 if ( 今回の演習 )
      53                 {
      54                         ban[spx][spy] = ban[cx][cy];
      55                         spx = cx;
      56                         spy = cy;
      57                         ban[spx][spy] = 15;
      58                         repaint();
      59                 }
      60         }
      61         public void mouseEntered(MouseEvent e) { }
      62         public void mouseExited(MouseEvent e) { }
      63         public void mouseReleased(MouseEvent e) { }
      64         public void mouseClicked(MouseEvent e) { }
      65         
      66         public static void main(String[] args)
      67         {
      68                 JFrame f;
      69                 
      70                 f = new JFrame();
      71                 f.setVisible(true);
      72                 f.setTitle("15Game");
      73                 f.setSize(420, 450);
      74                 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      75                 f.add( new Game6() );
      76         }
      77 }
    


演習

ボタンが押された位置が空白箇所の隣であるかを判定する条件を 今回の演習 の位置に記述しプログラムを完成させなさい。

ピースを動かす (最終更新日時 2012-01-12 07:09:21 更新者 masahiko)