一直有写一个博客的想法【没有博客能叫程序员?】,但是一直都没有去做,今天下定决定正式开始了,学了将近三年的vb.net,由于大学专业非计科类的,学的也是一般般。从7月开始学习java,由于也算是有基础,语法部分过得很快。然后就决定做一个程序来练练手。由于平时偶尔喜欢玩扫雷,决定就做一个简单点的扫雷好了。
第一步,起名字
给程序起一个名字还是很重要的,不然很快就认不出来了。直接使用了在线翻译软件决定名字为 Mine Clear
第二步,分析程序
整个程序比较简单,初始化什么的都比较简单,核心是点击潜在地雷的时候的反应,如果是地雷,游戏直接结束。如果不是地雷则计算周围的地雷数目【范围是 (x-1,x-1) & (y-1,y+1)】。如果数目是0,那么需要对周围的潜在地雷全部触发掉,来完成自动扩展。
第三步,列出成员
函数
构造函数(必备)
void startGame() 开始游戏(初始化游戏)
void gameOver() 游戏结束
int getMineCounter(int x,int y) 计算由x,y指定的坐标地雷的周围地雷数
boolean inArea(int x,int y) 判断参数是否在当前游戏坐标范围内
void click(int x,int y)从MouseClick监听器中抽取出来,用于实现自动扩展
类:
Mine 类(继承自JButton,添加三个公开字段,Boolean isMine , int x , int y)
常量:
int MINE_ROW_COUNT 一行的地雷数
int MINE_COL_COUNT 一列的地雷数
int MINE_COUNT 游戏中的真正地雷数目
变量:
int clearNumer 清除的地雷数目,用于判断游戏是否胜利
boolean[][] cleared 对应坐标的地雷时候清除【这一部分可以放进Mine类中】
Mine[][] mines 对应坐标的地雷
代码:
Mine类的定义
public class Mine extends JButton{
boolean isMine;
public Mine(boolean isM ) {
isMine = isM;
}
public Mine() {
isMine = false;
}
int x;
int y;
}
void startGame() //开始游戏
/*
*初始化游戏
*/
static void startGame(Game g,JPanel jp){
ArrayList<Mine> Mines = new ArrayList<Mine>(); //定义地雷动态集合
clearNumber = 0; //初始化已清除数目为0
cleared =new boolean[MINE_ROW_COUNT][MINE_COL_COUNT]; //初始化是否清除数组
mines = new Mine[MINE_ROW_COUNT][MINE_COL_COUNT]; //实例化地雷数组
for (int i = 0; i < MINE_ROW_COUNT * MINE_COL_COUNT; i++) { Mine tmpMine = g.new Mine(); //实例化地雷,由于是内部类,需要使用 parent.new childclass()这种方式 tmpMine.addMouseListener(MouseClick); //给地雷添加点击的监听 Mines.add(tmpMine); //添加地雷到地雷动态集合 } ArrayList<Integer> mineNumber =new ArrayList<Integer>(); //定义集合存放是真正地雷的编号 Random random = new Random(); //实例化随机器 while(mineNumber.size()<MINE_COUNT) //当地雷的编号的个数小于真正地雷数则继续循环 { int tmpNumber = random.nextInt(MINE_ROW_COUNT * MINE_COL_COUNT); for (int i= 0;i<mineNumber.size();i++) { if (tmpNumber == mineNumber.get(i)) //去重复 continue; } mineNumber.add(tmpNumber); // 添加 } while(mineNumber.size() > 0 ) //循环按编号给真正地雷的isMine赋值为true { int tmpNumber = mineNumber.get(0); Mine tmpMine = Mines.get(tmpNumber); tmpMine.isMine=true; mineNumber.remove(0); } GridLayout gridLayout =new GridLayout(MINE_ROW_COUNT,MINE_COL_COUNT,3,3); //设置布局为网格布局,并指定行数和列数,行列间距为3 contentPane.setLayout(gridLayout); g.setSize(40*MINE_ROW_COUNT, 40*MINE_COL_COUNT); //设置界面大小,保持地雷的大小固定 g. setResizable(false); //禁止调整界面大小 for (int i =0 ; i<MINE_ROW_COUNT;i++) { for (int j=0 ;j<MINE_COL_COUNT;j++) { cleared[i][j] = false ; //cleared赋值为false【不太清楚是否会自动初始化为false】 Mine m = Mines.get(i*MINE_COL_COUNT +j); //从动态集合中取出地雷 mines[i][j] = m; //吧地雷赋值给mines数组 m.x=i; //设置坐标 m.y=j; jp.add(m); //添加地雷到界面 } } jp.revalidate(); //刷新界面 }
点击事件:
static MouseAdapter MouseClick = new MouseAdapter() { //实例化点击监听 @Override public void mouseClicked(MouseEvent e) { Mine mine = (Mine) e.getSource(); //获取点击的对象 click(mine.x, mine.y); //调用点击方法 } }; static void click(int x,int y) //点击方法 { if (cleared[x][y]) return ; //判断该坐标的地雷是否操作过,操作过就直接退出 //System.out.println("CLICK:"+x+"---"+y); Mine mine = mines[x][y]; //获取到点击的地雷 if (mine.isMine){ //如果点击的是真正的地雷则调用结束游戏方法 System.out.println("isMine!"); gameover( ); } else{ clearNumber++; //把清除过得地雷数目加1 cleared[x][y] = true; //当前坐标设置为清除过 mine.setText(""+getMineCounter(mine.x, mine.y));//设置地雷的text属性,显示周围的地雷数 mine.setEnabled(false); //设置按钮不可用 if (clearNumber == MINE_ROW_COUNT * MINE_COL_COUNT-MINE_COUNT ) //如果清除过得数目等于非真正地雷数目则游戏通关 { JOptionPane.showMessageDialog(frame, "游戏通关", "You Win!",JOptionPane.WARNING_MESSAGE); } } }
计算周围地雷数:
static int getMineCounter(int x,int y) { int count = 0; if (inArea(x-1, y-1)) if (mines[x-1][ y-1].isMine) count++; if (inArea(x+1, y-1)) if (mines[x+1][ y-1].isMine) count++; if (inArea(x, y-1)) if(mines[x][ y-1].isMine) count++; if (inArea(x-1, y)) if (mines[x-1][ y].isMine) count++; if (inArea(x+1, y)) if (mines[x+1][ y].isMine) count++; if (inArea(x-1, y+1)) if(mines[x-1][ y+1].isMine) count++; if (inArea(x+1, y+1)) if(mines[x+1][ y+1].isMine) count++; if (inArea(x, y+1)) if(mines[x][ y+1].isMine) count++; if (count==0) { if (inArea(x+1, y+1)) click(x+1, y+1); if (inArea(x+1, y)) click(x+1, y); if (inArea(x+1, y-1)) click(x+1, y-1); if (inArea(x, y+1)) click(x, y+1); if (inArea(x, y-1)) click(x, y-1); if (inArea(x-1, y+1)) click(x-1, y+1); if (inArea(x-1, y)) click(x-1, y); if (inArea(x-1, y-1)) click(x-1, y-1); } return count; } static boolean inArea(int x,int y) { if (x<0 || x>MINE_COL_COUNT-1) return false ; if (y<0 || y>MINE_ROW_COUNT-1) return false ; return true; }