人工智能实验4——用盲目搜索求解八数码问题

八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。


广度优先搜索算法流程:

1. 把起始节点放到OPEN表中(如果该起始节点为一目标节点,则求得一个解答)。
2. 如果OPEN是个空表,则没有解,失败退出;否则继续。
3. 把第一个节点(节点n)从OPEN表移出,并把它放入CLOSED的扩展节点表中。 扩展节点n。如果没有后继节点,则转向上述第(2)步。
4. 把n的所有后继节点放到OPEN表末端,并提供从这些后继节点回到n的指针。
5. 如果n的任一个后继节点是个目标节点,则找到一个解答,成功退出;否则转向第(2)步。

package com.Mytest;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

public class test {//广度优先搜索

    class EightNumNode{
        int[][] numMap;    //eight num map
        int x;          //the space coordinate in lateral
        int y;            //the space coordinate in vertical
        int parentID;    //the ID of parent(the ID is the index in the closeList)
        int selfID;        //the ID of itself
    }

    public static EightNumNode beginStat;
    public static EightNumNode endStat;
    public static Queue<EightNumNode> openList;
    public static ArrayList<EightNumNode> closeList; 
    public static Stack<EightNumNode> pathStack;
    
    public int findSpaceX(int[][] M){
        for(int i=0; i<M.length; i++)
            for(int j=0; j<M[0].length; j++)
                if(M[i][j] == 0)
                    return i;
        return -1;
    }
    
    public int findSpaceY(int[][] M){
        for(int i=0; i<M.length; i++)
            for(int j=0; j<M[0].length; j++)
                if(M[i][j] == 0)
                    return j;
        return -1;
    }
    
    public boolean checkSame(int[][] A, int[][] B){
        for(int i=0; i<A.length; i++)
            for(int j=0; j<A[0].length; j++)
                if(A[i][j] != B[i][j])
                    return false;
        return true;
    }
    
    public void printMap(int[][] M){
        for(int i=0; i<M.length; i++){
            for(int j=0; j<M[0].length; j++){
                System.out.print(M[i][j]+" ");
            }
            System.out.println();
        }
    }
    
    public boolean expendPointN(EightNumNode par){
        if(par.y-1 >= 0){//move left
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x][par.y-1];
            son.numMap[par.x][par.y-1] = 0;
            son.x = par.x;
            son.y = par.y-1;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.offer(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.offer(son);
            }
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }
        if(par.x-1 >= 0){//move up
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x-1][par.y];
            son.numMap[par.x-1][par.y] = 0;
            son.x = par.x-1;
            son.y = par.y;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.offer(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.offer(son);
            }            
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }
        if(par.y+1 < 3){//move right
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x][par.y+1];
            son.numMap[par.x][par.y+1] = 0;
            son.x = par.x;
            son.y = par.y+1;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.offer(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.offer(son);
            }
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }
        if(par.x+1 < 3){//move down
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x+1][par.y];
            son.numMap[par.x+1][par.y] = 0;
            son.x = par.x+1;
            son.y = par.y;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.offer(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.offer(son);
            }
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }
        return false;
    }
    
    public void driver(int[][] beginM, int[][] endM){
        
        openList = new LinkedList<test.EightNumNode>(); 
        closeList = new ArrayList<test.EightNumNode>();
        pathStack = new Stack<test.EightNumNode>();
        //set the begin state
        beginStat = new EightNumNode();
        beginStat.numMap = beginM;
        beginStat.x = findSpaceX(beginM);
        beginStat.y = findSpaceY(beginM);
        beginStat.parentID = -1;
        //set the end state
        endStat = new EightNumNode();
        endStat.numMap = endM;
        endStat.x = findSpaceX(endM);
        endStat.y = findSpaceY(endM);
        endStat.parentID = -1;
        
        openList.offer(beginStat);
        EightNumNode n;
        int idcount = 0;
        while (!openList.isEmpty()) {
            n = openList.remove();
            closeList.add(n);
            n.selfID = idcount++;
            if (expendPointN(n)) {
                System.out.println("Success!!!");
                break;
            }
        }
        
        if (openList.isEmpty()) {
            System.out.println("Fail!!!");
        } else {
            int tempParID = pathStack.peek().parentID;
            EightNumNode tempNode;
            while(tempParID != -1){
                tempNode = closeList.get(tempParID);
                pathStack.push(tempNode);
                tempParID = tempNode.parentID;
            }
            System.out.println("The path from beginning to end:");
            int i=0;
            while(!pathStack.empty()){
                System.out.println("step "+(i++));
                printMap(pathStack.pop().numMap);
                System.out.println();
            }
            
        }
    }
    
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("Please input the beginMAP:");
        int[][] beginMap = new int[3][3];
        for(int i=0; i<beginMap.length; i++)
            for(int j=0; j<beginMap[0].length; j++)
                beginMap[i][j] = scan.nextInt();
        System.out.println("Please input the endMAP:");
        int[][] endMap = new int[3][3];
        for(int i=0; i<endMap.length; i++)
            for(int j=0; j<endMap[0].length; j++)
                endMap[i][j] = scan.nextInt();
/*        int[][] beginMap = { { 2, 8, 3 }, 
                              { 1, 0, 4 }, 
                              { 7, 6, 5 } };
        int[][] endMap = { { 1, 2, 3 }, 
                            { 8, 0, 4 }, 
                            { 7, 6, 5 } };
*/
        test t = new test();
        if(t.checkSame(beginMap, endMap)){
            System.out.println("The beginMap and endMap are the same.");
            System.out.println("No need to move!");
        }
        else{
            t.driver(beginMap, endMap);
        }
        
    } 

}

 

深度优先搜索算法流程:

1. 把起始节点放到OPEN表中(如果该起始节点为一目标节点,则求得一个解答)。
2. 如果OPEN是个空表,则没有解,失败退出;否则继续。
3. 把第一个节点(节点n)从OPEN表移出,并把它放入CLOSED的扩展节点表中。
4. 考察节点n是否为目标节点,若是,则找到问题的解,用回溯法求解路径,退出
5. 如果没有后继节点,则转向上述第(2)步。
6. 扩展节点n,把n的所有后继节点放到OPEN表前端,并提供从这些后继节点回到n的指针。转向第(2)步。

package com.Mytest;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

public class test2 {//深度优先搜索

    class EightNumNode{
        int[][] numMap;
        int x;
        int y;
        int parentID;
        int selfID;
    }

    public static EightNumNode beginStat;
    public static EightNumNode endStat;
    public static Stack<EightNumNode> openList;
    public static ArrayList<EightNumNode> closeList; 
    public static Stack<EightNumNode> pathStack;
    
    public int findSpaceX(int[][] M){
        for(int i=0; i<M.length; i++)
            for(int j=0; j<M[0].length; j++)
                if(M[i][j] == 0)
                    return i;
        return -1;
    }
    
    public int findSpaceY(int[][] M){
        for(int i=0; i<M.length; i++)
            for(int j=0; j<M[0].length; j++)
                if(M[i][j] == 0)
                    return j;
        return -1;
    }
    
    public boolean checkSame(int[][] A, int[][] B){
        for(int i=0; i<A.length; i++)
            for(int j=0; j<A[0].length; j++)
                if(A[i][j] != B[i][j])
                    return false;
        return true;
    }
    
    public void printMap(int[][] M){
        for(int i=0; i<M.length; i++){
            for(int j=0; j<M[0].length; j++){
                System.out.print(M[i][j]+" ");
            }
            System.out.println();
        }
    }
    
    public boolean expendPointN(EightNumNode par){
        if(par.x+1 < 3){//move down
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x+1][par.y];
            son.numMap[par.x+1][par.y] = 0;
            son.x = par.x+1;
            son.y = par.y;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.push(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.push(son);
            }
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }
        if(par.y+1 < 3){//move right
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x][par.y+1];
            son.numMap[par.x][par.y+1] = 0;
            son.x = par.x;
            son.y = par.y+1;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.push(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.push(son);
            }
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }
        if(par.x-1 >= 0){//move up
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x-1][par.y];
            son.numMap[par.x-1][par.y] = 0;
            son.x = par.x-1;
            son.y = par.y;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.push(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.push(son);
            }            
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }
        if(par.y-1 >= 0){//move left
            EightNumNode son = new EightNumNode();
            son.numMap = new int[3][3];
            for(int i=0; i<par.numMap.length; i++)
                for(int j=0; j<par.numMap[0].length; j++)
                    son.numMap[i][j] = par.numMap[i][j];
            son.numMap[par.x][par.y] = son.numMap[par.x][par.y-1];
            son.numMap[par.x][par.y-1] = 0;
            son.x = par.x;
            son.y = par.y-1;
            son.parentID = par.selfID;
            if(par.parentID == -1){
                openList.push(son);
            }
            else {
                if(!checkSame(son.numMap, closeList.get(par.parentID).numMap))
                    openList.push(son);
            }
            if(checkSame(son.numMap, endStat.numMap)){
                pathStack.push(son);
                return true;
            }
        }    
        return false;
    }
    
    public void driver(int[][] beginM, int[][] endM){
        
        openList = new Stack<EightNumNode>(); 
        closeList = new ArrayList<EightNumNode>();
        pathStack = new Stack<EightNumNode>();
        
        beginStat = new EightNumNode();
        beginStat.numMap = beginM;
        beginStat.x = findSpaceX(beginM);
        beginStat.y = findSpaceY(beginM);
        beginStat.parentID = -1;
        
        endStat = new EightNumNode();
        endStat.numMap = endM;
        endStat.x = findSpaceX(endM);
        endStat.y = findSpaceY(endM);
        endStat.parentID = -1;
        
        openList.push(beginStat);
        EightNumNode n;
        int idcount = 0;
        while (!openList.isEmpty()) {
            n = openList.pop();
            closeList.add(n);
            n.selfID = idcount++;
            if (expendPointN(n)) {
                System.out.println("Success!!!");
                break;
            }
        }
        if (openList.isEmpty()) {
            System.out.println("Fail!!!");
        } else {
            int tempParID = pathStack.peek().parentID;
            EightNumNode tempNode;
            while(tempParID != -1){
                tempNode = closeList.get(tempParID);
                pathStack.push(tempNode);
                tempParID = tempNode.parentID;
            }
            System.out.println("The path from beginning to end:");
            int i=0;
            while(!pathStack.empty()){
                System.out.println("step "+(i++));
                printMap(pathStack.pop().numMap);
                System.out.println();
            }
            
        }
    }
    
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("Please input the beginMAP:");
        int[][] beginMap = new int[3][3];
        for(int i=0; i<beginMap.length; i++)
            for(int j=0; j<beginMap[0].length; j++)
                beginMap[i][j] = scan.nextInt();
        System.out.println("Please input the endMAP:");
        int[][] endMap = new int[3][3];
        for(int i=0; i<endMap.length; i++)
            for(int j=0; j<endMap[0].length; j++)
                endMap[i][j] = scan.nextInt();
/*        int[][] beginMap = { { 2, 8, 3 }, 
                              { 1, 0, 4 }, 
                              { 7, 6, 5 } };
        int[][] endMap = { { 1, 2, 3 }, 
                            { 8, 0, 4 }, 
                            { 7, 6, 5 } };
*/
        test t = new test();
        if(t.checkSame(beginMap, endMap)){
            System.out.println("The beginMap and endMap are the same.");
            System.out.println("No need to move!");
        }
        else{
            t.driver(beginMap, endMap);
        }
        
    } 

}

直接运行程序,输入开始的八数码状态图(源),和结束的八数码状态图(目标),会打印出相应的从源图到目标图移动的路径上的所有节点,也就是打印了一种成功的解法。
广度优先搜索和深度优先搜索的代码结构基本一致,主要区别在
广度:open表用队列,扩展节点N的顺序是左上右下        深度:open表用栈,扩展节点N的顺序是下右上左

有个很好的PPT可以帮助理解 http://wenku.baidu.com/view/6fb5e40ebb68a98271fefa4b.html




posted @ 2013-04-11 16:40  sillypudding  阅读(3227)  评论(1编辑  收藏  举报