启发式搜索算法求解八数码问题(C)

原创 2012年08月07日 21:19:16


下午看一个游戏的算法时看了一下启发式搜索算法,心血来潮跑了一遍很久很久以前写八数码的程序(C语言),发现各种问题,后来顺着思路整理了一下,贴出来和大家分享一下,直接上代码:

//
//  main.c
//  yunsuan
//
//  Created by mac on 12-8-7.
//  Copyright 2012年 __MyCompanyName__. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 3 //数码组大小
#define Max_Step 50 //最大搜索深度
#define MAX 50

typedef struct node//八数码结构体
{
    int form[N][N];//数码组
    int evalue;//评估值
    int udirect;//所屏蔽方向,防止往回推到上已状态,1上2下3左4右
    struct node *parent;//父节点
}Graph;

Graph *Qu[MAX];//队列
Graph *St[MAX];//堆栈

/////////打印数码组
void Print(Graph *The_graph)
{
    int i,j;
    if(The_graph==NULL)
        printf("图为空\n");
    else
    {
        printf("---------------------\n");
        for(i=0;i<N;i++)
        {
            printf("|\t");
            for(j=0;j<N;j++)
            {
                printf("%d\t",The_graph->form[i][j]);//遍历打印
            }
            printf("\t|\n");
        }
        printf("|\t\t\t差距:%d\t|\n",The_graph->evalue);//差距显示
        printf("---------------------\n");
    }
}

/////////评价函数
int Evaluate(Graph *The_graph,Graph *End_graph)
{
    int valute=0;//差距数
    int i,j;
    for(i=0;i<N;i++)
    {
        for(j=0;j<N;j++)
        {
            if(The_graph->form[i][j]!=End_graph->form[i][j])
            {
                valute++;
            }
        }
    }
    The_graph->evalue=valute;
    return valute;
}

/////////移动数码组
Graph *Move(Graph *The_graph,int Direct,int CreatNew_graph)
{
    Graph *New_graph;//
    int HasGetBlank=0;//是否获取空格位置
    int AbleMove=1;//是否可移动
    int i,j,t_i,t_j,x,y;
    
    for(i=0;i<N;i++)//获取空格坐标i,j
    {
        for(j=0;j<N;j++)
        {
            if(The_graph->form[i][j]==0)
            {
                HasGetBlank=1;
                break;
            }
        }
        if(HasGetBlank==1)
            break;
    }
    //printf("空格位置:%d,%d\n",i,j);
    
    t_i=i;
    t_j=j;
    
    //移动空格
    switch(Direct)
    {
        case 1://上
            t_i--;
            if(t_i<0)
                AbleMove=0;
            break;
        case 2://下
            t_i++;
            if(t_i>=N)
                AbleMove=0;
            break;
        case 3://左
            t_j--;
            if(t_j<0)
                AbleMove=0;
            break;
        case 4://右
            t_j++;
            if(t_j>=N)
                AbleMove=0;
            break;
            
    }
    
    if(AbleMove==0)//不能移动则返回原节点
    {
        return The_graph;
    }
    if(CreatNew_graph==1)
    {
        New_graph=(Graph *)malloc(sizeof(Graph));//生成节点
        for(x=0;x<N;x++)
        {
            for(y=0;y<N;y++)
            {
                New_graph->form[x][y]=The_graph->form[x][y];//复制数码组
            }

        }
    }
    else
    {
        New_graph=The_graph;
    }
    //移动后
    New_graph->form[i][j]=New_graph->form[t_i][t_j];
    New_graph->form[t_i][t_j]=0;
    //printf("移动产生的新图:\n");
    //Print(New_graph);
    return New_graph;
}

/////////搜索函数
Graph *Search(Graph *Begin,Graph *End)
{
    Graph *g1,*g2,*g;
    int Step=0;//深度
    int Direct=0;//方向
    int i;
    int front,rear;
    front=rear=-1;//队列初始化
    g=NULL;
    rear++;//入队
    Qu[rear]=Begin;
    while(rear!=front)//队列不空
    {
        front++;//出队
        g1=Qu[front];
        //printf("开始第%d个图:\n",front);
        //Print(g1);
        for(i=1;i<=4;i++)//分别从四个方向推导出新子节点
        {
            Direct=i;
            if(Direct==g1->udirect)//跳过屏蔽方向
                continue;
            g2=Move(g1, Direct, 1);//移动数码组
            
            if(g2!=g1)//数码组是否可以移动
            {
                //可以移动
                Evaluate(g2, End);//评价新的节点
                //printf("开始产生的第%d个图:\n",i);
                //Print(g2);
                if(g2->evalue<=g1->evalue+1)
                {
                    //是优越节点
                    g2->parent=g1;
                    //移动空格
                    switch(Direct)//设置屏蔽方向,防止往回推
                    {
                        case 1://上
                            g2->udirect=2;
                            break;
                        case 2://下
                            g2->udirect=1;
                            break;
                        case 3://左
                            g2->udirect=4;
                            break;
                        case 4://右
                            g2->udirect=3;
                            break;
                            
                    }
                    rear++;
                    Qu[rear]=g2;//存储节点到待处理队列
                    if(g2->evalue==0)//为0则搜索完成
                    {
                        g=g2;
                        //i=5;
                        break;
                    }
                }
                else
                {
                    free(g2);//抛弃劣质节点
                    g2=NULL;
                }
            }
            
        }
        
        if(g!=NULL)//为0则搜索完成
        {
            if(g->evalue==0)
            {
                break;
            }
        }
        
        Step++;//统计深度
        if(Step>Max_Step)
        {
            break;
        }
    }
    return g;
}

/////////初始化一个八数码结构体
Graph *CR_BeginGraph(Graph *The_graph)
{
    srand((unsigned)time(0));
    int M=10;//随机移动步数
    int Direct;
    int i,x,y;
    Graph *New_graph;
    New_graph=(Graph *)malloc(sizeof(Graph));
    for(x=0;x<N;x++)
    {
        for(y=0;y<N;y++)
        {
            New_graph->form[x][y]=The_graph->form[x][y];
        }
    }
    for(i=0;i<M;i++)
    {
        Direct=rand()%4+1;//产生1-4随机数
        //printf("Direct:%d\n",Direct);
        New_graph=Move(New_graph, Direct, 0);
        //Print(New_graph);
    }
    
    New_graph->evalue=0;
    New_graph->udirect=0;
    New_graph->parent=NULL;
    
    return New_graph;
}

int main (int argc, const char * argv[])
{
    
    // insert code here...
    /*
    Graph Begin_graph={
        {{2,8,3},{1,6,4},{0,7,5}},0,0,NULL
    };
    
    Graph Begin_graph={
        {{2,8,3},{1,0,4},{7,6,5}},0,0,NULL
    };
    
    
    Graph Begin_graph={
        {{2,0,1},{4,6,5},{3,7,8}},0,0,NULL
    };
    */
    
    //目标数码组
    Graph End_graph={
        {{1,2,3},{8,0,4},{7,6,5}},0,0,NULL
    };
    
    //初始数码组
    Graph *Begin_graph;
    Begin_graph=CR_BeginGraph(&End_graph);//随机产生初始数码组
    Evaluate(Begin_graph, &End_graph);//对初始的数码组评价
    printf("初始数码组:\n");
    Print(Begin_graph);
    printf("目标数码组:\n");
    Print(&End_graph);
    
    Graph *G,*P;
    int top=-1;
    
    //图搜索
    G=Search(Begin_graph, &End_graph);
    //打印
    if(G)
    {
        //把路径倒序
        P=G;
        //压栈
        while(P!=NULL)
        {
            top++;
            St[top]=P;
            P=P->parent;
        }
        printf("<<<<<<<<<<<<<<<搜索结果>>>>>>>>>>>>>>>>\n");
        //弹栈打印
        while(top>-1)
        {
            P=St[top];
            top--;
            Print(P);
        }
        printf("<<<<<<<<<<<<<<<<<完成>>>>>>>>>>>>>>>>>>\n");
    }
    else
    {
        printf("搜索不到结果,深度为%d\n",Max_Step);
        //设计搜索深度范围主要是防止队列内存越界
    }

    
    return 0;
}

 

八数码问题的过程表示及其实现

过程式知识表示是将有关某一问题领域的知识, 连同如何使用这些知识的方法,均隐式的表达为 一个求解问题的过程,每个过程是一段程序,完 成对具体情况的处理。过程式不像陈述式那样具有固定的形式,如何描述知识...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

用C语言实现八数码问题

#include#includeint n,m;typedef struct Node{char matrix[10];/*存储矩阵*/char operate;/*存储不可以进行的操作,L代表不能左...

A*算法的简单实现(八数码问题)

第一部分:A*算法简介 程序环境: 运行环境:Windows xp 使用工具:Vc++6.0 启发式搜索简介: 启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

八数码问题-启发式搜索(A*算法)

八数码问题是这样一个问题。有一个3x3大小的棋盘,上面放着标记有1~8八个数字的方形棋子,剩下一个区域为空。 每一次只能移动一个棋子到相邻的空区域上,8个棋子都移动到如下图所示的位置时,就结束了。...

启发式搜索-A*算法解决八数码问题

代码如下: From [Artificial Intelligence: A System Approach] /* 用启发式算法——A*搜索来解决八数码问题 */ #include #d...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

八数码问题(启发式搜索)

(一)问题描述在一个3*3的方棋盘上放置着1,2,3,4,5,6,7,8八个数码,每个数码占一格,且有一个空格。这些数码可以在棋盘上移动,其移动规则是:与空格相邻的数码方格可以移入空格。现在的问题是:...
  • zuzubo
  • zuzubo
  • 2007年03月25日 02:22
  • 8424
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:启发式搜索算法求解八数码问题(C)
举报原因:
原因补充:

(最多只允许输入30个字)