求解字谜游戏问题

来源:互联网 发布:windows 打tar包 编辑:程序博客网 时间:2024/04/27 19:07

解决一个流行的字谜。输入是由一些字母和单词的二维数组组成。目标是赵楚字谜中的单词,这些单词可能是水平、垂直或沿着对角线异任何方向放置的。例如求解下图:

图1-1 字谜示例
12341 this2wats3oahg4fgdt


书中给出的直观算法:对单词表中的每个单词。我们检查每一个有序三元组(行,列,方向),验证单词的存在。算是直接暴力查找吧。书中后续章节有优化方法, 以后再做研究。现直观算法代码如下:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#define WORD_PUZZLE_TABLE_WIDTH 4#define WORD_PUZZLE_TABLE_HIGHT 4/** 字谜表 */const char word_puzzle_table[WORD_PUZZLE_TABLE_WIDTH][WORD_PUZZLE_TABLE_HIGHT] ={    {'t', 'h', 'i', 's'},    {'w', 'a', 't', 's'},    {'o', 'a', 'h', 'g'},    {'f', 'g', 'd', 't'}};/** 单词表 */const char *word_table[] = {"this", "two", "fat", "that"};#define WORD_TABLE_LEN (sizeof(word_table) / sizeof(char*))/** 点结构体 */typedef struct point{    int x;    int y;} point;/** * 查找结果结构体 * pword    查找结果单词指针 * begin    单词的开始位置 * end      单词的结束位置 * note:约定于坐标轴的方式表示,如: *         0 -----> x *         | *         | *         |y */typedef struct result{    const char *pword;    point begin;    point end;} result;/** 定义查找方式宏 */#define SEARCH_BEG          1#define LEFT_TO_RIGHT       1#define RIGHT_TO_LEFT       2#define TOP_TO_UPPER        3#define UPPER_TO_TOP        4#define MAIN_DIAGONAL       5#define R_MAIN_DIAGONAL     6#define COUNTER_DIAGONAL    7#define R_COUNTER_DIAGONAL  8#define SEARCH_END          8/** * 将字母c追加到字符串arras后面 * arras    待追加字符串指针 * c        待追加字母 */void append(char *arras, char c){    assert(NULL != arras);    while(*arras)        ++arras;    *arras = c;}/** * 查找函数 * presult_set  查找结果集 */void search(result *presult_set){    int search_way;    char str_temp[20];    int i, j, k;    int index = 0;    int flag = 0;    result temp;    asser(NULL != presult_set);    memset(str_temp, '\0', sizeof(str_temp));    /* 依次从各个方向开始查找 */    for(search_way=1; search_way<=SEARCH_END; ++search_way)    {        switch(search_way)        {        case LEFT_TO_RIGHT:            temp.begin.x = 1;            for(i=0; i<WORD_PUZZLE_TABLE_HIGHT; ++i)            {                temp.begin.y = i + 1;                for(j=0; j<WORD_PUZZLE_TABLE_WIDTH; ++j)                {                    append(str_temp, word_puzzle_table[i][j]);                    for(k=0; k<WORD_TABLE_LEN; ++k)                    {                        if(0 == strcmp(str_temp, word_table[k]))                        {                            temp.pword = word_table[k];                            temp.end.x = j + 1;                            temp.end.y = i + 1;                            presult_set[index] = temp;                            flag = 1;                            ++index;                            break;                        }                    }                    if(flag)                    {                        flag = 0;                        break;                    }                }                memset(str_temp, '\0', sizeof(str_temp));            }            break;        case RIGHT_TO_LEFT:            temp.begin.x = WORD_PUZZLE_TABLE_WIDTH;            for(i=WORD_PUZZLE_TABLE_HIGHT-1; i>=0; --i)            {                temp.begin.y = i + 1;                for(j=WORD_PUZZLE_TABLE_WIDTH-1; j>=0; --j)                {                    append(str_temp, word_puzzle_table[i][j]);                    for(k=0; k<WORD_TABLE_LEN; ++k)                    {                        if(0 == strcmp(str_temp, word_table[k]))                        {                            temp.pword = word_table[k];                            temp.end.x = j + 1;                            temp.end.y = i + 1;                            presult_set[index] = temp;                            flag = 1;                            ++index;                            break;                        }                    }                    if(flag)                    {                        flag = 0;                        break;                    }                }                memset(str_temp, '\0', sizeof(str_temp));            }            break;        case TOP_TO_UPPER:            temp.begin.y = 1;            for(i=0; i<WORD_PUZZLE_TABLE_WIDTH; ++i)            {                temp.begin.x = i + 1;                for(j=0; j<WORD_PUZZLE_TABLE_HIGHT; ++j)                {                    append(str_temp, word_puzzle_table[j][i]);                    for(k=0; k<WORD_TABLE_LEN; ++k)                    {                        if(0 == strcmp(str_temp, word_table[k]))                        {                            temp.pword = word_table[k];                            temp.end.x = i + 1;                            temp.end.y = j + 1;                            presult_set[index] = temp;                            flag = 1;                            ++index;                            break;                        }                    }                    if(flag)                    {                        flag = 0;                        break;                    }                }                memset(str_temp, '\0', sizeof(str_temp));            }            break;        case UPPER_TO_TOP:            temp.begin.y = WORD_PUZZLE_TABLE_HIGHT;            for(i=0; i<WORD_PUZZLE_TABLE_WIDTH; ++i)            {                temp.begin.x = i + 1;                for(j=WORD_PUZZLE_TABLE_HIGHT-1; j>=0; --j)                {                    append(str_temp, word_puzzle_table[j][i]);                    for(k=0; k<WORD_TABLE_LEN; ++k)                    {                        if(0 == strcmp(str_temp, word_table[k]))                        {                            temp.pword = word_table[k];                            temp.end.x = i + 1;                            temp.end.y = j + 1;                            presult_set[index] = temp;                            flag = 1;                            ++index;                            break;                        }                    }                    if(flag)                    {                        flag = 0;                        break;                    }                }                memset(str_temp, '\0', sizeof(str_temp));            }            break;        case MAIN_DIAGONAL:            temp.begin.x = 1;            temp.begin.y = 1;            for(i=0; i<WORD_PUZZLE_TABLE_HIGHT; ++i)            {                for(j=0; j<WORD_PUZZLE_TABLE_WIDTH; ++j)                {                    if(i == j)                    {                        append(str_temp, word_puzzle_table[i][j]);                        for(k=0; k<WORD_TABLE_LEN; ++k)                        {                            if(0 == strcmp(str_temp, word_table[k]))                            {                                temp.pword = word_table[k];                                temp.end.x = i + 1;                                temp.end.y = j + 1;                                presult_set[index] = temp;                                flag = 1;                                ++index;                                break;                            }                        }                    }                    if(flag)                        break;                }                if(flag)                {                    flag = 0;                    break;                }            }            memset(str_temp, '\0', sizeof(str_temp));            break;        case R_MAIN_DIAGONAL:            temp.begin.x = WORD_PUZZLE_TABLE_WIDTH;            temp.begin.y = WORD_PUZZLE_TABLE_HIGHT;            for(i=WORD_PUZZLE_TABLE_HIGHT-1; i>=0; --i)            {                for(j=WORD_PUZZLE_TABLE_WIDTH-1; j>=0; --j)                {                    if(i == j)                    {                        append(str_temp, word_puzzle_table[i][j]);                        for(k=0; k<WORD_TABLE_LEN; ++k)                        {                            if(0 == strcmp(str_temp, word_table[k]))                            {                                temp.pword = word_table[k];                                temp.end.x = i + 1;                                temp.end.y = j + 1;                                presult_set[index] = temp;                                flag = 1;                                ++index;                                break;                            }                        }                    }                    if(flag)                        break;                }                if(flag)                {                    flag = 0;                    break;                }            }            memset(str_temp, '\0', sizeof(str_temp));            break;        case COUNTER_DIAGONAL:            temp.begin.y = WORD_PUZZLE_TABLE_HIGHT;            temp.begin.x = 1;            for(i=WORD_PUZZLE_TABLE_HIGHT-1; i>=0; --i)            {                for(j=0; j<WORD_PUZZLE_TABLE_WIDTH; ++j)                {                    if(i + j == WORD_PUZZLE_TABLE_WIDTH - 1)                    {                        append(str_temp, word_puzzle_table[i][j]);                        for(k=0; k<WORD_TABLE_LEN; ++k)                        {                            if(0 == strcmp(str_temp, word_table[k]))                            {                                temp.pword = word_table[k];                                temp.end.x = j + 1;                                temp.end.y = i + 1;                                presult_set[index] = temp;                                flag = 1;                                ++index;                                break;                            }                        }                    }                    if(flag)                        break;                }                if(flag)                {                    flag = 0;                    break;                }            }            memset(str_temp, '\0', sizeof(str_temp));            break;        case R_COUNTER_DIAGONAL:            temp.begin.y = 1;            temp.begin.x = WORD_PUZZLE_TABLE_WIDTH;            for(i=0; i<WORD_PUZZLE_TABLE_HIGHT; ++i)            {                for(j=WORD_PUZZLE_TABLE_WIDTH-1; j>=0; --j)                {                    if(i + j == WORD_PUZZLE_TABLE_WIDTH - 1)                    {                        append(str_temp, word_puzzle_table[i][j]);                        for(k=0; k<WORD_TABLE_LEN; ++k)                        {                            if(0 == strcmp(str_temp, word_table[k]))                            {                                temp.pword = word_table[k];                                temp.end.x = j + 1;                                temp.end.y = i + 1;                                presult_set[index] = temp;                                flag = 1;                                ++index;                                break;                            }                        }                    }                    if(flag)                        break;                }                if(flag)                {                    flag = 0;                    break;                }            }            memset(str_temp, '\0', sizeof(str_temp));            break;        default:            break;        }        flag = 0;    }}int main(){    result rlt_set[WORD_TABLE_LEN];    int i;    search(rlt_set);    for(i=0; i<WORD_TABLE_LEN; ++i)        printf("%s, (%d, %d)-->(%d, %d)\n", rlt_set[i].pword,               rlt_set[i].begin.x, rlt_set[i].begin.y,               rlt_set[i].end.x, rlt_set[i].end.y);    return 0;}</span>
运行结果:


0 0