welcome: please sign in
location: "ピースを動かす"の差分
2と35のリビジョン間の差分 (その間の編集: 33回)
2009-12-04 06:15:29時点のリビジョン2
サイズ: 618
編集者: masahiko
コメント:
2012-01-12 06:27:44時点のリビジョン35
サイズ: 5491
編集者: masahiko
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 1: 行 1:
#acl All:
行 3: 行 2:
{{{
ピースを1つ取り除いてできた空白の箇所を使って
移動するための処理を記述します。

----
=== 空白の箇所の表現 ===

どこに空白があるかを表すために、インスタンス変数を使います。

 * spxで空白の横方向の位置を、0~3の値で表すものとします。

 * spyで空白の縦方向の位置を、0~3の値で表すものとします。

例えば、spx=0, spy=2 のときは
上から3番目の左端が空白。

=== 初期化 ===

最初は右下隅のピースを取り除いた位置です。
したがって値は
 . spx = 3
 . spy = 3
空白箇所は右下のピースを取り除いたものですから、
配列要素の値は右下のピースの値としておきます。
 . ban[spx][spy] = 15

----
=== 空白箇所の表示 ===
spx,spyで表された場所は空白であることを示すため、
1色で塗りつぶします。

クリック時の処理の演習ではcx,cyで示された位置を塗りつぶしていましたが、
spx,spyが示す箇所を塗りつぶすように修正します。

塗りつぶしの色は好みのものを指定してください。
----
=== ボタンが押されたときの処理 ===
変数 spx,spy の値をmousePressedメソッド内で、押された場所に応じて更新します。

mousePressedメソッドでは引数(!MouseEvent e)を通して
ボタンが押された位置を得ることができます。
 . e.getX() でX座標(左からのピクセル値)が得られます。
 . e.getY() でY座標(上からのピクセル値)が得られます。
この値を盤の座標値に変換するには
1つのピースの縦横の大きさで割ればよい。<<BR>>
ピースの大きさは変数habaに入っているので、
クリックされた盤座標をx,yに得るために次を行います。
 . 48,49行目
 . x = e.getX() / haba;
 . y = e.getY() / haba;

ボタンが押された位置が盤の外であるときは、以下の処理は行いません。<<BR>>
盤の内部であるかどうかはx,yの値で判定できます。<<BR>>
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の位置でも同様の処理でよいことがわかります。
----
=== 演習 ===
ピースを移動する処理は、空白箇所の隣でボタンが押されたときだけ行います。

条件が成り立つときだけ、ピースを移動する処理を行いrepaintを指示します。

ボタンが押された位置が空白箇所の隣であるかを判定する条件を
<<Color(red:演習(52行目))>>
の位置に記述しプログラムを完成させなさい。

ヒント
 . if( Aの位置である || Bの位置である || Cの位置である || Dの位置である )

----
以下のプログラムでは、修正が必要な箇所のみ示しています。
記述の無い部分は前回と同じです。
{{{#!java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Game2 extends JPanel implements MouseListener
{
 int haba;
 int yoko, tate;
 String fname;
 Image img;
 int[][] ban;
 int spx, spy;
 
 Game2()
 {
  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);
 }
行 6: 行 155:
  int ix, iy, dx, dy;   int x, y;
行 8: 行 157:
  ix = e.getX() / pSize;
  iy = e.getY() / pSize;
  if(ix < 0 || ix >= nx || iy < 0 || iy >= ny) return;
  if(ix == spx && iy != spy)
  x = e.getX() / haba;
  y = e.getY() / haba;
  if(x >= yoko || y >= tate)
   
return;
  if( 演習 )
行 13: 行 163:
   dx = 0;
   dy = (iy < spy) ? -1 : 1;
   ban[spx][spy] = ban[x][y];
   spx = x;
   spy = y;
   repaint();
行 16: 行 168:
  else if(iy == spy && ix != spx)
  {
   dy = 0;
   dx = (ix < spx) ? -1 : 1;
  }
  else
   return;
  do
  {
   ban[spx][spy] = ban[spx+dx][spy+dy];
   spx = spx + dx;
   spy = spy + dy;
  } while (spx != ix || spy != iy);
  ban[spx][spy] = nx*ny-1; // はずしたピース
  repaint();
行 32: 行 169:
   public void mouseEntered(MouseEvent e) { }
 public void mouseExited(MouseEvent e) { }
 public void mouseReleased(MouseEvent e) { }
 public void mouseClicked(MouseEvent e) { }

ピースを動かす

ピースを1つ取り除いてできた空白の箇所を使って 移動するための処理を記述します。


空白の箇所の表現

どこに空白があるかを表すために、インスタンス変数を使います。

  • spxで空白の横方向の位置を、0~3の値で表すものとします。
  • spyで空白の縦方向の位置を、0~3の値で表すものとします。

例えば、spx=0, spy=2 のときは 上から3番目の左端が空白。

初期化

最初は右下隅のピースを取り除いた位置です。 したがって値は

  • spx = 3
  • spy = 3

空白箇所は右下のピースを取り除いたものですから、 配列要素の値は右下のピースの値としておきます。

  • ban[spx][spy] = 15


空白箇所の表示

spx,spyで表された場所は空白であることを示すため、 1色で塗りつぶします。

クリック時の処理の演習ではcx,cyで示された位置を塗りつぶしていましたが、 spx,spyが示す箇所を塗りつぶすように修正します。

塗りつぶしの色は好みのものを指定してください。


ボタンが押されたときの処理

変数 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の位置でボタンが押された場合を考えます。

  • 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の位置でも同様の処理でよいことがわかります。


演習

ピースを移動する処理は、空白箇所の隣でボタンが押されたときだけ行います。

条件が成り立つときだけ、ピースを移動する処理を行いrepaintを指示します。

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

ヒント

  • if( Aの位置である || Bの位置である || Cの位置である || Dの位置である )


以下のプログラムでは、修正が必要な箇所のみ示しています。 記述の無い部分は前回と同じです。

   1 import javax.swing.*;
   2 import java.awt.*;
   3 import java.awt.event.*;
   4 
   5 public class Game2 extends JPanel implements MouseListener
   6 {
   7         int haba;
   8         int yoko, tate;
   9         String fname;
  10         Image img;
  11         int[][] ban;
  12         int spx, spy;
  13         
  14         Game2()
  15         {
  16                 addMouseListener(this);
  17         }
  18 
  19         void shokika()
  20         {
  21                 ...
  22                 spx = yoko-1;
  23                 spy = tate-1;
  24         }
  25 
  26         public void paintComponent(Graphics g)
  27         {
  28                 int dx, dy, sx, sy;
  29                 
  30                 for(dy = 0; dy < tate; dy++)
  31                         for(dx = 0; dx < yoko; dx++)
  32                         {
  33                                 sx = ...;
  34                                 sy = ...;
  35                                 g.drawImage(img,
  36                                         dx*haba, dy*haba, (dx+1)*haba, (dy+1)*haba,
  37                                         sx*haba, sy*haba, (sx+1)*haba, (sy+1)*haba,
  38                                         this);
  39                         }
  40                 g.setColor(Color.lightGray);
  41                 g.fillRect(spx*haba, spy*haba, haba, haba);
  42         }
  43 
  44         public void mousePressed(MouseEvent e)
  45         {
  46                 int x, y;
  47 
  48                 x = e.getX() / haba;
  49                 y = e.getY() / haba;
  50                 if(x >= yoko || y >= tate)
  51                         return;
  52                 if( 演習 )
  53                 {
  54                         ban[spx][spy] = ban[x][y];
  55                         spx = x;
  56                         spy = y;
  57                         repaint();
  58                 }
  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) { }      

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