なぜ面倒と思ったかというと、Javaのマウスリスナーはそのままでは左右ボタン同時押しを検出してくれないからなんです。左ボタンだけ押すとボタン1が押された、というイベントが発生し、右ボタンだけ押すとボタン3が押されたというイベントが発生するようになっています。 |
起動直後(左)とゲーム中(右)
開けていないパネルを右クリックするとマークを付けることができます。
数字と周囲のマークの数が同じとき、数字を右クリックすると、こういうポップアップメニューが出ます。
成功したとき(左)と失敗したとき(右)
今回もソースだけ公開します。各自でコンパイルして実行してください。拡張for文などを使っているので、JDK1.5.x以上じゃないとコンパイルできません。
import java.util.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.*; public class myminesw { private JFrame frm; private JPanel grpPnl; private JPanel statPnl; private JLabel statLbl; private JPopupMenu pMenu; private BufferedImage img; private final int cellWidth=12; private final int cellHeight=12; private final int chartWidth=20; private final int chartHeight=16; private final int mines=chartWidth*chartHeight/10; private final String statInit="Initializing..."; private final String statRdy="Ready."; private final String statSuc="Success!!"; private final String statFail="Fail..."; private LinkedList<Point> que; private int cellLeft; private int qOpenX; private int qOpenY; private class Cell { int x; int y; int count; boolean mine; boolean opened; boolean marked; private Cell(int x,int y) { this.x=x; this.y=y; this.count=0; this.mine=false; this.opened=false; this.marked=false; } private void setMine(boolean t) { this.mine=t; if(!t) { this.count=0; this.count=0; this.opened=false; this.marked=false; } } private void incCount() { this.count++; } private void drawSelf() { int gx = x*cellWidth; int gy = y*cellHeight; Graphics2D g = img.createGraphics(); g.setFont(new Font("Monospaced",Font.PLAIN,10)); if(this.opened) { g.setColor(Color.WHITE); g.fillRect(gx,gy,cellWidth,cellHeight); g.setColor(Color.BLACK); g.setBackground(Color.WHITE); if(this.mine) { g.drawString("*",gx+4,gy+10); } else { if(this.count>0) { g.drawString(Integer.toString(this.count),gx+4,gy+10); } } g.setColor(Color.GRAY); g.drawRect(gx,gy,cellWidth-1,cellHeight-1); } else { g.setColor(Color.GRAY); g.fillRect(gx,gy,cellWidth,cellHeight); g.setColor(Color.WHITE); g.drawLine(gx,gy,gx+cellWidth-1,gy); g.drawLine(gx,gy,gx,gy+cellHeight-2); g.setColor(Color.BLACK); g.drawLine(gx+cellWidth-1,gy+1,gx+cellWidth-1,gy+cellHeight-1); g.drawLine(gx,gy+cellHeight-1,gx+cellWidth-1,gy+cellHeight-1); if(this.marked) { g.drawLine(gx+3,gy+2,gx+3,gy+cellHeight-2); g.drawLine(gx+3,gy+2,gx+cellWidth-3,gy+2+(cellHeight-4)/4); g.drawLine(gx+3,gy+2+(cellHeight-4)/2,gx+cellWidth-3,gy+2+(cellHeight-4)/4); } } grpPnl.repaint(); } private void setOpen(boolean t) { this.opened = t; this.drawSelf(); } private void setMark(boolean t) { this.marked=t; this.drawSelf(); } private void toOpen() { if(! this.opened) { this.opened = true; this.drawSelf(); if(this.mine) { allOpen(); statLbl.setText(statFail); statPnl.setBackground(Color.RED); } else { cellLeft--; if(cellLeft==0) { allOpen(); statLbl.setText(statSuc); statPnl.setBackground(Color.GREEN); } else { if(this.count==0) { ArrayList<Point> a = this.neighbor(); for(Point p : a) { if(! cells[p.y][p.x].opened) que.add(p); } } } } } } private ArrayList<Point> neighbor() { ArrayList<Point> r = new ArrayList<Point>(8); if(this.y>0) { if(this.x>0) r.add(new Point(x-1,y-1)); r.add(new Point(x,y-1)); if(this.x<chartWidth-1) r.add(new Point(x+1,y-1)); } if(this.x>0) r.add(new Point(x-1,y)); if(this.x<chartWidth-1) r.add(new Point(x+1,y)); if(this.y<chartHeight-1) { if(this.x>0) r.add(new Point(x-1,y+1)); r.add(new Point(x,y+1)); if(this.x<chartWidth-1) r.add(new Point(x+1,y+1)); } return r; } } private Cell[][] cells = new Cell[chartHeight][chartWidth]; private void allOpen() { int i,j; for(i=0;i<chartHeight;i++) { for(j=0;j<chartWidth;j++) { cells[i][j].setOpen(true); } } } MouseListener pLsn = new MouseAdapter() { public void mousePressed(MouseEvent e) { if(e.getButton()==MouseEvent.BUTTON1) { if((qOpenX>=0) && (qOpenY>=0)) { ArrayList<Point> a = cells[qOpenY][qOpenX].neighbor(); for(Point p : a) { if((! cells[p.y][p.x].opened) && (! cells[p.y][p.x].marked)) cells[p.y][p.x].toOpen(); } } } } }; MouseListener mLsn = new MouseAdapter() { public void mousePressed(MouseEvent e) { int gx=e.getX(); int gy=e.getY(); int ix=gx/cellWidth; if(ix>chartWidth-1) ix=chartWidth-1; int iy=gy/cellHeight; if(iy>chartHeight-1) iy=chartHeight-1; if(statLbl.getText()==statRdy) { if(pMenu.isVisible()) { pMenu.setVisible(false); qOpenX=-1; qOpenY=-1; } else { if(e.getButton()==MouseEvent.BUTTON3) { if((cells[iy][ix].opened) && (cells[iy][ix].count>0)) { int n=0; ArrayList<Point> a = cells[iy][ix].neighbor(); for(Point p : a) { if(cells[p.y][p.x].marked) n++; } if(cells[iy][ix].count==n) { qOpenX=ix; qOpenY=iy; pMenu.show(grpPnl,gx,gy); } } else { cells[iy][ix].setMark(! cells[iy][ix].marked); } } else { if(e.getButton()==MouseEvent.BUTTON1) { if(! cells[iy][ix].opened) { cells[iy][ix].toOpen(); } } } } } else { if((statLbl.getText()==statSuc) || (statLbl.getText()==statFail)) { statLbl.setText(statInit); statPnl.setBackground(Color.GRAY); } } } }; private void doProg() { int i,j,n; for(i=0;i<chartHeight;i++) { for(j=0;j<chartWidth;j++) { cells[i][j] = new Cell(j,i); } } que = new LinkedList<Point>(); grpPnl.addMouseListener(mLsn); while(true) { if(statLbl.getText()==statInit) { cellLeft=chartWidth*chartHeight; for(i=0;i<chartHeight;i++) { for(j=0;j<chartWidth;j++) { cells[i][j].setMine(false); cells[i][j].setOpen(false); } } que.clear(); qOpenX=-1; qOpenY=-1; n=mines; while(n>0) { i=(int)(Math.random()*chartHeight); j=(int)(Math.random()*chartWidth); if(cells[i][j].mine) continue; cells[i][j].setMine(true); n--; cellLeft--; ArrayList<Point> a = cells[i][j].neighbor(); for(Point p : a) { cells[p.y][p.x].incCount(); } } statLbl.setText(statRdy); statPnl.setBackground(Color.WHITE); } else if(statLbl.getText()==statRdy) { while(que.size()>0) { Point p = que.removeFirst(); if(p==null) continue; if(! cells[p.y][p.x].opened) cells[p.y][p.x].toOpen(); if(statLbl.getText()!=statRdy) break; } } else { } } } private void makeFrame() { JFrame.setDefaultLookAndFeelDecorated(true); frm = new JFrame("myまいんすいーぱー"); frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); img = new BufferedImage(chartWidth*cellWidth,chartHeight*cellHeight, BufferedImage.TYPE_INT_RGB); JMenuItem pItmQop = new JMenuItem("Q.Open"); pItmQop.addMouseListener(pLsn); pMenu = new JPopupMenu(); pMenu.add(pItmQop); statPnl = new JPanel(); statPnl.setBorder(BorderFactory.createLineBorder(Color.black)); statLbl = new JLabel(statInit); statPnl.add(statLbl); grpPnl = new JPanel() { public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(img,0,0,this); } }; grpPnl.setPreferredSize(new Dimension(chartWidth*cellWidth,chartHeight*cellHeight)); frm.getContentPane().add(grpPnl,BorderLayout.CENTER); frm.getContentPane().add(statPnl,BorderLayout.SOUTH); frm.pack(); frm.setVisible(true); } public static void main(final String[] args) { myminesw myProg = new myminesw(); myProg.makeFrame(); myProg.doProg(); } } |