Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 590|回复: 0

[算法学习]根据启发函数(A*算法)求解八数码问题

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-7 00:03:37 | 显示全部楼层 |阅读模式
    八数码方块移动游戏要求从一个含8个数字(用1-8表示)的方块以及一个空格方块(用0表示)的3x3矩阵的起始状态开始,不断移动该空格方块以使其和相邻的方 块互换,直至达到所定义的目标状态。空格方块在中间位置时有上、下、左、右4个方向可移动,在四个角落上有2个方向可移动,在其他位置上有3个方向可移 动。例如,假设一个3x3矩阵的初始状态为:
        8 0 3
        2 1 4
        7 6 5
    目标状态为:
        1 2 3
        8 0 4
        7 6 5
    则一个合法的移动路径为:
    1. 8 0 3     8 1 3     8 1 3     0 1 3     1 0 3    1 2 3
    2. 2 1 4  >  2 0 4  >  0 2 4  >  8 2 4   > 8 2 4  > 8 0 4
    3. 7 6 5     7 6 5     7 6 5     7 6 5     7 6 5    7 6 5
    复制代码

      
       
       
         
       

         
       
      
          另外,在所有可能的从初始状态到目标状态的移动路径中,步数最少的路径被称为最短路径;在上面的例子中,最短路径为5。如果不存在从初试状态到目标状态的任何路径,则称该组状态无解。 根据启发函数求解八数码问题


    1. import java.applet.Applet;
    2. import java.awt.*;
    3. import java.awt.Graphics;
    4. import java.util.Vector;
    5. public class EightNumber extends Applet implements Runnable
    6. {
    7. /*内部类,表示一个节点,如
    8.   * 0  1  2
    9.   * 3  4  5
    10.   * 6  7  8
    11.   */
    12. private class State
    13. {
    14.   int[] states = new int[9];
    15.   int size;
    16.   int steps;
    17.   public State(int [] s)
    18.   {
    19.    int i;
    20.    for(i=0;i<9;i++)
    21.     states[i] = s[i];
    22.   }
    23.   public boolean equals(State st)
    24.   {
    25.    int[] s=st.getStates();
    26.    int i;
    27.    for(i=0;i<9;i++)
    28.     if(s[i] != states[i])
    29.      return false;
    30.    return true;
    31.   }
    32. //返回从当前节点跳到下一节点时,与“0”交换移动的位置,这个位置的数字用红色画出
    33.   public int judgeMove(State st)
    34.   {
    35.    int[] s=st.getStates();
    36.    int i;
    37.    for(i=0;i<9;i++)
    38.    {
    39.     if(s[i] != states[i] && s[i]!=0)
    40.      return i;
    41.    }
    42.    return -1;
    43.   }
    44.   public int[] getStates()
    45.   {
    46.    return states;
    47.   }
    48.   public int expandSize()//返回从一个节点出发,可以扩展的点节数(以“0”为中心)
    49.   {
    50.    if(states[4] == 0)//如果"0"位于中心,可以扩展出4个节点
    51.     size = 4;
    52.    else if(states[0]==0 || states[2]==0 || states[6]==0 || states[8]==0)
    53.     size = 2;//如果“0”位于角上,可以扩展出2个节点
    54.    else
    55.     size = 3;//边上
    56.    return size;
    57.   }
    58.   public State[] expandState()//返回当前节点扩展出的所有节点
    59.   {
    60.    State[] st;
    61.    int [] ex=new int[9];
    62.    int i,j,k;
    63.    int m=0,n=0;
    64.    int a=0,b=0;
    65.    st = new State[size];
    66.    for(i=0;i<3;i++)
    67.    {
    68.     for(j=0;j<3;j++)
    69.     {
    70.      k = i*3+j;
    71.      ex[k] = states[k];
    72.      if(states[k] == 0)//记录“0”的位置
    73.      {
    74.       m = i;
    75.       n = j;
    76.      }
    77.     }
    78.    }
    79.    //以下根据"0"的位置,求出所有扩展的节点
    80.    i = 0;
    81.    a = m*3+n;
    82.    if(m-1>=0)
    83.    {
    84.     b = (m-1)*3+n;
    85.     ex[a] = ex[b];
    86.     ex[b] = 0;
    87.     st[i] = new State(ex);
    88.     ex[b] = ex[a];
    89.     ex[a] = 0;
    90.     i++;
    91.    }
    92.    if(m+1<=2)
    93.    {
    94.     b = (m+1)*3+n;
    95.     ex[a] = ex[b];
    96.     ex[b] = 0;
    97.     st[i] = new State(ex);
    98.     ex[b] = ex[a];
    99.     ex[a] = 0;
    100.     i++;
    101.    }
    102.    if(n-1>=0)
    103.    {
    104.     b = m*3+(n-1);
    105.     ex[a] = ex[b];
    106.     ex[b] = 0;
    107.     st[i] = new State(ex);
    108.     ex[b] = ex[a];
    109.     ex[a] = 0;
    110.     i++;
    111.    }
    112.    if(n+1<=2)
    113.    {
    114.     b = m*3+(n+1);
    115.     ex[a] = ex[b];
    116.     ex[b] = 0;
    117.     st[i] = new State(ex);
    118.     ex[b] = ex[a];
    119.     ex[a] = 0;
    120.     i++;
    121.    }
    122.    return st;
    123.   }
    124. }
    125. Image[] stateImg = new Image[10];
    126. Image[] moveImg = new Image[10];
    127. Image stepsImg;
    128. Vector vecClose = new Vector();//闭集,记录下已经扩展的节点
    129. Vector vecOpen = new Vector();//开集,记录下未扩展的节点
    130. int[] first = {7,2,4,5,0,6,8,3,1};
    131. int[] aim = {0,1,2,3,4,5,6,7,8};
    132. State nowState = null;//当前节点
    133. State aimState = new State(aim);//目标节点
    134. int stepX;
    135. int stepY;
    136. int startX;
    137. int startY;
    138. int steps;
    139. int move;
    140. boolean start;
    141. Thread moveTh = null;
    142. public void init()
    143. {
    144.   int i;
    145.   Integer tmp;
    146.   String fileName;
    147.   State st = new State(first);
    148.   st.steps = 0;
    149.   
    150.   resize(200,300);
    151.   startX = 16;
    152.   startY = 19;
    153.   stepX = 55;
    154.   stepY = 55;
    155.   steps = 0;
    156.   start = false;
    157.   move = -1;
    158.   for(i=0;i<10;i++)
    159.   {
    160.    tmp = new Integer(i);
    161.    fileName = "img/";
    162.    fileName = fileName + tmp.toString()+"_1.jpg";
    163.    stateImg[i] = getImage(getCodeBase(),fileName);
    164.    waitForImage(stateImg[i]);
    165.    fileName = "img/";
    166.    fileName = fileName + tmp.toString() + "_2.jpg";
    167.    moveImg[i] = getImage(getCodeBase(),fileName);
    168.    waitForImage(stepsImg);
    169.   }
    170.   vecOpen.add(st);//将首节点加入到开集中
    171.   fileName = "img/steps.jpg";
    172.   stepsImg = getImage(getCodeBase(),"img/steps.jpg");
    173.   waitForImage(stepsImg);
    174.    
    175. }

    176. public void waitForImage(Image i)//载入图像
    177.    {
    178.     MediaTracker tracker = new MediaTracker(this);
    179.         try
    180.         {
    181.          tracker.addImage(i,0);
    182.             tracker.waitForID(0);
    183.         }
    184.         catch(InterruptedException e) {System.err.println("Wait interrupted.");}
    185.    }

    186. public void paint(Graphics g) //画当前节点
    187. {
    188.   int i,j,k;
    189.   int[] state;
    190.   Integer tmp;
    191.   if(start == false)
    192.    return ;
    193.   state = nowState.getStates();
    194.   g.drawImage(stepsImg,startX+20,startY,this);
    195.   tmp = new Integer(steps);
    196.   g.drawString("第"+tmp.toString()+"步",startX+80,startY+20);
    197.   
    198.   for(i=0;i<3;i++)
    199.   {
    200.    for(j=0;j<3;j++)
    201.    {
    202.     k = i*3+j;
    203.    
    204.     if(move == k)
    205.     {
    206.      putNumber(g,state[k],i,j,false);//刚移动的位置,用红色画出
    207.     }
    208.     else
    209.     {
    210.      putNumber(g,state[k],i,j,true);
    211.     }
    212.    }
    213.   }
    214. }
    215. public void update(Graphics g)
    216. {
    217.   paint(g);
    218. }
    219. private void putNumber(Graphics g,int number,int i,int j,boolean isState )
    220. {
    221.   int x,y;
    222.   x = startX + j*stepX;
    223.   y = startY + i*stepY + stepY;
    224.   if(isState)
    225.   {
    226.    g.drawImage(stateImg[number],x,y,this);
    227.   }
    228.   else
    229.   {
    230.    g.drawImage(moveImg[number],x,y,this);
    231.   }
    232. }
    233. //启发函数,计算节点st与目标节点的距离(曼哈顿距离)。
    234. private int suggestFunc(State st)
    235. {
    236.   int i,j,m,n;
    237.   int a=0,b=0;
    238.   int result=0;
    239.   int[] state;
    240.   state = st.getStates();
    241.   for(i=0;i< 3;i++)
    242.   {
    243.    for(j=0;j< 3;j++)
    244.    {
    245.     a = i*3+j;
    246.     if(state[a]==0)
    247.      continue;
    248.     for(m=0;m< 3;m++)
    249.     {
    250.      for(n=0;n< 3;n++)
    251.      {
    252.       b = m*3+n;
    253.       if(state[a] == aim[b])
    254.       {
    255.        result += (Math.abs(m-i)+Math.abs(n-j));
    256.        break;
    257.       }
    258.      }
    259.      if(state[a] == aim[b])
    260.       break;
    261.     }
    262.    }
    263.   }
    264.   return result;
    265. }

    266. public void start()
    267. {
    268.   if(moveTh == null)
    269.   {
    270.    moveTh = new Thread(this);
    271.    moveTh.start();//启动线程
    272.   }
    273. }
    274. public void stop()
    275. {
    276.   if(moveTh != null)
    277.   {
    278.    moveTh = null;
    279.   }
    280. }
    281. public void run()
    282. {

    283.   searchPath();
    284. }

    285. //寻找路径
    286. private boolean searchPath()
    287. {
    288.   int openSize;
    289.   State st;
    290.   boolean result=false;
    291.   start = true;
    292.   while(!vecOpen.isEmpty())
    293.   {
    294.    openSize = vecOpen.size();;
    295.    st = (State)vecOpen.elementAt(openSize-1);
    296.    if(nowState != null)
    297.    {
    298.     move = nowState.judgeMove(st);
    299.    }
    300.    
    301.    nowState = st;
    302.    vecOpen.remove(openSize-1);
    303.    vecClose.add(nowState);
    304.    if(expandNowState() == 0)
    305.    {
    306.     result = true;
    307.    }
    308.    steps++;
    309.    repaint();
    310.    if(result == true)
    311.     break;
    312.    try
    313.    {
    314.     Thread.sleep(2000);
    315.    }
    316.    catch(InterruptedException e){}
    317.    
    318.   }
    319.   return result;
    320. }

    321. private boolean haveContained(State st)//判断闭集中是否包含节点st
    322. {
    323.   int size;
    324.   int i;
    325.   State tmp;
    326.   size = vecClose.size();
    327.   for(i=0;i< size;i++)
    328.   {
    329.    tmp = (State)vecClose.elementAt(i);
    330.    if(tmp.equals(st))
    331.     return true;
    332.   }
    333.   return false;
    334. }
    335. //扩展当前节点,1表示扩展成功,0表示找到目标节点,-1表示当前节点不可扩展
    336. private int expandNowState()
    337. {
    338.   int[] value = {255,255,255,255};
    339.   int size;
    340.   int i,j;
    341.   int have = -1;
    342.   State st[];
    343.   State tmpState;
    344.   int tmp;
    345.   size = nowState.expandSize();//当前节点能扩展的节点数
    346.   st = nowState.expandState();//获取所有扩展的节点
    347.   for(i=0;i< size;i++)
    348.   {
    349.    if(!haveContained(st[i]))
    350.    {
    351.     value[i] = suggestFunc(st[i]);
    352.     if(value[i] == 0)
    353.     {
    354.      move = nowState.judgeMove(st[i]);
    355.      nowState = st[i];
    356.      return 0;
    357.     }
    358.     else
    359.      have = 1;
    360.    }
    361.   }
    362.   if(have == 1)//对扩展的节点根据距离排序
    363.   {
    364.    for(i=0;i< size;i++)
    365.    {
    366.     for(j=i+1;j< size;j++)
    367.     {
    368.      if(value[j]>value[i])
    369.      {
    370.       tmp = value[j];
    371.       tmpState = st[j];
    372.       value[j] = value[i];
    373.       st[j] = st[i];
    374.       value[i] = tmp;
    375.       st[i] = tmpState;
    376.      }
    377.     }
    378.    }
    379.    for(i=0;i< size;i++)
    380.    {
    381.     if(value[i]!=255)
    382.     {
    383.      vecOpen.add(st[i]);//所有扩展的节点排序后放入开集
    384.     }
    385.    }
    386.   }
    387.   return have;
    388. }
    389. }
    390.                   
    复制代码


      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/11/7/000337140.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 10:39 , Processed in 0.369488 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表