团队名称:Sweephtml
团队成员介绍:陈玉婷,彭佳妮,罗梅丽git
任务分配:算法
陈玉婷:文件管理,及扫雷游戏算法实现,画UML图数组
彭佳妮:GUI登录界面设置,用户密码验证及其监听,写博客架构
罗梅丽:GUI登录界面设置,写博客ide
成员 | 博客连接 |
陈玉婷(组长) | https://www.cnblogs.com/chenyutin/p/10279348.html
|
彭佳妮 | http://www.javashuo.com/article/p-hspflokp-q.html |
罗梅丽 | https://www.cnblogs.com/luomeili/p/10281816.html |
https://gitee.com/pengjiani/mine_clearance布局
提交记录this
扫雷游戏介绍:spa
《扫雷》是一款大众类的益智小游戏。游戏目标是在最短的时间内根据点击格子出现的数字找出全部非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。.net
游戏设定:
游戏区包括雷区,肯定大小的矩形雷区中随机布置必定数量的地雷(初级为9*9个方块9个雷,中级为14*14个方块14个雷,高级为16*16个方块16个雷,玩家须要尽快找出雷区中的全部不是地雷的方块,而不准踩到地雷。
功能流程图
功能构架图
优秀设计部分
能够保存游戏进度,增长游戏的灵活性和用户体验
保存游戏进度
再次登录时进入上一次游戏
界面显示模块
//登录界面设置 setSize(496, 557); setLayout(new GridLayout(2, 1)); // JMenuBar bar=new JMenuBar(); HomePanel panelN = new HomePanel("2018-01-10_12-55-41.gif"); HomePanel panelS = new HomePanel("ApplicationFrameHost_2018-01-10_13-37-17.png"); panelN.setLayout(new FlowLayout()); JButton button=new JButton(); button.setIcon(new ImageIcon("ApplicationFrameHost_2018-01-10_13-39-56.png")); //button.setOpaque(false); //设置控件透明 button.setBorder(null); //设置边框 button.setContentAreaFilled(false); //设置控件透明 button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { System.exit(0); } }); //键盘监听 KeyListener key_Listener = new KeyListener() { public void keyTyped(KeyEvent e) {} public void keyReleased(KeyEvent e){} public void keyPressed(KeyEvent e){ if(e.getKeyChar() == KeyEvent.VK_ENTER ) { String name = usenameField.getText(); String word = new String(passwordField.getPassword()); if(judge(name,word) == 0) JOptionPane.showMessageDialog(null, "用户名不存在!"); else if(judge(name,word) == -1) JOptionPane.showMessageDialog(null, "密码错误!"); else { Selection selection=new Selection(file); MFrame.this.dispose(); } try { file.setFileName(usenameField.getText()); // Selection selection=new Selection(file); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }; passwordField.addKeyListener(key_Listener);
咱们的扫雷由n x m 的方格区域构成,当咱们点击其中一个方块的时候,若是它不是雷,它就应当以数字的形式表示出在它外圈的一圈内包含有多少个雷,这个数字的范围是1到8,在它不是雷的前提下,若是它周围也没有雷的话,那咱们点击的方块在下一秒应当展开当前的一片无雷的区域,以数字做为边界,该边界指出外圈的雷的数目,咱们的作法是,以二维数组的形式定义一片区域,每二维数组上的每个数字映射着咱们雷区的每一块方格,而后就是该二维数组的数字的范围,咱们取整型数字的范围为0到9,用9来表示雷,用0到8来表示外围雷的数目,咱们这里的0在 后是不用来显示在方块上的,咱们判断到方块下面的数字是0的话咱们会让雷区展开一片空白区域。
也就是说,咱们刚开始初始化了一个二维数组map,来映射一片雷区,其中的整型数字范围为0到9,用9来表示雷。
因此刚开始的代码,将二维数组初始化为0,接下来按行随机和列随机的方式随机布下指定数目的雷的数量,这样,咱们 开始的并且也是扫雷中 实际的“雷区”(map)也就生成了。
但 终要实现用户交互界面,因此须要将咱们的map映射到frame上,并能实现点击交互。咱们这里的作法是,使用按钮,以为使用按钮能够没必要再去鼠标点击的区域的具体坐标,直接使用按钮监听器来实现对点击位置的具体把控。
因此咱们在交互界面,frame上,咱们初始化了JButton数组,而后使用了gridlayout的网格布局将按钮布置上去,刚开始的按钮的外观惨不忍睹,后来才采用了图片的形式来替代默认的按钮外观。这些是外在,内在咱们还有不少须要考虑的地方。先记住咱们的初始化雷区map是0到9的二维数组。
好比,咱们刚开始须要为用户提供一个初始界面,就是都没有被动过的按钮,当用户点击的时候,须要展开区域,仍是显示数字,仍是显示雷,仍是标记此位置为雷,每个按钮的“状态”即外观都是不同的,而这些“状态”的改变与咱们的map上面的数字不能直接造成一一映射的关系,也就是说,咱们状态须要改变,可是咱们的map是咱们基本的雷区,是不能被改变的,并且0到9的范围有10种状态选择,但咱们的交互界面须要的状态变化有13种,因此为了解决这种问题,咱们引入了一层隐藏层,来表示咱们的frame上面的每一块方块的状态变化,咱们为隐藏层命名为hiddenmap,一样为咱们的int型以便于储存多“状态”。
部分代码:
public void findZero(int i, int j) { if (hiddenmap[i][j] != 0) { if (map[i][j] == 0) { hiddenmap[i][j] = 0; if (i == 0) { if (j == 0) { if (map[i][j + 1] != 0 && map[i][j + 1] != 9) hiddenmap[i][j + 1] = map[i][j + 1]; if (map[i + 1][j] != 0 && map[i + 1][j] != 9) hiddenmap[i + 1][j] = map[i + 1][j]; } else if (j == length - 1) { if (map[i][j - 1] != 0 && map[i][j - 1] != 9) hiddenmap[i][j - 1] = map[i][j - 1]; if (map[i + 1][j] != 0 && map[i + 1][j] != 9) hiddenmap[i + 1][j] = map[i + 1][j]; } else { if (map[i][j - 1] != 0 && map[i][j - 1] != 9) hiddenmap[i][j - 1] = map[i][j - 1]; if (map[i + 1][j] != 0 && map[i + 1][j] != 9) hiddenmap[i + 1][j] = map[i + 1][j]; if (map[i][j + 1] != 0 && map[i][j + 1] != 9) hiddenmap[i][j + 1] = map[i][j + 1]; } } if (i == width - 1) { if (j == 0) { if (map[i][j + 1] != 0 && map[i][j + 1] != 9) hiddenmap[i][j + 1] = map[i][j + 1]; if (map[i - 1][j] != 0 && map[i - 1][j] != 9) hiddenmap[i - 1][j] = map[i - 1][j]; } else if (j == length - 1) { if (map[i - 1][j] != 0 && map[i - 1][j] != 9) hiddenmap[i - 1][j] = map[i - 1][j]; if (map[i][j - 1] != 0 && map[i][j - 1] != 9) hiddenmap[i][j - 1] = map[i][j - 1]; } else { if (map[i][j + 1] != 0 && map[i][j + 1] != 9) hiddenmap[i][j + 1] = map[i][j + 1]; if (map[i - 1][j] != 0 && map[i - 1][j] != 9) hiddenmap[i - 1][j] = map[i - 1][j]; if (map[i][j - 1] != 0 && map[i][j - 1] != 9) hiddenmap[i][j - 1] = map[i][j - 1]; } } if (j == 0) { if (i != 0 && i != width - 1) { if (map[i - 1][j] != 0 && map[i - 1][j] != 9) hiddenmap[i - 1][j] = map[i - 1][j]; if (map[i + 1][j] != 0 && map[i + 1][j] != 9) hiddenmap[i + 1][j] = map[i + 1][j]; if (map[i][j + 1] != 0 && map[i][j + 1] != 9) hiddenmap[i][j + 1] = map[i][j + 1]; } } if (j == length - 1) { if (i != 0 && i != width - 1) { if (map[i - 1][j] != 0 && map[i - 1][j] != 9) hiddenmap[i - 1][j] = map[i - 1][j]; if (map[i + 1][j] != 0 && map[i + 1][j] != 9) hiddenmap[i + 1][j] = map[i + 1][j]; if (map[i][j - 1] != 0 && map[i][j - 1] != 9) hiddenmap[i][j - 1] = map[i][j - 1]; } } if (i != 0 && i != width - 1 && j != 0 && j != length - 1) { if (map[i][j + 1] != 0 && map[i][j + 1] != 9) hiddenmap[i][j + 1] = map[i][j + 1]; if (map[i + 1][j] != 0 && map[i + 1][j] != 9) hiddenmap[i + 1][j] = map[i + 1][j]; if (map[i][j - 1] != 0 && map[i][j - 1] != 9) hiddenmap[i][j - 1] = map[i][j - 1]; if (map[i - 1][j] != 0 && map[i - 1][j] != 9) hiddenmap[i - 1][j] = map[i - 1][j]; } if (j >= 1) findZero(i, j - 1); if (i >= 1) findZero(i - 1, j); if (j <= getLength() - 2) findZero(i, j + 1); if (i <= getWidth() - 2) findZero(i + 1, j); } } }
ObjectInputStream readFile; if (file.isNewOne() == false) { try { readFile = new ObjectInputStream(new FileInputStream(file.getFileName())); this.minefield = (Minefield) readFile.readObject(); readFile.close(); if (minefield.isBoom() == true) { boom.play(); upset.play(); } else { playGame.play(); } } catch (FileNotFoundException e) { //不存在上局时,自动生成一局 this.minefield = new Minefield(file.getWidth(), file.getLength(), file.getLambnumber()); playGame.play(); // JOptionPane.showMessageDialog(null, "您还未开始游戏,不存在上局哦!"); // e.printStackTrace(); } catch (IOException e) { // e.printStackTrace(); } }
改正步骤
第一种错误:缺乏覆盖标志@Override
第二种:缺乏大括号
不足:没有设置计时器和剩余雷的个数。按钮没法改变大小,因此限制了游戏界面没法改变大小。
改良:设置一下计时器和剩余雷的个数,而后将按钮设置成能随着框的改变个改变大小,这就比较能够了。