只是讨论4行4列情况(书中情况)
原来是将预先写好的单词存在字符串中,但考虑到当单词较多时,可以将单词文本以txt形式存储
使用文件处理操作将文本中内容读入字符串words中,通过字符串函数查找是否存在单词
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
using namespace std;
const char input[4][4] = { {'t','h','i','s'},
{'w','h','t','s'},
{'o','a','a','g'} ,
{'f','g','d','t'} };
//char words[] = " this fat that two ";
char words[1024];
char s1[10], s2[10], s3[10], s4[10];
int a, b, c, d, h,t = 0,res=0;
int pd1[1000],pd2[1000],pd3[1000],pd4[1000];//记录是否选过该字母/避免重复
//计算阶乘
int factorial(int x)
{
int ret = 1;
for (int i = 2; i <= x; i++)
ret *= i;
return ret;
}
//全排列查找
void search(int m, char* s1, int* a)
{
int p = factorial(m), q = 1;
while (!strstr(words, s1) && q <= p)//(计算阶乘,全排列次数是否全列举完)
next_permutation(s1, s1 + m), q++;//进行全排列
char* x = strstr(words, s1);// 该函数返回的是查找到的单词地址
h = x - words;//锁定位置(为避免歧义,文本中每个单词前后均设为空格)
if (x && words[h-1] == ' ' && words[h+m] == ' '){
printf("word %d : %s\n", ++t, s1);
*a = 1;//节省时间,表明在此行/列中已经查找到正确的单词,避免重复查找
res=1;//说明存在正确的单词
}
return;
}
void findtransverse(int k,int m, int trans)//横向 单词数 行数
{
if (k == m&&!a) { search(m, s1, &a); return;}
for (int i = k; i < 4; i++) {
if (!pd1[i]) {//避免重复
pd1[i] = 1;
s1[k] = input[trans][i];
findtransverse(k + 1, m, trans);
pd1[i] = 0; //置为0
}
}
}
void findvertical(int k, int m, int ver)//竖向 //4 0 0
{
if (k == m && !b) { search(m, s2, &b); return; }
for (int i = k; i < 4; i++)
{
if (!pd2[i]) {
pd2[i] = 1;
s2[k] = input[i][ver];
findvertical(k + 1, m, ver);
pd2[i] = 0;
}
}
}
void finddiagonal1(int k,int m)//对角线
{
if (k == m && !c) { search(m, s3, &c); return; }
for (int i = k; i < 4; i++) {
if (!pd3[i]) {
pd3[i] = 1;
s3[k] = input[i][i];
finddiagonal1(k + 1, m);
pd3[i] = 0;
}
}
}
void finddiagonal2(int k,int m)//对角线 3
{
if (k == m && !d) { search(m, s4, &d); return; }
for (int j = k; j < 4; j++){
if (!pd4[j]) {
pd4[j] = 1;
s4[k] = input[3 - j][j];
finddiagonal2(k + 1, m);
pd4[j] = 0;
}
}
}
//重新清理0
void reinit(char* p, int j)
{
for (int i = 0; i < j; i++)
p[i] = 0;
}
int main()
{
FILE* pf = fopen("D:\\作业\\字谜游戏文档存储.txt", "r");
if (pf == NULL)
{
perror("open the file");
return 0;
}
fgets(words, 1024, pf);//将文本内容读入字符串
for (int i = 0; i < 4; i++) //决定横向/竖向查找的行和列
{
a = 0, b = 0, c = 0, d = 0;
for (int j = 4; j >= 1; j--) //决定单词字母数目
{
if (!a) findtransverse(0,j, i), reinit(s1, j);//横向
if (!b) findvertical(0,j, i), reinit(s2, j);//竖向
if (i==0&&!c) finddiagonal1(0,j), reinit(s3, j);//左上-右下(对角线方向的只用找一次)
if (i==0&&!d) finddiagonal2(0,j), reinit(s4, j);//左下-右上(不同于横向竖向与行数/列数相关,只用找一次)
}
}
if (!res) printf( "不存在符合条件的单词");
fclose(pf);
pf = NULL;
return 0;
}