Java GUI实战:Swing 实现可视化马尔可夫迭代(一)
问题
有一个Agent走迷宫。它在每个格子有四种选择:向上,向下,向左,向右。向上移动,有60%的概率移动到正上方的格子里,20%的概率移动到左上方的格子里,20%的概率移动到
右上方的格子里。其余方向同理。Agent需要找到一条从起点到终点的路。通过这个问题可视化演示马尔可夫迭代过程。
核心算法
马尔可夫迭代算法。细节见下一篇。
目标
设计一个5*5的迷宫,迷宫包括陷阱,障碍,起点,终点,以及干扰点,不同节点用不同的颜色标明。Agent从起点出发,找到一条到达终点的路径。
Agent走到终点,则找到一条路径;走到陷阱,则返回起点;走到干扰点,会获得一个较小的回报值(也就是干扰);走到障碍或边界,会返回之前所在的节点。
陷阱的回报值设置为-1,终点的回报值设置为1,干扰节点的回报值设为0.25,障碍的回报值设置为2(仅仅是为了之后在算法中识别障碍)。初始状态,所有节点状态值均为0.
GUI界面将包括一张地图,实时显示每次迭代的状态值。一个按钮next,点击即可进行一次马尔可夫迭代,旁边应能显示迭代的次数。一个按钮apply,旁边有输入框可以输入横坐标,
纵坐标,节点属性三元组,用以绘制地图。一个按钮play,用来锁定地图状态,并激活next按钮。一个按钮replay,用于将所有状态清零。一个按钮show route,用来显示在
某一状态下的寻路情况。同一迭代状态下,可以多次点击该按钮,以显示由于不确定性导致的寻路的多种可能。
实现效果
如图一,默认地图
如图二,迭代十次后状态
如图三,迭代十次后寻路
如图四,继续迭代至二十次寻路
如图五,迭代二十次再次寻路
Java Swing实现GUI
JFrame mainWindow = new JFrame("Markov Show");
mainWindow.setSize(500,700);//窗口大小,单位为像素
mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainWindow.setLocationRelativeTo(null);
GridLayout layout = new GridLayout(8,5);//采用网格模式
JPanel panel = new JPanel(layout);
ArrayList<JLabel> grids = new ArrayList<>();
for(int i=0;i<25;i++){
JLabel label = new JLabel(i+"",SwingConstants.CENTER);
label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
label.setBackground(Color.white);
label.setOpaque(true);
grids.add(label);
}
int[] startIndex = {0};
grids.get(0).setBackground(Color.BLUE);//start
grids.get(8).setBackground(Color.YELLOW);//Trump!
grids.get(15).setBackground(Color.GRAY);
grids.get(17).setBackground(Color.GRAY);
grids.get(22).setBackground(Color.GRAY);
grids.get(24).setBackground(Color.RED);//end
for(int i=0;i<25;i++){
panel.add(grids.get(i));
}
JButton next = new JButton("NEXT");//NEXT按钮
JLabel blank = new JLabel("");
JLabel nnn = new JLabel("N");
JLabel equals = new JLabel("=");
next.setEnabled(false);//没有点击PLAY时,NEXT不激活
//counters
int[] count={0};
JLabel showN = new JLabel(count[0]+"");
panel.add(next);
panel.add(blank);
panel.add(nnn);
panel.add(equals);
panel.add(showN);
int[] stepCount = {0};//显示迭代次数
//gamma
double[] gammaa = {0.25};//马尔可夫算法中的伽马值
//maze editor
JButton edit = new JButton("APPLY");
JLabel blank1 = new JLabel("");
JTextField editX = new JTextField("enter x");
JTextField editY = new JTextField("enter y");
JTextField editAttr = new JTextField("enter attribute");//自定义地图
JButton start = new JButton("PLAY");
JButton restart = new JButton("REPLAY");
JButton showRoute = new JButton("SHOW ROUTE");//寻路
JLabel totalStep = new JLabel("Total steps:");//从起点到终点多少步
JLabel stepCountShow =new JLabel(stepCount[0]+"");
panel.add(edit);
panel.add(blank1);
panel.add(editX);
panel.add(editY);
panel.add(editAttr);
panel.add(start);
panel.add(restart);
panel.add(showRoute);
panel.add(totalStep);
panel.add(stepCountShow);
double[] values = new double[25];
double[] rewards = new double[25];//奖励值
for(int i=0;i<25;i++)
values[i] = 0;
rewards[8]=0.25;//gold
rewards[15]=-1;
rewards[17]=-1;
rewards[22]=-1;
rewards[24]=1;//end
for(int i=0;i<25;i++){//可视化各节点状态值
if(rewards[i]==1||rewards[i]==-1){
grids.get(i).setText(rewards[i]+"");
}else {
grids.get(i).setText(values[i] + "");
}
}