![]() |
![]() |
![]() |
![]() |
mang :-
Mänguseisu joonistamisel määrab ruudule joonistatava märgi predikaat mark
. Joonistada tuleb
X
, kui ruut on inimese poolt märgistatud ruutude nimistus ja O
, kui arvuti poolt joonistatud ruutude nimistus; kui ruut ei esine kummaski nimistus, jääb ta tühjaks. Algseisu joonistamise ajal aga tuleb igasse ruutu kirjutada ruudu järjekorranumber. Et seda saavutada, lisatakse (primitiivi asserta
abil) algseisu joonistamise ajaks predikaadi mark
kirjelduses esimeseks lause, mis tagab, et ruudu märk on selle ruudu järjekorranumber; niipea kui algseis on joonistatud, vastav lause eemaldatakse LPA-Prologi primitiiviga retract
:
joonista_algseis :-
joonista_seis(Arvuti,Inimene) :-
mark(N,Arvuti,Inimene,'X') :-
mark(N,Arvuti,Inimene,'O') :-
mark(_,_,_,' ').
joonista_rida(N,Arvuti,Inimene) :-
Predikaat
sirge
kirjutab antud arvu märke:
sirge(0,_) :-
sirge(Pikkus,Mark) :-
Nii arvuti kui ka inimese käigu sooritamisel kontrollitakse, kas antud seisus üldse tasub jätkata (leidub veel mõni sirge, millel ei ole mõlema osavõtja märke):
inimese_kaik(Arvuti,Inimene,Vabad) :-
inimese_kaik(Arvuti,Inimene,Vabad) :-
kontrolli_kaik(Arvuti, Inimene, Vabad, Kaik):-
kontrolli_kaik(Arvuti, Inimene, Vabad, _):-
write('See käik ei ole lubatud!') ,
arvuti_kaik(Arvuti,Inimene,Vabad) :-
arvuti_kaik(Arvuti,Inimene,Vabad) :-
arvuti_kaik(Arvuti,Inimene,Vabad) :-
kontrolli_voit(Arvuti, Inimene, Vabad, Kaik):-
kontrolli_voit(Arvuti, Inimene, Vabad, Kaik):-
Mängu ei ole enam mõtet jätkata, kui kumbki ei suuda kõigi veel vabade ruutude täitmisel oma märkidega mängu vöita. Sellepärast lisatakse viigi kontrolliks algul arvuti poolt täidetud ruutudele köik vabad ruudu ja kontrollitakse, et saadud seis ei ole võiduseis, siis korratakse sama inimese poolt täidetud ruutude nimistuga:
kontrolli_viik(Arvuti,Inimene,Vabad) :-
Ruutude nimistu on võiduseis (sellele mängijale, kumma ruudud need on), kui selles esinevad ühe sirge kõik ruudud:
voidab(Ruudud) :-
Ruutude nimistus esinevate sirgete arvu määrab predikaat
sirgeid(Ruudud,Arv) :-
sirgeid
Prologi süsteemipredikaadi
findall
abil; see kogub kõik tingimust
(sirge(S),alamnimistu(S,Ruudud))
täitvad muutuja
S
väärtused nimistuks Sirged
:
Predikaat alamnimistu
kontrollib, et kõik esimeses ruutude nimistus (need on mingi sirge ruudud) esinevad ruudud esinevad ka teises nimistus.
Siin kasutatakse predikaati member(X,Nimistu)
, mis kontrollib, kas element X
esineb nimistus Nimistu
. Kuna see predikaat (nagu ka eespool esinenud predikaat length
) ei ole süsteemipredikaat, vaid on defineeritud moodulis Util.pro
, peab see moodul olema ka laaditud (käsuga : consult('Util.pro').
):
alamnimistu([],Ruudud2) :-!.
alamnimistu([X|Y],Z):-
Arvuti poolt järgmisena täidetava ruudu arvutab predikaat kaik
. Köige enne püüab see leida ruudu, mille täitmisel arvuti kohe vöidaks; kui sellist ei leidu, otsitakse predikaadi käik teises lauses ruutu, mille täitmisel vöiks inimene järgmisel käigul vöita; kui sellist ruutu ka ei leidu, otsitakse vabadest ruutudest parim:
kaik(Arvuti,Inimene,Vabad,Ruut) :-
kaik(Arvuti,Inimene,Vabad,Ruut) :-
kaik(Arvuti,Inimene,Vabad,Ruut) :-
Ruut on parim, kui sellesse ruutu oma märgi tegemine kõige enam tõstab arvuti võiduvõimalusi (selle "parima" ruudu otsimine teebki programmi intelligentseks!). Võiduvõimalused arvutatakse järgmiselt: algul arvutatakse arvuti potentsiaalne sirgete arv antud seisus, s.t. sirgete arv, mille arvuti saab, kui ta täidaks kõik veel vabad ruudud oma märkidega; siis arvutatakse samal viisil inimese potentsiaalsete sirgete arv; arvuti võiduvõimalused saadakse esimesest arvust teise lahutamisel.
parim(Arvuti,Inimene,Vabad,Ruut) :-
ruudu_Punktid(Arvuti,Inimene,Vabad,Ruut,Punktid) :-
korgeim(Ruut,Punktid,[[Ruut,Punktid]]) :-
korgeim(Ruut,Punktid,[[R1,P1]|Ruudud]) :-
leia_max(R1, P1, R2, P2, R1, P1):-
leia_max(R1, P1, R2, P2, R2, P2).
seis(Arvuti,Inimene,Vabad,Punktid) :-
Abipredikaat vahe
leiab nimistu, mis saadakse predikaadi teise argumendina olevast nimistust, kui sellest eemaldada esimese argumendina olev ruut:
vahe(Ruut,[Ruut|Muud],Muud1) :-
vahe(Ruut,[Ruut1|Muud], [Ruut1|Vahe]) :-
vahe(_,[],[]).
Lõpuks tuleb kirjeldada, millised ruudud moodustavad sirgeid:
sirge([1,2,3]).
sirge([4,5,6]).
sirge([7,8,9]).
sirge([1,4,7]).
sirge([2,5,8]).
sirge([3,6,9]).
sirge([1,5,9]).
sirge([3,5,7]).