初步学习prolog语言,感觉上手还是挺容易的,虽然不是很深,但基本的语法结构比较简单,然后看了一些入门资料:
prolog语言,耐心看完你就入门了
链接:http://pan.baidu.com/s/1mijQUrY 密码:3yb5
prolog环境搭建:
链接:http://pan.baidu.com/s/1cj5tGa 密码:7olj
prolog语言教程:
链接:http://pan.baidu.com/s/1c2DTwSK 密码:tpav
然后看到一篇关于prolog解决数独和八皇后问题的文章:先看下这个链接吧
尝试自己写一个八皇后问题prolog程序,当作学习吧
position(). %标记皇后的位置,只能是第一列到第八列中的一个
position().
position().
position().
position().
position().
position().
position().
% if P then Q else R
%if_then_else结构
if_then_else(P,Q,R):- call(P),!,Q.
if_then_else(P,Q,R):- R.
有关于if_then_else结构的prolog知识,可以看if_then_else
list_append(A,B):- append([],[A],B). %将数字A转化为列表B
last_one(A,X):- append(_,[A],X). %A等于表X的最后一个元素
first_part(A,X):- last_one(B,X),append(A,[B],X). %得到A等于表X的除最后一个元素的前部分表
有关append()以及list的相关知识,同样可以看一下
list
append
%在已有棋局X下添加一行,A为满足条件的皇后的列号,B用于递归的参数
%如果X的长度为0,即目前要放的是第一行,则八个位置均可。否则取X最后一个元素,需要A满足不在其同一列以及不在同一对角线上要求,在递归判断前一行,直到第一行。
% if(length(X)==0)
% {
% A = position();
% }
% else
% {
% C=last_one_of(X);
% B++,判断 A是否与C同行,同列,同对角线
% B1 = B
% 如果安全
% 递归safe(X前安全部分,A,B1)
% }
safe(X,A,B):-
if_then_else((length(X,L),L=:=),
(position(A)),
(position(A),last_one(C,X),A=\=C,A=\=C+B,A=\=C- B,B1 is B+,first_part(Y,X),safe(Y,A,B1))).
%求出所有八皇后问题的解。X为现有棋盘,Y为在X基础上添加一行的棋盘,直到添加了8行。每一次先判断在X下可以放的位置有哪些,在将其转化为列表,再将其添加到X后
% queen(X,Y)
% if(length(X)<8)
% {
% safe(X,A,1)
% B=A
% Z=X+B
% queens(Z,Y)
% }
%
% else
% {
% Y = X
% }
queens(X,Y):-
if_then_else((length(X,L),L<),
(safe(X,A,),list_append(A,B),append(X,B,Z),queens(Z,Y)),
(append(X,[],Y))).
入口查询:结果X=[Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8]
eight_queens([(_,Y1),(_,Y2),(_,Y3),(_,Y4),(_,Y5),(_,Y6),(_,Y7),(_,Y8)]):-
queens([],X),
append([],[Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8],X).
其实还是挺简单的啦
运行过程:
consut运行:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICO1EDOxAjMyEDOxATM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
查询:(每次键入冒号得到更多的结果)
完整的程序:
position(). %标记皇后的位置,只能是第一列到第八列中的一个
position().
position().
position().
position().
position().
position().
position().
% if P then Q else R
%if_then_else结构
if_then_else(P,Q,R):- call(P),!,Q.
if_then_else(P,Q,R):- R.
list_append(A,B):- append([],[A],B). %将数字A转化为列表B
last_one(A,X):- append(_,[A],X). %A等于表X的最后一个元素
first_part(A,X):- last_one(B,X),append(A,[B],X). %得到A等于表X的除最后一个元素的前部分表
%在已有棋局X下添加一行,A为满足条件的皇后的列号,B用于递归的参数
%如果X的长度为0,即目前要放的是第一行,则八个位置均可。否则取X最后一个元素,需要A满足不在其同一列以及不在同一对角线上要求,在递归判断前一行,直到第一行。
% if(length(X)==0)
% {
% A = position();
% }
% else
% {
% C=last_one_of(X);
% B++,判断 A是否与C同行,同列,同对角线
% B1 = B
% 如果安全
% 递归safe(X前安全部分,A,B1)
% }
%
safe(X,A,B):-
if_then_else((length(X,L),L=:=),
(position(A)),
(position(A),last_one(C,X),A=\=C,A=\=C+B,A=\=C- B,B1 is B+,first_part(Y,X),safe(Y,A,B1))).
%求出所有八皇后问题的解。X为现有棋盘,Y为在X基础上添加一行的棋盘,直到添加了8行。每一次先判断在X下可以放的位置有哪些,在将其转化为列表,再将其添加到X后
% queen(X,Y)
% if(length(X)<8)
% {
% safe(X,A,1)
% B=A
% Z=X+B
% queens(Z,Y)
% }
%
% else
% {
% Y = X
% }
queens(X,Y):-
if_then_else((length(X,L),L<),
(safe(X,A,),list_append(A,B),append(X,B,Z),queens(Z,Y)),
(append(X,[],Y))).
%X=[Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8]
eight_queens([(_,Y1),(_,Y2),(_,Y3),(_,Y4),(_,Y5),(_,Y6),(_,Y7),(_,Y8)]):-
queens([],X),
append([],[Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8],X).