求解字谜游戏问题

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

图1-1 字谜示例

1234
1 this
2wats
3oahg
4fgdt


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

#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>
运行结果:


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值