このプログラムにも不備がある。まず、フォントサイズがうち決めされていることと縦方向の中央寄せがいいかげんであることだ。ゲームとしてはスコア計算がない。
また、openZeroは初心者には分かりにくい再帰で書かれている。しかし、これは再起を使えば難しい処理も簡単に表現できる一例になっている。
package game.minesweeper; import java.applet.Applet; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; @SuppressWarnings("serial") public class MineSweeper extends Applet implements MouseListener { public static final int N = 8; // board size N x N cells public static final int M = 8; // #mines public static final int S = 16; // cell size // modeling game board boolean[][] mines; boolean[][] isOpen; int[][] counts; boolean bang; // game over public void init() { // データの初期化 bang = false; setMines(); // GUIの設定 setFont(new Font("Monospaced",Font.PLAIN,S)); setSize(N*S+1,N*S+1); addMouseListener(this); } // 地雷の設置 void setMines() { mines = new boolean[N][N]; isOpen = new boolean[N][N]; counts = new int[N][N]; for(int i=0; i<M; i++) { int x, y; do { x = (int)(Math.random() * N); y = (int)(Math.random() * N); } while(mines[y][x]); mines[y][x] = true; countMines(x, y); } } // 地雷の場所(x,y)周辺のカウントを増やす void countMines(int x, int y) { for(int dy=-1; dy<=1; dy++) for(int dx=-1; dx<=1; dx++) { if (dx==0 && dy==0) continue; if (onBoard(x+dx, y+dy)) counts[y+dy][x+dx]++; } } // viewing model public void paint(Graphics g){ FontMetrics fm = g.getFontMetrics(); int w = fm.stringWidth("*"); for(int y=0; y<N; y++) for(int x=0; x<N; x++) { g.drawRect(x*S, y*S, S, S); if (isOpen[y][x]) { String s = (mines[y][x]) ? "*" : ""+counts[y][x]; g.drawString(s,x*S+S/2-w/2,y*S+S-2); } } if (bang) { String msg = "Bang!"; g.setColor(Color.red); g.drawString(msg, N*S/2-msg.length()*w/2, N*S/2); } } boolean onBoard(int x, int y) { return (0<=y && y<N && 0<=x && x<N); } // すべて開く void openAll() { for(int y=0; y<N; y++) for(int x=0; x<N; x++) isOpen[y][x] = true; } // 隣接する0をすべて開ける void openZero(int x, int y) { if (! onBoard(x, y)) return; if (isOpen[y][x]) return; isOpen[y][x] = true; if (counts[y][x] > 0) return; for(int dy=-1; dy<=1; dy++) for(int dx=-1; dx<=1; dx++) openZero(x+dx, y+dy); } @Override public void mouseClicked(MouseEvent e) { int x = e.getX() / S; int y = e.getY() / S; if (! onBoard(x, y)) return; if (mines[y][x]) { bang = true; openAll(); } openZero(x, y); repaint(); } @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} }
0 件のコメント:
コメントを投稿