我正面对这个困难的练习,我已经看过其他关于填字游戏的练习(即最后一次练习" p-99:九十九个prolog节目"或者#&# 34;人工智能的Prolog编程" Bratko),但这是不同的,也更难,因为在这里我们没有任何模板可以填写。
文字:
编写Prolog程序以生成填字游戏。假设你有一个这样的事实字典:w(Word,Lentgth)。写一个谓词填字游戏(C,W,H)来实例化C,到字典的字符列表(填字游戏行)的所有可能列表(填字游戏),其中黑色单元格用星号表示。
例如:
w(online,6).
w(prolog,6).
w(perl,5).
w(emacs,5).
w(linux,5).
w(gnu,3).
w(mac,3).
w(nfs,3).
w(sql,3).
w(web,3).
w(xml,3).
w(a,1).
w(b,1).
w(e,1).
w(i,1).
w(l,1).
w(m,1).
w(n,1).
w(o,1).
w(q,1).
w(r,1).
w(s,1).
w(t,1).
w(u,1).
w(w,1).
?- crossword(C,9,6).
C=[[p,r,o,l,o,g,*,*,e],
[e,*,n,*,*,n,*,*,m],
[r,*,l,i,n,u,x,*,a],
[l,*,i,*,f,*,m,a,c],
[*,*,n,*,s,q,l,*,s],
[*,w,e,b,*,*,*,*,*]]
给出提示
1)你可以在字典中添加这些" black"词:
black(*,1).
black(**,2).
black(***,3).
black(****,4).
black(*****,5).
2)每一行都是" white"单词(普通单词)和"黑色"单词交错,这个序列可以用两者开始/结束。
3)我建议你用2个不同的条款管理前一点的2种可能性。
4)填字游戏是一个字符矩阵,因此它的转置仍然是一个填字游戏。
5)转置填字游戏已经实例化,所以你只需要用字典检查它的可行性。
这就是我的想法:为每个列表(行)创建一个H(填字游戏,行的高度)列表(填字游戏的行)列表我尝试从字典中插入单词后跟&# 34;黑色"单词,然后再一个单词,直到行满,或者从"黑色"开始。当填字游戏已满时,我将其转置并检查转置是否也是一个有效的填字游戏:包含的每个单词都是字典中的有效单词。 我知道这是一种非常低效的方法,我尝试使用一个小字典生成填字游戏2x2,它正确地生成第一个第二,但似乎需要多年才能获得第三个。我不知道我的代码是否有问题,可能会卡在某处。您是否知道一种更有效的方法来解决此问题,或者您在我的代码中看到了一些需要改进的地方?
crossword(C,W,H):- create(C,H),
insert_words(C,W,[],_),
clpfd:transpose(C,Traspose),
isok(Traspose).
insert_words([],_,U,U).
insert_words([H|T],W,Uacc,U):-
(add_white(H,[],C,[],Uacc,Udef);
add_black(H,[],C,[],Uacc,Udef)),
insert_words(T,C,Udef,U).
create(Puzzle,H) :- length(Puzzle,H).
add_white(P,P,0,_,U,U).
add_white(P,Row,R,Used,Uacc,Udef):-
R\=0,
w(Word,L),
\+member(Word,Used),
\+member(Word,Uacc),
R2 is R-L,
R2 >= 0,
atom_chars(Word,Word2),
append(Row,Word2,Row2),
append(Used,[Word],Used2),
append(Uacc,[Word],Uacc2),
add_black(P,Row2,R2,Used2,Uacc2,Udef).
add_white(P,Row,R,Used,Uacc,Udef):-
R\=0,
w(Word,L),
\+member(Word,Used),
R2 is R-L,
R2 < 0,
append(Used,[Word],Used2),
add_white(P,Row,R,Used2,Uacc,Udef).
add_white(P,Row,R,Used,Uacc,Udef):-
R\=0,
w(Word,_),
member(Word,Used),
add_white(P,Row,R,Used,Uacc,Udef).
add_black(P,P,0,_,U,U).
add_black(P,Row,R,Used,Uacc,Udef):-
R\=0,
black(Black,L),
R2 is R-L,
R2 >= 0,
atom_chars(Black,Black2),
append(Row,Black2,Row2),
add_white(P,Row2,R2,Used,Uacc,Udef).
add_black(P,Row,R,Used,Uacc,Udef):-
R\=0,
black(_,L),
R2 is R-L,
R2 < 0,
add_black(P,Row,R,Used,Uacc,Udef).
isok([]).
isok([H|T]):-split(H,*,R),
check(R),
isok(T).
split(L,C,R):-split2(L,C,X),trim(X,R).
split2(In, Sep, [Left|Rest]) :-
append(Left, [Sep|Right], In), !, split2(Right, Sep, Rest).
split2(In, _Sep, [In]).
trim([],[]).
trim([H|T],[H|T2]):-H\=[],trim(T,T2).
trim([H|T],Y):-H=[],trim(T,Y).
check([]).
check([H|T]):-
atom_chars(X,H),
w(X,_),
check(T).
我使用这个小字典而不是原始字典来测试我的程序并生成简单的2x2填字游戏,但正如我之前所说的那样,在正确找到2个解决方案后似乎卡住了。
w(ci,2).
w(ca,2).
w(i,1).
w(a,1).
black(*,1).