GUI部品とイベント処理の例 マインスィーパもどきの作成 倉敷芸術科学大学 産業科学技術学部 梶浦文夫
ゲームの説明 ◎いくつかの桝目の中 に爆弾が隠れている ◎爆弾の桝目を開けると 負け ◎爆弾のない桝目を 全部開けると勝ち に爆弾が隠れている ◎爆弾の桝目を開けると 負け ◎爆弾のない桝目を 全部開けると勝ち ◎ヒントとして周囲の爆弾 の個数を表示
ゲームの説明2 0 周囲の爆弾の 個数とは? 2 隣接する8個の桝目のなかにある爆弾の数 3 1
実行 画面 8×8の 舛目 終了ボタン リプレイボタン
実行中 の画面 桝目を開けると、周りの爆弾の個数が表示される ここを開けたとき
実行中 の画面 爆弾の桝目を開けてしまって負けたところ
ゲーム盤の作成 Frame BorderLayout Panel GridLayout Button Panel リプレイボタン 終了ボタン
碁盤目の作成 Panel p1; //全体のレイアウトはボーダーレイアウト setLayout(new BorderLayout()); GridLayout 碁盤目の作成 Frame BorderLayout Panel Panel p1; //全体のレイアウトはボーダーレイアウト setLayout(new BorderLayout()); //盤のためのパネル p1 = new Panel(); p1.setLayout(new GridLayout(SIZE, SIZE));
碁盤目の作成 //パネルp1上に盤の作成 for(int i = 0;i < SIZE;i++) 碁盤目の作成 GridLayout Panel Button //パネルp1上に盤の作成 for(int i = 0;i < SIZE;i++) for(int j = 0;j < SIZE;j++) { b[i][j] = new Button(" "); b[i][j].addActionListener(this); p1.add(b[i][j]); } //盤を中央に貼りつけ add(p1, BorderLayout.CENTER); 8行8列に ボタン作成 リスナ設定 Panelに貼り付け
リプレイボタン、終了ボタン Panel p2; //パネル Button b_end; //終了ボタン Button b_cont; //継続ボタン //終了ボタン貼りつけ b_end = new Button("End"); b_end.addActionListener(this); //p2の貼りつけ p2.add(b_end); add(p2, BorderLayout.SOUTH);//下側に貼りつけ リプレイボタン省略
盤の状態を保持する変数(配列) boolean bombset[8][8]; //爆弾がセットされているか? ○ 桝目の個数分の要素を持つ配列(64個) ○ 要素の型はboolean型 ○ trueなら爆弾あり! falseなら爆弾なし boolean opened[8][8]; //桝目がオープンされているか? ○ 桝目の個数分の要素を持つ配列(64個) ○ 要素の型はboolean型 ○ trueなら開かれている! falseならまだ!
盤の初期化1 64個の要素全部を設定 void init_board() { //桝目の状態初期化 for(int i = 0;i < SIZE;i++) for(int j = 0;j < SIZE;j++) opened[i][j] = false; bombset[I][j] = false; b[i][j].setLabel(" "); } オープンされていない 爆弾はセットされていない ボタンの文字は空白
盤の初期化2 爆弾の個数分繰り返し //爆弾の位置設定 for(int i = 0;i < NOB;i++) while(true) { int x = (int)(Math.random() * 8.0); int y = (int)(Math.random() * 8.0); if(!bombset[x][y]) bombset[x][y] = true; break; } 同じ位置にならないように 0~7の乱数 まだ爆弾がセットされていなければ 爆弾をセット 0.0 <= Math.random() < 1.0 の乱数
イベント処理1 public void actionPerformed(ActionEvent ae) { //終了ボタンの場合 if(ae.getSource() == b_end) System.exit(0); //継続ボタンの場合 else if(ae.getSource() == b_cont) init_board(); :
イベント処理2 64個のボタンのうちどのボタンが押されたのか調べる int ii = -1; int jj = -1; for(int i = 0;i < SIZE;i++) for(int j = 0;j < SIZE;j++) if(ae.getSource() == b[i][j]) { ii = i; jj = j; } 押されたのはii行jj列のボタン
イベント処理3 開かれてなかったら 爆弾があったら 爆弾がなかったら if(ii >= 0 && !opened[ii][jj]) { //爆発! if(bombset[ii][jj]) disp_bomb(); //爆弾の位置表示 else //ラッキー //周囲の爆弾の個数表示 b[ii][jj].setLabel(" " + count_bomb(jj, ii)); //状態変数openedをtrueに opened[ii][jj] = true; } 開かれてなかったら 爆弾があったら 爆弾がなかったら
隣接する8個の桝目 bombset[y-1][x-1] bombset[y-1][x] bombset[y-1][x+1]
周りの爆弾の個数 //y行目、x桁目の周りの爆弾の個数を調べる //周囲の爆弾の個数 int count = 0; if(y > 0 && x > 0 && bombset[y - 1][x - 1]) count++; //左上チェック if(y > 0 && bombset[y - 1][x]) count++; //上チェック if(y > 0 && x < 7 && bombset[y - 1][x + 1]) count++; //右上チェック if(x > 0 && bombset[y][x - 1]) count++; //左チェック if(y < 7 && x > 0 && bombset[y + 1][x - 1]) count++; //左下チェック if(y < 7 && bombset[y + 1][x]) count++; //下チェック if(y < 7 && x < 7 && bombset[y + 1][x + 1]) count++; //右下チェック if(x < 7 && bombset[y][x + 1]) count++; //右チェック return count;
最後に 今回のプログラムで使用したクラスは… Button、Panel、Frameなどである 使用したLayoutは… 今回のプログラムで使用したクラスは… Button、Panel、Frameなどである 使用したLayoutは… FlowLayout、BorderLayout、GridLayoutである イベント処理は… actionPerformed( )である 今後の課題は… 現在の爆弾の個数、オープンした桝目の数な どを表示するようにする