先看一个有意思的问题, 我们定义一个二维数组表示迷宫。

它表示一个迷宫, 其中的1表示墙壁,0表示可以走的路, 只能横着走或竖着走,不能斜着走,

我们要编程序找出从左上角到右下角的路线。其实这个问题可以用深度优先搜索的方法搞定的了。

这个算法中涉及到了几个知识:

1. 一个是栈,每走过一个点会把这个点会把这个点压入栈中。

2. 用一个新的数据结构保存走迷宫的路线,每个走过的点都有一个前趋(Predecessor)的点,表示是从哪儿走到

当前点的,比如predecessor[4][4]是座标为(3, 4)的点,就表示从(3, 4)走到了(4, 4),一开始predecessor的各元素

初始化为无效座标(-1, -1)。在迷宫中探索路线的同时就把路线保存在predecessor数组中。

3. 已经走过的点在maze数组中记为2防止重复走。 算法的伪代码如下 :

分为几个文件来分开实现 :

/* main.c */

/***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015               */
/*                                                         */
/*  FILE NAME             :  main.c                   */
/*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
/*  SUBSYSTEM NAME        :  MakFile                       */
/*  MODULE NAME           :  makefile                      */
/*  LANGUAGE              :  C                             */
/*  TARGET ENVIRONMENT    :  ANY                           */
/*  DATE OF FIRST RELEASE :  2015/04/05                    */
/*  DESCRIPTION           :  This is a makefile program    */
/***********************************************************/

/*
 *Revision log:
 *
 *Ceated by GaoZhipeng, 2015/04/05
 *     
 */


#include<stdio.h>
#include"main.h"
#include"stack.h"
#include"maze.h"

struct point predecessor[MAX_ROW][MAX_COL] = {
    {{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
    {{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
    {{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
    {{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
    {{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}},
};


void visit(int row, int col, struct point pre)
{
    struct point visit_point = {row, col};
    maze[row][col] = 2;
    predecessor[row][col] = pre;
    push(visit_point);
}

int main(void)
{
    struct point p = { 0, 0 };
    maze[p.row][p.col] = 2;
    push(p);
    while (!is_empty()) {
        p = pop();
        if (p.row == MAX_ROW - 1 /* goal */
                && p.col == MAX_COL - 1)
            break;
        if (p.col+1 < MAX_COL
                /* right */
                && maze[p.row][p.col+1] == 0)
            visit(p.row, p.col+1, p);
        if (p.row+1 < MAX_ROW
                /* down */
                && maze[p.row+1][p.col] == 0)
            visit(p.row+1, p.col, p);
        if (p.col-1 >= 0
                /* left */
                && maze[p.row][p.col-1] == 0)
            visit(p.row, p.col-1, p);
        if (p.row-1 >= 0
                /* up */
                && maze[p.row-1][p.col] == 0)
            visit(p.row-1, p.col, p);
        print_maze();
    }
    if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1) {
        printf("(%d, %d)\n", p.row, p.col);
        while (predecessor[p.row][p.col].row != -1) {
            p = predecessor[p.row][p.col];
            printf("(%d, %d)\n", p.row, p.col);
        }
    } else
        printf("No path!\n");
    return 0;
}
View Code

/* main.h */

/***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015               */
/*                                                         */
/*  FILE NAME             :  main.h                   */
/*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
/*  SUBSYSTEM NAME        :  MakFile                       */
/*  MODULE NAME           :  makefile                      */
/*  LANGUAGE              :  C                             */
/*  TARGET ENVIRONMENT    :  ANY                           */
/*  DATE OF FIRST RELEASE :  2015/04/05                    */
/*  DESCRIPTION           :  This is a makefile program    */
/***********************************************************/

/*
 *Revision log:
 *
 *Ceated by GaoZhipeng, 2015/04/05
 *     
 */


#ifndef MAIN_H
#define MAIN_H

typedef struct point{
    int row, col;
} item_t;

#define MAX_ROW 5
#define MAX_COL 5

#endif
View Code

/* maze.c */

/***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015               */
/*                                                         */
/*  FILE NAME             :  maze.c                   */
/*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
/*  SUBSYSTEM NAME        :  MakFile                       */
/*  MODULE NAME           :  makefile                      */
/*  LANGUAGE              :  C                             */
/*  TARGET ENVIRONMENT    :  ANY                           */
/*  DATE OF FIRST RELEASE :  2015/04/05                    */
/*  DESCRIPTION           :  This is a makefile program    */
/***********************************************************/

/*
 *Revision log:
 *
 *Ceated by GaoZhipeng, 2015/04/05
 *     
 */

#include<stdio.h>
#include"maze.h"

int maze[MAX_ROW][MAX_COL] = {
    0, 1, 0, 0, 0,
    0, 1, 0, 1, 0,
    0, 0, 0, 0, 0,
    0, 1, 1, 1, 0,
    0, 0, 0, 1, 0,
};

void print_maze(void)
{
    int i, j;
    for(i=0; i<MAX_ROW; i++)
    {
        for(j=0; j<MAX_COL; j++)
        {
            printf("%d ", maze[i][j]);
        }
        putchar('\n');
    }

    printf("*********\n");
}
View Code

/* maze.h */

/***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015               */
/*                                                         */
/*  FILE NAME             :  maze.h                   */
/*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
/*  SUBSYSTEM NAME        :  MakFile                       */
/*  MODULE NAME           :  makefile                      */
/*  LANGUAGE              :  C                             */
/*  TARGET ENVIRONMENT    :  ANY                           */
/*  DATE OF FIRST RELEASE :  2015/04/05                    */
/*  DESCRIPTION           :  This is a makefile program    */
/***********************************************************/

/*
 *Revision log:
 *
 *Ceated by GaoZhipeng, 2015/04/05
 *     
 */


#ifndef MAZE_H
#define MAZE_H


#include"main.h"



extern int maze[MAX_ROW][MAX_COL];
void print_maze(void);


#endif
View Code

/* stack.c */

/***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015               */
/*                                                         */
/*  FILE NAME             :  stack.c                       */
/*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
/*  SUBSYSTEM NAME        :  MakFile                       */
/*  MODULE NAME           :  makefile                      */
/*  LANGUAGE              :  C                             */
/*  TARGET ENVIRONMENT    :  ANY                           */
/*  DATE OF FIRST RELEASE :  2015/04/05                    */
/*  DESCRIPTION           :  This is a makefile program    */
/***********************************************************/

/*
 *Revision log:
 *
 *Ceated by GaoZhipeng, 2015/04/05
 *     
 */

#include"stack.h"

static item_t stack[512];
static int top = 0;


void push(item_t p)
{
    stack[top++] = p;
}


item_t pop(void)
{
    return stack[--top];
}

int is_empty(void)
{
    return top == 0;
}
View Code

/* stack.h */

/***********************************************************/
/* Copyright (C) SA14226214, USTC, 2014-2015               */
/*                                                         */
/*  FILE NAME             :  stack.h                       */
/*  PRINCIPAL AUTHOR      :  GaoZhipeng                    */
/*  SUBSYSTEM NAME        :  MakFile                       */
/*  MODULE NAME           :  makefile                      */
/*  LANGUAGE              :  C                             */
/*  TARGET ENVIRONMENT    :  ANY                           */
/*  DATE OF FIRST RELEASE :  2015/04/05                    */
/*  DESCRIPTION           :  This is a makefile program    */
/***********************************************************/

/*
 *Revision log:
 *
 *Ceated by GaoZhipeng, 2015/04/05
 *     
 */


#ifndef STACK_H
#define STACK_H


#include "main.h"

extern void push(item_t);
extern item_t pop(void);
extern int is_empty(void);


#endif
View Code

 然后我们要做的就是在Linux下对上述程序进行编译和运行。

 对于程序的编译命令, 最原始的编译指令可以这样写:  $ gcc main.c stack.c maze.c -o main

 不过还有一个更加简便的操作, 那就是写一个Makefile文件和源代码放在同一个目录下面。下面是一个写好的Makefile

# This is an simple makefile


main : main.o stack.o maze.o
       gcc main.o stack.o maze.o -o main
    
main.o : main.c main.h stack.h maze.h
         gcc -c main.c -o main.o

stack.o : stack.c stack.h main.h
          gcc -c stack.c -o stack.o

maze.o : maze.c maze.h main.h
         gcc -c maze.c -o maze.o
         
clean : 
        @echo "cleanning the project"
        -rm main *.o
        @echo "cleanning completed"

.PHONY : clean

 make 命令会自动读取当前目录下的Makefile 文件, 完成相应的编译步骤。Makefile由一组规则(Rule)组成,每条规则的格式是:

 例如 :  main: main.o stack.o maze.o
      gcc main.o stack.o maze.o -o main

main 是这条规则的目标(Target),main.o、stack.o 和maze.o是这条规则的条件(Prerequisite)。目标和条件之间的关系是:欲更新目标,

必须首先更新它的所有条件;所有条件中只要有一个条件被更新了,目标也必须随之被更新。所谓“更新”就是执行一遍规则中的命令列表,

命令列表中的每条命令必须以一个Tab开头,注意不能是空格,Makefile的格式不像C语言的缩进那么随意,对于Makefile中的每个以Tab

开头的命令,make 会创建一个Shell进程去执行它。

Makefile中有一些常用的特殊变量 :

  • $@ ,表示规则中的目标。
  • $< ,表示规则中的第一个条件。
  • $?,表示规则中所有比目标新的条件,组成一个列表,以空格分隔。
  • $^ ,表示规则中的所有条件,组成一个列表,以空格分隔。

那么我们可以把Makefile进一步化简, 写成如下的形式:

#this is a makefile

all : main

main : main.o stack.o maze.o
    gcc $^ -o $@

main.o : main.h stack.h maze.h
stack.o : stack.h main.h
maze.o : maze.h main.h

clean :
    -rm main *.o

.PHONY: clean

把命令 gcc main.o stack.o maze.o -o main 改写成 gcc $^ -o $@。

这样即使以后又往条件里添加了新的目标文件,编译命令也不需要修改,减少了出错的可能。

posted on 2015-04-08 17:51  beyond_Acm  阅读(245)  评论(0编辑  收藏  举报