}
public void resume(){//恢复迷宫 for(int i=0;i public void setEnd(int x,int y){ } public void setBegin(int x,int y){ } begin=new Position(x,y); end=new Position(x,y); } for(int j=0;j if(this.mazeMap[i][j]==2||this.mazeMap[i][j]==3){ } this.mazeMap[i][j]=0; 3.4 MazeGUI.java 3.4.1 效果图 MazeGUI类创建的迷宫图形界面窗口的效果图如图5所示。 16 图5 MazeGUI类创建的迷宫图形界面窗口的效果图 3.4.2 UML图 MazeGUI类是Frame类的一个子类,创建的对象是Rollback类最重要的成员之一。该类负责创建迷宫图形窗口界面,方便用户在界面上设置起点、终点、障碍等并展现求解迷宫的过程。该类还包含两个内部类SolveThead、AThread,该内部类实现了runnable接口。标明Maze类的主要成员变量、成员方法的UMl图如图6所示。 17 图6 MazeGUI类的UML图 以下是UML图中有关数据和方法的详细说明。 1) 成员变量 ? obj是Object类型的对象,该对象用于充当线程问题中的同步锁。 ? row、col是int类型的变量,用来设置值迷宫图形界面的大小(不是指长度和宽度)。 ? offScreen是Image类的对象,用于双缓冲技术防止屏幕闪烁。 ? maze是Maze类的对象。该对象是在MazeGUI类的构造方法中根据row和col的值来创 建的。 ? rollback是Rollback类的对象,该对象负责求解迷宫,并绘制人物在迷宫图形界面中 的位置。 ? t1、t2是Thread线程类的对象,该对象负责控制求解迷宫的线程,便于展现求解迷宫 的过程。 2) 成员方法 ? paint(Graphics g)方法,该方法调用了maze对象的draw(Graphics g)和rollback 对象的draw(Graphics g),分别绘制迷宫内容图像和人物图像。 ? update(Graphics g) ? MazeGUI(int row,int col)是MazeGUI类的构造方法,负责完成创建迷宫图形界面窗口 的初始化操作。初始化操作包括:根据row和col创建maze对象,并根据创建的maze对象和MazeGUI自身的一个引用来创建rollback对象;为迷宫图形窗口注册KeyEvent的事件监听器;设置窗口的大小,以及窗口在屏幕上显示的位置,设置菜单栏和菜单选项的内容,放入窗口中,并为菜单选项注册ActionEvent的事件监听器。 ? threadSleep()方法,在求解迷宫的过程结束时,MazeGUI类的对象可调用该方法暂 停求解迷宫线程,使求解迷宫线程等待。具体来说是,求解迷宫线程拥有MazeGUI类的对象的监视器,当对象调用该方法时,放弃对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。 18 然后该线程将等到重新获得对监视器的所有权后才能继续执行。 ? keyTyped(KeyEvent e)方法为KeyListener接口中的抽象方法,必须要实现,但在本 程序中没有实际用处,故在MazeGUI类中该方法为空方法; ? keyReleased(KeyEvent e)方法为KeyListener接口中的抽象方法,必须要实现,但在 本程序中没有实际用处,故在MazeGUI类中该方法为空方法; ? keyPressed(KeyEvent e)方法为KeyListener接口中的抽象方法,必须要实现。该 方法的操作如下:当按下键盘上的按键时,将会调用repaint()方法。根据所按下键的键值分成一下几种情况:若按下键盘的Enter键,将会把迷宫图形界面中定位方框位置对应的迷宫数组的元素值改为1,maze对象将在该位置绘制墙的图像;若按下键盘的Delete键,将会把迷宫图形界面中定位方框位置对应的迷宫数组的元素值改为0,maze对象将在该位置绘制通路的图像;若按下键盘方向键的上键,将会把迷宫图形界面中定位方框上移一个单位;若按下键盘方向键的下键,将会把迷宫图形界面中定位方框下移一个单位;若按下键盘方向键的左键,将会把迷宫图形界面中定位方框左移一个单位;若按下键盘方向键的右键,将会把迷宫图形界面中定位方框右移一个单位;若按下键盘的Home键,将会调用maze对象的setBegin(int x,int y)方法,把当前定位方框所在位置的坐标传给setBegin(int x,int y)方法,创建Maze类中的begin对象,并且maze对象将在该位置绘制起点图像;若按下键盘的End键,将会调用maze对象的setEnd(int x,int y)方法,把当前定位方框所在位置的坐标传给setEnd(int x,int y)方法,创建Maze类中的end对象,并且maze对象将在该位置绘制终点图像;若按下键盘的F9键,如果迷宫图形界面没有设置起点或终点,将会提示设置起点或终点,否则不能演示求解迷宫,如果迷宫设置完毕,将启动求解迷宫线程,演示求解迷宫的过程; ? actionPerformed(ActionEvent e)方法,当鼠标点击菜单选项时将把产生的事件传给该 方法,鼠标点击菜单选项“退出”时,将会关闭窗口并退出程序;鼠标点击刷新地图时,将会清空迷宫里内容,让用户重新设置。 3)内部类SolveThread ? 内部类SolveThread实现了runnable接口,是在MazeGUI内部定义的一个线程类。该 线程根据rollback.isOver()返回的值判断求解迷宫过程是否结束,若没有结束,则不断在求解过程中不断地使线程睡眠200毫秒,可使求解迷宫的过程能清楚地展现给用户,此外还调用rollback.forward()、rollback.back()等求解迷宫的核心算法,并调用repaint()重绘。 3.4.3 代码(MazeGUI.java) package maze; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * 迷宫图形界面 * */ @SuppressWarnings(\) 19 public class MazeGUI extends Frame implements KeyListener,ActionListener{//迷宫GUI final Object obj=new Object();//锁对象 int row=0,col=0; Image offScreen = null; Maze maze;//构建迷宫参数 Rollback rollback; Astar astar; Thread t1 = new Thread(new SolveThread(),\);//寻路进程, 在初始化Thread类时,把目标对象传递给这个线程实例 Thread t2 = new Thread(new AThread(),\); public void paint(Graphics g){//调用绘制地图的draw()方法和绘制人物位置的draw()方法 maze.draw(g); } public MazeGUI() { } public MazeGUI(int row,int col){//初始化窗体 this.setTitle(\算法课程设计-求解迷宫问题\); this.setSize(col*50, row*50); this.setLocation(200, 80); this.setResizable(false); this.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ } System.exit(0); public void update(Graphics g){//双缓冲防止屏幕闪烁 if(offScreen == null){ } Graphics offg = offScreen.getGraphics(); Color c = offg.getColor(); offg.setColor(Color.BLUE); offg.fillRect(0, 0, col*50, row*50); offg.setColor(c); paint(offg); g.drawImage(offScreen, 0, 0, null); offScreen = this.createImage(col*50, row*50); } rollback.draw(g); }); 20