Click here to load reader
SVEUĈILIŠTE U ZAGREBU
FAKULTET ORGANIZACIJE I INFORMATIKE
VARAŽDIN
Integracija logiĉkog, objektno orijentiranog programiranja i
skriptnih programskih jezika
Marko Velić
Ivan Padavić
Mentor: Prof. dr. sc. Mirko Čubrilo
Varaţdin, svibanj 2005.
ii
SVEUĈILIŠTE U ZAGREBU
FAKULTET ORGANIZACIJE I INFORMATIKE
VARAŽDIN
Marko Velić, Ivan Padavić
INTEGRACIJA LOGIĈKOG, OBJEKTNO
ORIJENTIRANOG PROGRAMIRANJA I SKRIPTNIH
PROGRAMSKIH JEZIKA
Rad predloţen Fakultetu organizacije i informatike Sveučilišta u Zagrebu
povodom Natječaja za dodjelu Rektorove nagrade
Varaţdin, svibanj 2005.
iii
Ovaj rad izraĎen je na Fakultetu organizacije i informatike Varaţdin, u sklopu
Natječaja za dodjelu Rektorove nagrade, pod vodstvom prof. dr. sc. Mirka Čubrila
iv
Popis slika
2.1.1. PRIMJER STRUKTURE U FORMALNOJ LOGICI .................................................................... 3
2.2.1. KLAUZULA NAPISANA U PROLOGU ......................................................................................... 5
4.3.1. PSHARP.DLL, PROLOG KOD I P# INTERPRETER U ISTOM DIREKTORIJU ..................13
4.3.2.. PREVOĐENJE NAREDBOM COMPILE(). .................................................................................14
4.3.3. POTREBNE DATOTEKE UKLJUĈENE U PROJEKT ..............................................................15
4.3.4. KONAĈNI IZGLED JEDNOSTAVNE WEB APLIKACIJE “RODITELJ_DJED” .................17
4.3.5. DIJAGRAM IZRADE P# APLIKACIJE ........................................................................................17
5.2.1. KONAĈNI IZGLED C# APLIKACIJE ..........................................................................................21
5.2.2. STRUKTURNI PRIKAZ “KRIŽIĆ-KRUŽIĆ” APLIKACIJE ....................................................21
5.3.1. SUĈELJE OSTVARENO U FLASH-U ...........................................................................................24
5.3.2. STRUKTURNI PRIKAZ “KRIŽIĆ-KRUŽIĆ” APLIKACIJE NAKON INTEGRACIJE S
FLASH-OM .................................................................................................................................................25
v
Sadržaj
1. UVOD ........................................................................................................................................................ 1
2. PROLOG ................................................................................................................................................... 2
2.1. LOGIČKO PROGRAMIRANJE .................................................................................................................. 2 2.2. OBILJEŢJA I SINTAKSA PROLOGA ......................................................................................................... 4
3. C# ............................................................................................................................................................... 6
3.1. .NET PLATFORMA ............................................................................................................................... 6 3.2. OBILJEŢJA C# JEZIKA ........................................................................................................................... 8
4. P# ............................................................................................................................................................... 9
4.1. SOURCE-TO-SOURCE PREVOĐENJE ....................................................................................................... 9 4.2. OBILJEŢJA P# ALATA ..........................................................................................................................11 4.3. POSTUPAK IZRADE P# APLIKACIJE – KORAK PO KORAK ......................................................................12
5. PRIMJER IZRADE CJELOVITE P# APLIKACIJE ..........................................................................18
5.1. ODABIR PROBLEMA ............................................................................................................................18 5.2. IZRADA APLIKACIJE ............................................................................................................................19 5.3. PROŠIRENJE OSNOVNE P# APLIKACIJE KORIŠTENJEM FLASH-A, ACTION SCRIPT-A I PERL-A ...............22
5.3.1. Flash grafičko sučelje ................................................................................................................22 5.3.2. Ostvarenje igre putem Interneta ................................................................................................26
6. ZAKLJUĈAK ..........................................................................................................................................28
DODATAK A – IZVORNI C# KOD WEB APLIKACIJE PRIKAZANE U POGLAVLJU 4.3. .........29
A.1. GLAVNA WEB FORMA ........................................................................................................................29 A.2. DATOTEKA DJED_2.CS .......................................................................................................................31 A.3. DATOTEKA RODITELJ_2.CS ................................................................................................................32
DODATAK B – IZVORNI PROLOG KOD IGRE “KRIŽIĆ-KRUŽIĆ” .............................................34
DODATAK C – C# IZVORNI KOD IGRE “KRIŽIĆ-KRUŽIĆ” ..........................................................38
DODATAK D - ACTION SCRIPT IZVORNI KOD GRAFIĈKOG SUĈELJA...................................52
DODATAK E - OSTVARENJE IGRE PUTEM INTERNETA ..............................................................55
E.1. ACTION SCRIPT – KLIJENTSKI DIO ......................................................................................................55 E.2. PERL – SERVERSKI DIO .......................................................................................................................60
LITERATURA ............................................................................................................................................65
vi
TEMELJNA DOKUMENTACIJSKA KARTICA
Sveučilište u Zagrebu
Fakultet organizacije i informatike Varaţdin
INTEGRACIJA LOGIĈKOG, OBJEKTNO ORIJENTIRANOG
PROGRAMIRANJA I SKRIPTNIH PROGRAMSKIH JEZIKA
Marko Velić, Ivan Padavić
U ovom radu prikazane su mogućnost integracije logičkog i objektno orijentiranog
programiranja, te logičkog programiranja i skriptnih programskih jezika. U informatičkoj
industriji danas, objektni pristup izgradnji aplikacija gotovo je postao standard. Objektno
orijentirani operacijski sustavi, aplikacije, programski jezici i razvojna okruţenja nalaze se na
većini današnjih računala. Kada govorimo o rješavanju logičkih problema u programiranju,
prednost ipak ima logičko programiranje, zbog elegancije rješavanja takvih problema. Mnogi
autori danas smatraju da je Prolog vodeći jezik logičkog programiranja. Integraciju ova dva
pristupa programiranju ostvarujemo pomoću alata P#. P# spada u skupinu tzv. “source-to-source”
prevoditelja, a prevodi izvorni kod napisan u Prologu u C# izvorni kod. Na taj način moguće je
iskoristiti prednosti ovih dvaju jezika i snaţni logički mehanizam programa iz Prologa povezati s
naprednim mogućnostima jezika C#, kao što su atraktivna grafička sučelja, dobra podrška za
mreţni rad i Internet (TCP/IP) aplikacije, višedretveni rad i slično. Nakon prikaza logičkog,
objektno orijentiranog programiranja i P# alata te uputa za izgradnju aplikacije korak-po-korak,
dajemo prikaz aplikacije koju smo izgradili pomoću P#-a. Nadalje, izradili smo i jednu inačicu
programa koja koristi Flash grafičko sučelje napisano u skriptnom programskom jeziku Action
Script. Program omogućuje igru više korisnika putem Interneta realizacijom kroz programske
jezike Perl i Action Script. TakoĎer, u dodatku su priloţeni i izvorni programski kodovi razvijene
aplikacije (Prolog, C#, Action Script i Perl).
Ključne riječi: logičko programiranje, objektno orijentirano programiranje, skriptni programski
jezici, Prolog, C#, Action Script, Flash.
Mentor: prof. dr. sc. Mirko Čubrilo, redoviti profesor Fakulteta organizacije i informatike
Sveučilišta u Zagrebu
(73 stranice, 11 slika, 18 navoda literature, jezik izvornika: hrvatski)
vii
BASIC DOCUMENTATION CARD
University of Zagreb
Faculty of Organization and informatics Varaţdin
INTEGRATION OF LOGIC PROGRAMMING, OBJECT ORIENTED
PROGRAMMING AND SCRIPTING PROGRAMMING LANGUAGES
Marko Velić, Ivan Padavić
In this paper we discuss how to integrate logic programming, object oriented
programming and scripting programming languages. Nowadays in software industry, object
oriented approach is de facto standard. Object oriented operation systems, applications,
programming languages and development environments can be found on most of today’s personal
computers. When it comes to solving logic problems, logic programming is often the best
approach, because of the elegant way to solve that kind of problems. Many authors say that
Prolog is the leader among logic programming languages. We implement this interoperation
using P# tool. P# belongs to a group of so called source-to-source translators. P# compiles source
code written in Prolog into C# source code. In this way, it is possible to use advantages of both
languages, and powerful logic mechanisms of Prolog language, integrate with C# advanced
features, such as attractive graphic user interfaces (GUI), network functions and support for
TCP/IP, multithreading etc. After introduction to logic, object oriented programming, P# tool and
step-by-step tutorial, we present an example of application that we developed using P#. Also we
developed one version that uses Flash GUI written with Action Script language. Program is
playable over Internet. This is accomplished by programming in Perl and Action Script. Finally,
in appendix, we included our source code (Prolog, C#, Action Script, Perl).
Kewords: logic programming, object oriented programming, scripting programming languages,
Prolog, C#, Action Script, Flash, Perl.
Supervisor: Mirko Čubrilo, Ph. D., Full Professor, Zagreb University, Faculty of Organization
and Informatics, Varaţdin
(73 pages, 11 figures, 18 references, original in: Croatian)
1
1. Uvod
U programiranju danas glavnu ulogu igraju objektni pristup i objektno orijentirani
programski jezici. Moderni, objektno orijentirani programski jezici kao što su Java, C++,
C# i slični omogućuju brzu i efikasnu izgradnju aplikacija koje su vrlo štedljive u
pogledu memorijskih resursa, procesorske snage i vremena izvoĎenja. TakoĎer moderni
objektno orijentirani jezici kao C# i razvojne okoline kao Microsoft .NET uključuju
bogatu podršku za ostale postojeće tehnologije (XML, baze podataka, mreţni rad i slično)
putem svojih standardnih biblioteka. Nasuprot tome, deklarativni programski jezici za
logičko programiranje, kao što je Prolog, više su orijentirani na problem koji treba riješiti
i kako taj problem riješiti nego na izvoĎenje samog programa. Prolog i logičko
programiranje danas imaju veliku ulogu u izgradnji ekspertnih sustava, aplikacija koje
koriste inteligentno pretraţivanje baza podataka i slično. Integracijom logičkog i objektno
orijentiranog programiranja moguće je iskoristiti prednosti obaju pristupa. Integraciju ova
dva pristupa postiţemo pomoću alata P#. P# je alat koji prevodi izvorni kod Prologa u C#
izvorni kod, tzv. source-to-source prevoĎenje. Detaljniji prikaz Prologa i koncepta
logičkog programiranja dan je u poglavlju 2. Poglavlje 3 prikazuje osnove objektno
orijentiranog pristupa te daje uvid u .NET platformu i C# programski jezik. Poglavlje 4
obraĎuje P# i objašnjava postupak prevoĎenja Prolog koda u C# kod, uz demonstraciju
izrade jednostavne Web aplikacije. Poglavlje 5 detaljno opisuje izradu cijele aplikacije
“Kriţić - kruţić” čija je logika implementirana u Prologu, a grafičko sučelje u C# jeziku.
Pored source-to-source prevoĎenja, integracija različitih tehnologija moguća je
uključivanjem vanjskih programskih modula za komunikaciju meĎu dijelovima aplikacije
koji su realizirani kroz različite jezike. To smo prikazali izradom inačice koja koristi
Flash grafičko sučelje. Flash odnosno Action Script korišteni su i za realizaciju
klijentskog dijela aplikacije namijenjene za igranje putem Interneta. Server koji
omogućuje igru preko Interneta napisan je u Perl programskom jeziku. Konačno dodaci
A, B, C, D i E sadrţe izvorne programske kodove naše aplikacije.
2
2. Prolog
2.1. Logičko programiranje
Pojam logičkog programiranja javlja se 1970-ih godina u radovima R. Kowalskog
i A. Colmerauera. Logičko programiranje predstavlja koncept programiranja koji se
temelji na matematičkoj logici. Programer definira odnose meĎu vrijednostima nekih
podataka te zatim postavlja upite kako bi odredio postojanje tih veza. Drugim riječima
moţemo reći i da se logičko programiranje temelji na činjenicama (premisama) iz kojih
se dobiva zaključak (konkluzija).
Niz pravila i činjenica definiranih u programu predstavlja bazu znanja iz koje se
zatim mogu donositi zaključci. Ovakav pristup programiranju najviše se upotrebljava u
izgradnji sustava temeljenih na znanju, inteligentnom pretraţivanju baza podataka i
dokazivanju matematičkih teorema gdje su se programi napisani logičkim
programiranjem pokazali brzim u donošenju zaključaka na temelju velikog broja
podataka ili činjenica koje treba razmatrati.
Kowalski - eva definicija algoritma u logičkom programiranju glasi: algoritam =
logika + kontrola. Logička komponenta predstavlja “Što se treba učiniti?”, a kontrolna
komponenta odreĎuje “Kako će se učiniti?”.
Dva temeljna pojma s kojima se susrećemo u formalnoj logici su struktura i
teorija. Strukturom nazivamo skup objekata (entiteta) zajedno sa skupom odnosa
(relacija) meĎu njima. Teorijom nazivamo skup izjavnih rečenica (iskaza) izraţenih
nekim danim jezikom. Struktura je dio svijeta koji teorijom nastojimo opisati. S druge
strane, teorijom se iskazuju neka znanja o svijetu na koji se ona odnosi. (Mario Radovan,
Programiranje u Prologu, Informator, Zagreb, 1987.)
Strukturu bismo mogli prikazati grafom, a tu strukturu opisati teorijom u obliku
rečenica. Primjer teorije su tvrdnje da je osoba “Marko” otac osobe “Ivan” i da je osoba
“Ivan” otac osobe “Stjepan”. Grafički bi struktura izgledala kako je prikazano na slici
2.1.1.
3
Slika 2.1.1. Primjer strukture u formalnoj logici
Ovu strukturu mogli bismo opisati teorijom pomoću rečenica:
otac(marko, ivan).
otac(ivan, stjepan).
djed(marko, stjepan).
* Stjepan
* Ivan
otac
* Marko
otac
djed
4
2.2. Obilježja i sintaksa Prologa
Jedan od najpopularnijih programskih jezika za logičko programiranje je Prolog
koji spada u skupinu tzv. deklarativnih jezika (vidi tablicu 1). Prva implementacija ovog
programskog jezika nastala je 1973. godine, a izradila ju je grupa A. Colmerauera. Prolog
je korišten za pisanje širokog spektra aplikativnih i sistemskih programa, poput
ekspertnih sustava, programa za procesiranje prirodnog jezika, prevodioca, ureĎivača
teksta i niza drugih specifičnih programa.
Naredbeni jezici Deklarativni jezici
Filozofija Korisnik točno opisuje kako
će se problem riješiti
Korisnik opisuje što je
problem
Program Niz naredbi Niz tvrdnji
Primjer Pascal, C, Java, C# Prolog, ML, Scheme, Gödel
Prednosti Brzi i specijalizirani
programi
Općeniti programi, lakše
rješavanje logičkih
problema
Tablica 2.2.1. Usporedba naredbenih i deklarativnih programskih jezika
Osnovnu komponentu u logičkom programu predstavlja predikat. Predikati se
izvršavaju uspješno ili neuspješno tj. ne vraćaju neku odreĎenu vrijednost. Prema tome u
Prologu ne postoje funkcije već atomi, termovi, predikati i klauzule.
5
Hrvatski Logiĉka oznaka Prolog
i ,
ili ;
samo ako ← :-
ne \+
Tablica 2.2.2. Osnovna sintaksa Prologa
Slika 2.2.1. Klauzula napisana u Prologu
Primjer klauzule prikazan je u slici 2.2.1. Ovakva klauzula naziva se Hornova
klauzula i sastoji se od zaključka, operatora “:-” i pretpostavki. Hornove klauzule često su
temelj logike programa napisanog u Prologu. Svaka naredba tj. tvrdnja u Prologu
završava znakom “.”. Konkretno, primjer:
brat(X,Y) :− roditelj(Z,X) , roditelj(Z,Y).
tumačimo ovako:
X je brat od Y ako je Z roditelj od X-a i ako je Z roditelj od Y-a za neki Z.
Prolog u svojoj osnovi ne poznaje tipove podataka, iako su se pojavile i neke
proširene implementacije Prologa koje omogućuju tipove podataka znak (character) i
cijeli broj (integer).
predikat(x1, ..., xn) :- p1(x1, ..., xn), ..., pn(x1, ..., xm).
Glava klauzule
(zaključak)
Vrat klauzule
(kopula)
Tijelo klauzule
(pretpostavke)
6
3. C#
3.1. .NET Platforma
C# je moderan objektno orijentirani programski jezik visokih performansi koji je
nastao u okviru Microsoftove .NET platforme. .NET platforma sastoji se od brojnih
tehnologija uključujući razvojna okruţenja, operacijske sustave i programske jezike. Ova
platforma uključuje napredne koncepte kao što su Garbage Collection, GAC (Global
Assembly Cache) i JIT'ing (Just In Time debugging). .NET programi prevode se u
svojevrsni meĎu-jezik (MSIL – Microsoft Intermediate Language) bez obzira koji se
.NET jezik koristi za programiranje što omogućava da više programera koji rade s
različitim jezicima, primjerice C# i VB.NET, rade na istom projektu bez prebacivanja na
jezik onog drugog. Ekvivalent MSIL-u kod Java programskog jezika je JVML (Java
Virtual Machine Language) poznat i pod nazivom Java byte-code.
Garbage Collection ili u doslovnom prijevodu “Sakupljanje smeća” označava
funkciju prevoditelja koja u programskom kodu prepoznaje objekte koji se više ne koriste
i automatski oslobaĎa memoriju, tako da programer više ne mora razmišljati o
eksplicitnom oslobaĎanju zauzetih resursa (primjerice delete naredba u C++ jeziku).
GAC ili Global Assembly Cache predstavlja dio datotečnog sustava .NET
platforme koji sluţi za pohranu dijeljenih programskih komponenti i modula. Na taj način
izbjegnuta je konfuzija koja je obično nastajala ako programer koristi puno DLL
pomoćnih datoteka za svoj program. Ova pojava znana je i pod nazivom “DLL Hell” ili
“DLL Pakao”, a temeljni problem javljao se onda kada bi različiti programeri nazivali
svoje DLL datoteke istim imenima pa bi se instalacijom jednog programa prebrisale
datoteke potrebne za rad nekog ranije instaliranog programa.
JIT'ing (Just In Time debugging) ili u slobodnom prijevodu pravovremeno
prevoĎenje koda predstavlja koncept koji omogućava prevoĎenje koda u strojni jezik
prilikom izvoĎenja aplikacije, tako da se izvršavaju samo potrebni dijelovi koda što
rezultira veoma brzim izvoĎenjem aplikacije, a dijelovi koda koji se pokreću ponovno
7
nakon što su već jednom bili izvršeni ne prevode se ponovno u strojni jezik već se izvode
direktno. Samim time .NET aplikacije, kako se koriste, postaju sve brţe.
.NET platforma sadrţi i napredne koncepte za sigurnost napisanih aplikacija i
podataka koje koriste. Primjer su “meta-data” C# klase i “isolated storage” koncept. Ove
karakteristike .NET-a ograničavaju modificiranje podataka izvan okvira koje je zadao
programer. Sigurnost je poboljšana kod Web aplikacija i kod Windows aplikacija.
8
3.2. Obilježja C# jezika
Otprilike svakih deset godina javlja se novi pristup programiranju. Ranih 1980-ih
pojavio se operacijski sustav Unix i programski jezik C koji je razvila tvrtka AT&T.
Početkom 1990-ih pojavio se operacijski sustav Windows i programski jezik C++. Danas
novi pristup predstavljaju .Net platforma i jezik C#. Platforma uključuje više
programskih jezika, ali C# predstavlja njen temeljni jezik. Korištenje ovog jezika
omogućuje iskorištenje svih naprednih koncepata koje pruţa objektna paradigma kao što
su: nasljeĎivanje, enkapsulacija, polimorfizam i slično. U okviru .NET platforme C# se
koristi i kao jezik za programiranje Internet aplikacija (ASP.NET).
Moţemo reći da je C# jezik naučio mnogo od svojih prethodnika tijekom protekla
tri desetljeća. U njemu već na prvi pogled prepoznajemo utjecaj programskih jezika kao
što su Java, C++, Visual Basic. Mnogi autori ističu kako je C# naslijedio eleganciju Jave
i brzinu jezika C++. C# je od Visual Basic-a naslijedio tzv. RAPID razvijanje aplikacija
koje podrazumijeva veoma brzu izradu aplikacija i jednostavno oblikovanje korisničkog
sučelja. TakoĎer C# ima dobru podršku za danas sve popularniji XML (eXtensible
Markup Language), jezik za opisivanje strukturiranih podataka. XML i C# u kombinaciji
predstavljaju vrlo dobar izbor za izradu Web aplikacija kojima je vaţno upravljanje
podacima. Takav pristup omogućava izradu dinamičkih Web stranica i predstavlja
svojevrsnu alternativu bazama podataka korištenim na Webu.
Jezik je relativno jednostavan s otprilike 80-ak ključnih riječi i podrţanim svim
standardnim tipovima podataka. Još jedna novost je i uvoĎenje foreach naredbe koja do
sada nije postojala u obitelji C jezika, a uvedena je iz Visual Basic-a. Ova naredba veoma
je korisna i cijenjena meĎu programerima jer omogućava elegantno izvršavanje naredbi
nad svim elementima polja ili bilo koje druge kolekcije podataka.
C# takoĎer podrţava i direktno pristupanje memorijskim lokacijama pomoću
pokazivača u stilu C++ jezika. Pri tom programer označava takve operacije kao unsafe i
upozorava Garbage Collection da ne oslobaĎa te lokacije dok nisu dereferencirane. To
omogućava programiranje na nešto niţoj razini.
9
4. P#
4.1. Source-to-source prevođenje
Raznolikost programskih jezika, platformi i pristupa programiranju omogućava
mnogo načina rješavanja nekog problema. Ipak ponekad se javlja potreba za integracijom
različitih pristupa i tehnologija. Mogući način integracije različitih tehnologija je
uključivanje novih programskih biblioteka ili modula (plug-in) koji omogućavaju
komunikaciju meĎu programskim komponentama napisanim u različitim programskim
jezicima. Takva sučelja nazivaju se “foreign language interfaces”. Korištenje takvih
vanjskih sučelja često rezultira nepreglednim kodom koji je kasnije teţak za ispravljanje i
mijenjanje.
Drugi način je tzv. “source-to-source” prevoĎenje, a odnosi se na prevoĎenje
izvornog programskog koda napisanog u jednom programskom jeziku u programski kod
napisan u nekom drugom programskom jeziku. Obzirom da smo odabrali Prolog i C# kao
predstavnike područja iz kojih dolaze, a zbog njihovih prednosti opisanih ranije, u ovom
radu odlučili smo integraciju logičkog i objektno orijentiranog programiranja ostvariti
alatom P#. Naime, uz sve nabrojane prednosti i napredne koncepte, .NET i C# nemaju
podršku za čisto logičko programiranje.
Tablica 4.1.1. Primjeri “source-to-source” prevoditelja
Prevoditelj Polazni kod Ciljni kod
Jython Phython JVML
GNU Prolog Prolog C
Prolog Café Prolog Java
P# Prolog C#
10
U narednom poglavlju prikazat ćemo cjelovit primjer P# aplikacije koju smo
izradili. Osim “source-to-source” prevoĎenja, u jednom od naših primjera prikazali smo i
drugu mogućnost integracije različitih tehnologija koja se temelji na korištenju vanjskih
sučelja izradom druge verzije programa, koja predstavlja svojevrsno proširenje prve
verzije, te uz P# koristi “Flash” grafičko sučelje, napisano u Action Script skriptnom
programskom jeziku te mogućnost igre preko Interneta putem Action Script i Perl
skriptnih jezika.
11
4.2. Obilježja P# alata
Prednosti Prologa i C#-a navedene u poglavljima 2 i 3, mogu se iskoristiti
integracijom obaju jezika, a to postiţemo pomoću alata P#. Alat P# razvijen je na
Sveučilištu u Edinburghu pod vodstvom Johnatana J. Cook-a. P# spada u skupinu tzv.
“source-to-source” prevoditelja tj. programa koji izvorni programski kod napisan u
jednom programskom jeziku prevode u izvorni programski kod nekog drugog jezika.
Kako se iz samog imena moţe naslutiti, P# integrira Prolog i C#. P# prevoditelj baziran
je na Prolog Cafe - u, ranije razvijenom prevoditelju Prolog koda u Java izvorni kod. P#
radi na taj način da klauzule napisane u prologu izdvaja u posebne datoteke s ekstenzijom
.cs (ekstenzija datoteka napisanih u jeziku C#). Temeljna komponenta P#-a je Psharp.dll
datoteka koja se moţe uključiti u GAC, a dovoljno je i da se nalazi u istom direktoriju
kao i prevoditelj (interpreter), da bi prevoĎenje bilo uspješno. Nakon prevoĎenja .pl
(.pro) datoteke (.pl i .pro su ekstenzije datoteka napisanih u Prologu, treba obratiti paţnju
na .pl ekstenziju koja je ujedno i ekstenzija datoteka Perl programskog jezika) u niz C#
datoteka, programer te datoteke moţe uključiti u svoj projekt unutar razvojne okoline te
nakon uključivanja Psharp.dll datoteke (ukoliko nije uključena u GAC) moţe slobodno
pozivati funkcije iz .cs datoteka te na taj način koristiti predikate i činjenice definirane u
Prologu. Detaljan opis ovog postupka slijedi uz jednostavan primjer.
12
4.3. Postupak izrade P# aplikacije – korak po korak
Za potrebe demonstriranja postupka prevoĎenja Prologa u C# ovdje ćemo
prikazati jednostavan primjer Internet aplikacije. Za početak, napisali smo jednostavan
program u Prologu koji glasi ovako:
djed(X,Z) :- roditelj(X,Y), roditelj(Y,Z).
roditelj(marko, ivan).
roditelj(ivan, stjepan).
U programskom kodu imamo klauzulu koja opisuje tipičan problem tranzitivnosti.
U klauzuli tvrdimo sljedeće: osoba X je djed osobe Y ako i samo ako je osoba X roditelj
osobe Y i ako je osoba Y roditelj osobe Z. Nadalje u kodu imamo dvije činjenice koje
govore da je osoba “marko” roditelj osobe “ivan”, a osoba “ivan” roditelj osobe
“stjepan”. Mogli bismo reći da u ovom jednostavnom primjeru početna klauzula
predstavlja naš mehanizam zaključivanja, a činjenice jednostavnu bazu znanja. Dakle ako
bismo ovom programu postavili pitanje tko je roditelj osobe “stjepan”, odgovor bi trebao
biti “ivan”, što proizlazi iz druge činjenice, a ukoliko bismo ga pitali tko je djed osobe
“stjepan”, na temelju obaju činjenica i naše klauzule, odgovor bi trebao biti “marko”.
Slijedi opis postupka izgradnje Web aplikacije na temelju ovog Prolog programa.
Na početku, potrebno je datoteku s programskim kodom koji ţelimo prevesti, staviti u isti
direktorij sa P# interpreterom i Psharp.dll datotekom (ukoliko ona nije u GAC-u) što je i
prikazano na slici 4.3.1.
13
Slika 4.3.1. Psharp.dll, Prolog kod i P# interpreter u istom direktoriju
Zatim je potrebno pokrenuti interpreter i naredbom compile(). prevesti ţeljeni kod
u C#. Unutar zagrada navodimo ime datoteke. Rezultat će biti dvije C# datoteke u istom
direktoriju. Nazivi datoteka odgovaraju nazivima klauzule i činjenica. Datoteka
Djed_2.cs sadrţi logiku klauzule, a datoteka Roditelj_2 sadrţi podatke o roditeljima.
Postupak je prikazan na slici 4.3.2.
14
Slika 4.3.2.. Prevođenje naredbom compile().
Sljedeći korak je uključivanje datoteka u projekt unutar razvojne okoline, što je
prikazano na slici 4.3.3. Opet, ukoliko Psharp.dll nije unutar GAC-a, potrebno ga je
referencirati unutar projekta. Sada programer u svojoj glavnoj formi moţe pozivati
dodane C# datoteke.
Za pozivanje funkcija iz datoteka potrebno je definirati novo sučelje naredbama:
PrologInterface sharp = new PrologInterface( );
sharp.AddAssembly (System.Reflection.Assembly.GetExecutingAssembly());
Potrebno je stvoriti novi term koji će biti simbol (atom) naredbom:
SymbolTerm s1 = SymbolTerm.MakeSymbol( TextBox1.Text );
Poziv predikata ostvarujemo sljedećim naredbama:
sharp.SetPredicate( new Djed_2(netko, s1,new ReturnCs( sharp ) ) );
sharp.Call();
15
Slika 4.3.3. Potrebne datoteke uključene u projekt
Slijedi popis P# funkcija za stvaranje novih termova u drugim tipovima podataka.
Za cijele brojeve: IntegerTerm i = new IntegerTerm( 3 );
Za decimalne brojeve: DoubleTerm d = new DoubleTerm( 2.5 );
Za stvaranje C# objekta kao npr. StringBuilder, koristimo: CsObjectTerm o = new CsObjectTerm( new StringBuilder( ) );
Za stvaranje varijable: VariableTerm v = new VariableTerm( );
Ako P# Prolog kod instancira varijablu v, nakon što je učinjen poziv Prologa, v moţe biti
dereferencirana kako bi se pribavila vrijednost iz Prologa, primjerice: IntegerTerm it = (IntegerTerm)( v.Dereference() );
Ako ţelimo stvoriti jednostavnu listu [1,x,2], moţemo koristiti kod: ListTerm empty = SymbolTerm.MakeSymbol( "[]" );
ListTerm item1 = new IntegerTerm( 1 );
ListTerm item2 = SymbolTerm.MakeSymbol( "x" );
16
ListTerm item3 = new IntegerTerm( 2 );
ListTerm list = new ListTerm( item1,
new ListTerm( item2,
new ListTerm( item3, empty )
)
);
ako ţelimo definirati strukturu podataka dob ('Josip',25), programski kod bi bio:
Term[] args = { SymbolTerm.MakeSymbol( "Josip" ),
new IntegerTerm( 25 ) };
StructureTerm st = new StructureTerm(
SymbolTerm.MakeSymbol( "dob", 2 ), // ( ime strukture, broj
članova strukture )
args );
C# programski kod glavne forme koja poziva generirane C# datoteke nalazi se u
dodatku A. Pritiskom na tipku “Tko je djed?” pozivamo Prolog predikat stvarajući novi
term koji je simbol, a prima vrijednost polja u koje se unosi ime osobe. Predikat to ima
prima kao parametar i vraća ime osobe koja je traţeni djed. Sličan je postupak i za tipku
“Tko je roditelj?”. Konačni izgled aplikacije prikazan je na slici 4.3.4.
17
Slika 4.3.4. Konačni izgled jednostavne Web aplikacije “Roditelj_djed”
Ovaj primjer veoma je jednostavan ali reprezentativan u pogledu postupka
izgradnje P# aplikacije. Za potrebe ovog rada izgradili smo primjer cjelovite, sloţenije
aplikacije, a njen detaljan prikaz dan je u sljedećem poglavlju.
Slika 4.3.5. Dijagram izrade P# aplikacije
Prolog
izvorni kod
P#
prevoditelj C# izvorni
kod C#
prevoditelj Izvršna
datoteka
18
5. Primjer izrade cjelovite P# aplikacije
5.1. Odabir problema
Prilikom odabira problema koji smo ţeljeli riješiti, a kako bismo prikazali moć
P#-a i općenito integracije logičkog i objektnog programiranja, vaţno je bilo da primjer
bude relativno jednostavan, a da uključuje sve bitne mogućnosti P# alata. Na temelju
ovih pretpostavki zaključili smo da bi bilo najučinkovitije izraditi primjer jednostavne
logičke igrice čiji bismo kod napisan u Prologu, a zaduţen za logiku igre, pomoću P#-a
integrirali s C#-om i ostvarili aplikaciju koja će imati C# grafičko sučelje. Implementirali
smo jednostavnu logičku igricu “Kriţić-kruţić” koja ima ploču formata 4*4. Pravila igre
nalaţu da se igrači izmjenjuju nakon svakog poteza i pobjednik je onaj igrač koji prvi
sloţi četiri simbola vodoravno, okomito ili dijagonalno na ploči. Obično, ako su oba
igrača paţljiva, igra završava bez pobjednika sa svim popunjenim poljima. Igra je
izvedena kao program koji će se pokretati na lokalnom računalu korisnika.
19
5.2. Izrada aplikacije
Logika igre napisana je u Prologu i temelji se na tri osnovna pravila koje računalo
razmatra prije nego odigra potez. Prvo pravilo računalu nalaţe da, ukoliko postoji
mogućnost da korisnik pobjedi tj. da mu nedostaje još jedan simbol u nizu, blokira tu
mogućnost postavljanjem svog simbola na to polje. Drugo pravilo nalaţe računalu da
odigra pobjednički potez, ako je moguć, tj. ako računalo ima tri simbola u nizu negdje na
ploči. Treće pravilo izvršava se ako ne postoje uvjeti za prva dva pravila, a pomoću njega
se računa najbolji potez koji bi u budućnosti mogao stvoriti izglednu situaciju za pobjedu.
Grafičko sučelje ostvareno je u C#-u na način da šesnaest gumbića predstavlja ploču na
kojoj se igra. Kruţići i kriţići ispisuju se na gumbićima, nakon što igrač odigra neki
potez. Pritisak na gumbić poziva C# funkciju koja pozadini aplikacije (koja je prevedena
iz Prologa) šalje trenutno stanje ploče. Ako korisnik igra protiv računala, logika iz
Prologa na temelju spomenutih pravila odreĎuje sljedeći potez. To je izvedeno
pozivanjem Prolog predikata iza C#-a. Trenutno stanje ploče predstavlja parametar za
predikat na temelju kojeg slijedi zaključivanje.
Nakon što je program napisan u Prologu preveden u C# postupkom opisanim u
poglavlju 4.3. komunikacija grafičkog sučelja i Prologa ostvarena je funkcijama u
glavnoj formi programa. Slijedi kratak prikaz nekih vaţnijih funkcija, a u dodatku je
priloţen i cijeli programski kod.
Funkcija za korisnikov potez:
private void korisnik(int broj)
{
PrologInterface sharp = new PrologInterface( );
Term a1 = new IntegerTerm( broj );
Term a2 = new VariableTerm( );
Predicate humanMove = new PlayInGivenPlace_4( currentPlayer,
currentBoard,a2, a1, new ReturnCs( sharp ) );
sharp.SetPredicate( humanMove );
sharp.Call( );
Term result = a2.Dereference();
if ( !result.IsList() || ((ListTerm)result).Length() != 16 )
{
labela.Text="invalid";
return;
}
currentBoard = a2.Dereference();
Term elm;
20
elm = ((ListTerm)result).cdr.Dereference();
SwapPlayer();
DrawBoard( (ListTerm)currentBoard );
CheckForWinningLine();
}
Funkcija za potez računala:
private void ComputerMove( )
{
PrologInterface sharp = new PrologInterface( );
Term a3 = new VariableTerm( );
Predicate compMove = new Rule_3( currentPlayer, currentBoard,
a3, new ReturnCs( sharp ) );
sharp.SetPredicate( compMove );
sharp.Call( );
Term result = a3.Dereference();
if ( !result.IsList() || ((ListTerm)result).Length() != 16 )
{
return;
}
currentBoard = a3.Dereference();
SwapPlayer( );
Term elm2;
elm2 = ((ListTerm)result).cdr.Dereference();
DrawBoard( (ListTerm)currentBoard );
CheckForWinningLine( );
}
Funkcija za provjeru pobjede:
private void CheckForWinningLine( )
{
PrologInterface sharp = new PrologInterface( );
Term a2 = new VariableTerm( );
Predicate win = new WinningLine_2( currentBoard, a2,
new ReturnCs( sharp ) );
sharp.SetPredicate( win );
sharp.Call( );
Term result = a2.Dereference();
if ( !result.IsList() || ((ListTerm)result).Length() != 16 )
{
return;
}
DrawWin( (ListTerm)result );
}
Funkcija za osvjeţavanje ploče:
private void resetiraj()
{
VariableTerm ispis = new VariableTerm();
PrologInterface sharp = new PrologInterface( );
sharp.AddAssembly
(System.Reflection.Assembly.GetExecutingAssembly());
Term a1 = new VariableTerm( );
Predicate reset = new Blank_1( a1, new ReturnCs( sharp ) );
sharp.SetPredicate( reset );
sharp.Call( );
Term result = a1.Dereference();
if ( !result.IsList() || ((ListTerm)result).Length() != 16 )
21
{
labela.Text = "Invalid result!";
return;
}
Term elm;
elm = ((ListTerm)result).cdr.Dereference();
currentBoard = result.Dereference();
DrawBoard( (ListTerm)currentBoard );
for (int i = 0; i < 16; i++)
{
if (Cellovi[i].Text != "")
{
Cellovi[ i ].Text = "";
}
}
}
Slika 5.2.1. Konačni izgled C# aplikacije
Slika 5.2.2. Strukturni prikaz “Križić-kružić” aplikacije
Prolog Logička
komponenta
Korisničko sučelje C#
P#
22
5.3. Proširenje osnovne P# aplikacije korištenjem Flash-a, Action
Script-a i Perl-a
5.3.1. Flash grafičko sučelje
Osnovna zamisao ovoga dijela rada bila je demonstracija drugog načina
povezivanja različitih tehnologija, a to je uključivanje programskih modula koji
omogućavaju razmjenu informacija meĎu različitim programskim jezicima. Izradili smo
primjer koji povrh P# aplikacije koristi i Flash za još atraktivniji prikaz grafičkog sučelja.
Danas je čest slučaj da se programi napisani u objektnim jezicima kao C# ili C++
povezuju s Flash komponentama baš iz ovog razloga. Time je omogućeno integriranje
multimedijalnih rješenja s logikom iz Prologa, dodavanje animacija, zvučnih efekata i
slično. Općenito o Flash-u moţemo reći da donosi moćan sustav za izradu multimedijskih
sadrţaja. Uz Flash koristi se programski jezik Action Script koji omogućava manipulaciju
multimedijskim sadrţajem i programiranje kompleksnih interaktivnih sustava. Flash i
Action Script prvenstveno su namijenjeni za Web, ali kao što vidimo moguća je i izrada
sloţenih Windows aplikacija, bilo samo kroz Flash ili integracijom s drugim
tehnologijama kao što je to ovdje slučaj. Programski moduli koji omogućuju pozivanje
Flash-a iz C#-a su sljedeći: AxShockwaveFlashObjects.dll i ShockwaveFlashObjects.dll.
Deklaracija i funkcije koje se pozivaju unutar koda i omogućuju interakciju C#
programa i Flash sučelja su sljedeće:
private AxShockwaveFlashObjects.AxShockwaveFlash axShockwaveFlash1;
this.axShockwaveFlash1 = new AxShockwaveFlashObjects.AxShockwaveFlash();
((System.ComponentModel.ISupportInitialize)(this.axShockwaveFlash1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.axShockwaveFlash1)).EndInit();
this.axShockwaveFlash1.Enabled = true;
this.axShockwaveFlash1.Location = new System.Drawing.Point(0, 0);
this.axShockwaveFlash1.Name = "axShockwaveFlash1";
this.axShockwaveFlash1.OcxState =
((System.Windows.Forms.AxHost.State)(resources.GetObject("axShockwaveFlash1.OcxState")));
this.axShockwaveFlash1.Size = new System.Drawing.Size(800, 600);
this.axShockwaveFlash1.TabIndex = 24;
this.Controls.Add(this.axShockwaveFlash1);
private void Form1_Load(object sender, System.EventArgs e)
{
Form1 ova_forma = new Form1();
23
bool neistina = false;
this.Show();
Pocetak forma = new Pocetak();
forma.ShowDialog();
forma.Activate();
Cellovi = new Button[] {Cells1, Cells2, Cells3, Cells4, Cells5,
Cells6, Cells7, Cells8,
Cells9, Cells10, Cells11, Cells12, Cells13, Cells14, Cells15, Cells16 };
resetiraj();
}
private void axShockwaveFlash1_FSCommand(object sender,
AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent e)
{
int proba;
if (e.command == "flashMessage")
{
this.richTextBox1.AppendText(e.args + "\n");
proba = Convert.ToInt32(e.args);
korisnik(proba);
}
if (e.command == "resetiraj")
{
resetiraj();
}
}
private string posalji_pobjedu (string ploca)
{ richTextBox1.Text+=ploca;
string posalji = "";
int brojac = 0;;
for (int i = 1; i<=31; i=i+2)
{ brojac++;
if (ploca[i].ToString() != "," &&
ploca[i].ToString() != "b" && ploca[i].ToString() != "[" && ploca[i].ToString() != "]")
posalji +=brojac.ToString()+"|";
}
this.axShockwaveFlash1.SetVariable("pobjeda", posalji);
richTextBox1.Text += posalji;
richTextBox1.Text += currentPlayer.ToString();
return "s";
}
private void ComputerMove( )
{
if (mod_igre.Equals(1))
{
PrologInterface sharp = new PrologInterface( );
Term a3 = new VariableTerm( );
Predicate compMove = new Rule_3( currentPlayer,
currentBoard,
a3, new ReturnCs( sharp ) );
sharp.SetPredicate( compMove );
sharp.Call( );
Term result = a3.Dereference();
if ( !result.IsList() || ((ListTerm)result).Length() != 16
)
{
return;
24
}
this.axShockwaveFlash1.SetVariable("varijabla",
parsiraj(currentBoard.ToString(),a3.Dereference().ToString()).ToString());
currentBoard = a3.Dereference();
labela.Text = a3.Dereference().ToString();
Term elm2;
elm2 = ((ListTerm)result).cdr;
DrawBoard( (ListTerm)currentBoard );
CheckForWinningLine( );
SwapPlayer();
}
}
Cjeloviti izvorni kod priloţen je u dodatku zajedno s Action Script kodom koji se
odvija iza grafičkog sučelja.
Slika 5.3.1. Sučelje ostvareno u Flash-u
25
Slika 5.3.2. Strukturni prikaz “Križić-kružić” aplikacije nakon integracije s Flash-om
Prolog Logička
komponenta
Korisničko sučelje C#
P#
Flash
26
5.3.2. Ostvarenje igre putem Interneta
U današnjoj softverskoj industriji sve je tanja linija koja odjeljuje “desktop” od
Internet aplikacija. Čest je slučaj da klijent traţi aplikaciju koja će u sebi imati integrirane
obje mogućnosti, bilo za poslovne ili neke druge namjene. Kada govorimo o Internet
aplikacijama najznačajnija i danas najčešće korištena je klijent-server arhitektura.
Općenito klijent server arhitektura je mreţna arhitektura u kojoj postoje dvije
vrste računala odnosno aplikacija. Server ili posluţitelj svoje usluge nudi ostalim
entitetima koji sudjeluju u komunikaciji bilo da su oni drugi serveri ili klijenti. Klijent
predstavlja entitet koji koristi usluge servera. U današnjim sustavima se te uloge često
izmjenjuju. Klijent-server arhitektura se razvila kao odgovor na krutu arhitekturu
terminala i main-frame računala kao i na ubrzani razvitak karakteristika osobnih računala.
Klijent-server arhitekturu koristili smo i u našem primjeru. Klijent je ostvaren
pomoću jezika Action Script, a posluţitelj je ostvaren u skriptnom programskom jeziku
Perl. Komunikacija izmeĎu klijenta i servera ostvarena je priključnicom (socket-om).
Server otvara priključnicu i čeka konekciju klijenta. Priključnica je ostvarena parom host-
port, gdje host odreĎuje računalo, a port priključnu točku. Isječak koda koji ostvaruje
priključnicu je:
# $lsn - socket prikljucnica servera postavljena na slusanje
$lsn = new IO::Socket::INET(Listen => 1,LocalPort => 7777, Reuse
=> 1, Proto => 'tcp' ) or die ("Nisam se uspio pokrenuti: $!");
$lsn->blocking(0);
$lsn->autoflush(1);
warn "Server je podignut...\n";
Klijentska strana ostvarena je u Action Script jeziku, a na zadanu priključnicu povezuje
se sljedećom funkcijom:
function spoji(){
socket = new XMLSocket();// Stvara se novi XMLSocket objekt
socket.connect(host,port);// Konekcija na server
Sada kad je veza uspostavljena, mogu se razmjenjivati poruke. Slijedi primjer.
27
Klijentska strana:
function trazi_listu(){
var zalistu = "303" //303 kod trazenje liste
saljem = new XML(zalistu);
socket.send(saljem);
}
Ovom funkcijom klijent od servera traţi listu trenutno spojenih korisnika.
Serverska strana:
sub saljilistu {
my $nw, $key, $val;
my $count = 0;
my $msg = "503 ";
while (($key, $val) = each %users){
if ($count == 0) {
$msg .= $val->{UNAME};
} else {
$msg .= "|" . $val->{UNAME};
}
$count++;
} #while
$msg .= $terminator;
$nw = syswrite($users{$client}->{SOCKREF}, $msg, length($msg));
warn "Poslana lista korisniku: " . $users{$client}->{UNAME} . "
($nw bytes)\n";
}
Server na zahtjev klijenta vraća zatraţenu listu trenutno spojenih korisnika.
Cijela aplikacija ostvarena je nizom takvih komunikacija izmeĎu klijenta i servera,
cjeloviti programski kod priloţen je u dodatku.
Web adresa na kojoj se moţe pronaći Web inačica je http://student.foi.hr/~ipadavic.
28
6. Zaključak
Pokušali smo dati prikaz integracije logičkog i objektno orijentiranog
programiranja pomoću alata P#. Logičko programiranje je način rješavanja specifičnih
problema primjenom matematičke logike. Najpoznatiji jezik logičkog programiranja je
Prolog. Prolog se upotrebljava u izradi ekspertnih sustava, naprednom pretraţivanju baza
podataka, procesiranju prirodnog jezika i slično. Danas je u informatičkoj industriji
najznačajniji objektni pristup programiranju. Dobar primjer objektnog programskog
jezika je C#. C# jezik omogućava korištenje svih koncepata objektnog pristupa
(nasljeĎivanje, polimorfizam, enkapsulacija i sl.). P# omogućava pisanje aplikacija koje
koriste logiku iz Prologa i moderne mogućnosti C#-a kao što su grafička sučelja, mreţni
rad, višedretveni rad, korištenje mnoštva postojećih biblioteka (primjerice za XML, baze
podataka i sl.) ili povezivanje s drugim postojećim tehnologijama putem vanjskih sučelja.
Opisali smo postupak izgradnje P# aplikacije korak-po-korak na primjeru jednostavne
Web aplikacije. TakoĎer izradili smo cjelovitu aplikaciju “Kriţić-kruţić” u dvije verzije,
prvoj koja korisničko sučelje implementira u C#-u i drugoj koja C# koristi kao poveznicu
izmeĎu logike iz Prologa i atraktivnog grafičkog sučelja izraĎenog u Flash-u i
omogućava igru putem Interneta. Igra putem interneta ostvarena je pomoću Action
Script-a za klijentsku stranu i Perl-a za serversku stranu.
29
Dodatak A – Izvorni C# kod Web aplikacije prikazane u
poglavlju 4.3.
A.1. Glavna Web forma
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using JJC.Psharp.Lang;
using JJC.Psharp.Predicates;
using JJC.Psharp.Lang.Resource;
using JJC.Psharp.Resources;
namespace Roditelj_djed_web
{
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.TextBox TextBox1;
protected System.Web.UI.WebControls.Button Button1;
protected System.Web.UI.WebControls.Label Label1;
protected System.Web.UI.WebControls.Label Label2;
protected System.Web.UI.WebControls.Button Button2;
protected System.Web.UI.WebControls.Label Label3;
protected System.Web.UI.WebControls.TextBox TextBox3;
protected System.Web.UI.WebControls.TextBox TextBox2;
private void Page_Load(object sender, System.EventArgs e)
{
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
30
this.Button1.Click += new
System.EventHandler(this.Button1_Click);
this.Button2.Click += new
System.EventHandler(this.Button2_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void Button1_Click(object sender, System.EventArgs
e)
{
PrologInterface sharp = new PrologInterface( );
sharp.AddAssembly
(System.Reflection.Assembly.GetExecutingAssembly());
SymbolTerm s1 = SymbolTerm.MakeSymbol( TextBox1.Text
);
VariableTerm netko = new VariableTerm( );
sharp.SetPredicate( new Djed_2(
netko,
s1,
new ReturnCs( sharp ) ) );
sharp.Call();
TextBox2.Text += netko.Dereference().ToString()+" " ;
}
private void Button2_Click(object sender, System.EventArgs
e)
{
PrologInterface sharp = new PrologInterface( );
sharp.AddAssembly
(System.Reflection.Assembly.GetExecutingAssembly());
SymbolTerm s1 = SymbolTerm.MakeSymbol( TextBox1.Text
);
VariableTerm netko = new VariableTerm( );
sharp.SetPredicate( new Roditelj_2(
netko,
s1,
new ReturnCs( sharp ) ) );
sharp.Call();
TextBox3.Text += netko.Dereference().ToString()+" " ;
}
}
}
31
A.2. Datoteka Djed_2.cs
namespace JJC.Psharp.Predicates {
using JJC.Psharp.Lang;
using JJC.Psharp.Lang.Resource;
using Predicates = JJC.Psharp.Predicates;
using Resources = JJC.Psharp.Resources;
public class Djed_2 : Predicate {
public Term arg1, arg2;
public Djed_2(Term a1, Term a2, Predicate cont) {
arg1 = a1;
arg2 = a2;
this.cont = cont;
}
public Djed_2(){}
public override void setArgument(Term[] args, Predicate cont) {
arg1 = args[0];
arg2 = args[1];
this.cont = cont;
}
public override Predicate exec( Prolog engine ) {
engine.setB0();
Term a1, a2, a3;
Predicate p1;
a1 = arg1.Dereference();
a2 = arg2.Dereference();
a3 = engine.makeVariable();
p1 = new Predicates.Roditelj_2(a3, a2, cont);
return new Predicates.Roditelj_2(a1, a3, p1);
}
public override int arity() { return 2; }
public override string ToString() {
return "djed(" + arg1 + ", " + arg2 + ")";
}
}
}
32
A.3. Datoteka Roditelj_2.cs
namespace JJC.Psharp.Predicates {
using JJC.Psharp.Lang;
using JJC.Psharp.Lang.Resource;
using Predicates = JJC.Psharp.Predicates;
using Resources = JJC.Psharp.Resources;
public class Roditelj_2 : Predicate {
static internal readonly Predicate dollar_fail_0 = new
Predicates.dollar_fail_0();
static internal readonly Predicate Roditelj_2_1 = new
Predicates.Roditelj_2_1();
static internal readonly Predicate Roditelj_2_2 = new
Predicates.Roditelj_2_2();
static internal readonly Predicate Roditelj_2_var = new
Predicates.Roditelj_2_var();
public Term arg1, arg2;
public Roditelj_2(Term a1, Term a2, Predicate cont) {
arg1 = a1;
arg2 = a2;
this.cont = cont;
}
public Roditelj_2(){}
public override void setArgument(Term[] args, Predicate cont) {
arg1 = args[0];
arg2 = args[1];
this.cont = cont;
}
public override Predicate exec( Prolog engine ) {
engine.aregs[1] = arg1;
engine.aregs[2] = arg2;
engine.cont = cont;
return call( engine );
}
public virtual Predicate call( Prolog engine ) {
engine.setB0();
return engine.switch_on_term(
Roditelj_2_var,
dollar_fail_0,
Roditelj_2_var,
dollar_fail_0,
dollar_fail_0
);
}
public override int arity() { return 2; }
33
public override string ToString() {
return "roditelj(" + arg1 + ", " + arg2 + ")";
}
}
sealed class Roditelj_2_var : Roditelj_2 {
static internal readonly Predicate Roditelj_2_var_1 = new
Predicates.Roditelj_2_var_1();
public override Predicate exec( Prolog engine ) {
return engine.jtry(Roditelj_2_1, Roditelj_2_var_1);
}
}
sealed class Roditelj_2_var_1 : Roditelj_2 {
public override Predicate exec( Prolog engine ) {
return engine.trust(Roditelj_2_2);
}
}
sealed class Roditelj_2_1 : Roditelj_2 {
static internal readonly SymbolTerm s1 =
SymbolTerm.MakeSymbol("marko");
static internal readonly SymbolTerm s2 =
SymbolTerm.MakeSymbol("ivan");
public override Predicate exec( Prolog engine ) {
Term a1, a2;
a1 = engine.aregs[1].Dereference();
a2 = engine.aregs[2].Dereference();
Predicate cont = engine.cont;
if ( !s1.Unify(a1, engine.trail) ) return engine.fail();
if ( !s2.Unify(a2, engine.trail) ) return engine.fail();
return cont;
}
}
sealed class Roditelj_2_2 : Roditelj_2 {
static internal readonly SymbolTerm s1 =
SymbolTerm.MakeSymbol("ivan");
static internal readonly SymbolTerm s2 =
SymbolTerm.MakeSymbol("stjepan");
public override Predicate exec( Prolog engine ) {
Term a1, a2;
a1 = engine.aregs[1].Dereference();
a2 = engine.aregs[2].Dereference();
Predicate cont = engine.cont;
if ( !s1.Unify(a1, engine.trail) ) return engine.fail();
if ( !s2.Unify(a2, engine.trail) ) return engine.fail();
return cont;
}
}
}
34
Dodatak B – Izvorni Prolog kod igre “Križić-kružić”
% igra krizic-kruzic (prema J.J. Cook, University of Edinburgh,
% http://www.dcs.ed.ac.uk/home/jjc/psharp/psharp-1.1/dlpsharp.html)
:- discontiguous( rule/3 ).
:- dynamic( sumvec/1 ).
:- dynamic( current/1 ).
:- dynamic( x_won/0 ).
:- dynamic( o_won/0 ).
blank( [b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b] ).
% vodoravno
row( [o, o, o, o, b, b, b, b, b, b, b, b, b, b, b, b] ).
row( [b, b, b, b, o, o, o, o, b, b, b, b, b, b, b, b] ).
row( [b, b, b, b, b, b, b, b, o, o, o, o, b, b, b, b] ).
row( [b, b, b, b, b, b, b, b, b, b, b, b, o, o, o, o] ).
% okomito
row( [o, b, b, b, o, b, b, b, o, b, b, b, o, b, b, b] ).
row( [b, o, b, b, b, o, b, b, b, o, b, b, b, o, b, b] ).
row( [b, b, o, b, b, b, o, b, b, b, o, b, b, b, o, b] ).
row( [b, b, b, o, b, b, b, o, b, b, b, o, b, b, b, o] ).
% dijagonalno
row( [o, b, b, b, b, o, b, b, b, b, o, b, b, b, b, o] ).
row( [b, b, b, o, b, b, o, b, b, o, b, b, o, b, b, b] ).
% npr.
current( [o, o, b, x, x, b, b, b, b] ).
%
pickoutrow( [], [], [] ) :- !.
pickoutrow( [o|Rt], [Ch|Ct], [Ch|A] ) :- !, pickoutrow( Rt, Ct, A ).
pickoutrow( [b|Rt], [Ch|Ct], A ) :- !, pickoutrow( Rt, Ct, A ).
count_symb_inner( [], A, A, S ).
count_symb_inner( [S|T], A, R, S ) :- !, A1 is A + 1, count_symb_inner(
T, A1, R, S ).
count_symb_inner( [_|T], A, R, S ) :- count_symb_inner( T, A, R, S ).
count_symb( L, R, S ) :- count_symb_inner( L, 0, R, S ).
add_in_blank( Sym, [], [], [] ).
add_in_blank( Sym, [o|Rt], [b|B], [Sym|B2] ) :- !, add_in_blank( Sym,
Rt, B, B2 ).
add_in_blank( Sym, [_|Rt], [H|B], [H|B2] ) :- add_in_blank( Sym, Rt, B
, B2 ).
% OSTVARIVANJE POBJEDE (tu ce uvijek vratiti kruzic)
% ----------------------------------------------
35
winning_line( Board, Line ) :-
row( R ), pickoutrow( R, Board, PR ),
( count_symb( PR, 4, o ) ; count_symb( PR, 4, x ) ), !,
Line = R.
% PRAVILO 1 (racunalo je o).
% ------
opposer( o, x ).
opposer( x, o ).
rule( Player, Board, NewBoard ) :-
row( R ), pickoutrow( R, Board, PR ),
count_symb( PR, 3, Player ), count_symb( PR, 1, b ), !,
add_in_blank( Player, R, Board, NewBoard ),
( Player = x -> asserta( x_won ) ; asserta( o_won ) ).
%PRAVILO 2
% ------
rule( Player, Board, NewBoard ) :-
row( R ), pickoutrow( R, Board, PR ),
opposer( Player, Opposer ),
count_symb( PR, 3, Opposer ), count_symb( PR, 1, b ), !,
add_in_blank( Player, R, Board, NewBoard ).
% PRAVILO 3
% ------
add_lists( [], [], [] ).
add_lists( [Ah|At], [Bh|Bt], [Sh|St] ) :- Sh is Ah + Bh, add_lists( At,
Bt, St ).
blank_at_pos_inner( [], P ) :- fail.
blank_at_pos_inner( [b|Rt], P, P ) :- !.
blank_at_pos_inner( [_|Rt], P, P ) :- fail.
blank_at_pos_inner( [_|Rt], P, C ) :- C1 is C + 1, blank_at_pos_inner(
Rt, P, C1 ).
blank_at_pos( R, P ) :- blank_at_pos_inner( R, P, 1 ).
row_contains_inner( [Rh|Rt], P, P ) :- !, Rh = o.
row_contains_inner( [Rh|Rt], P, Q ) :- Q1 is Q + 1, row_contains_inner(
Rt, P, Q1 ).
row_contains( R, P ) :- row_contains_inner( R, P, 1 ).
construct_scores_inner( Player, R, B, [], 17 ) :- !.
construct_scores_inner( Player, R, B, [1|St], P ) :-
blank_at_pos( B, P ), row_contains( R, P ), pickoutrow( R, B, PR ),
count_symb( PR, 4, b ), !,
P1 is P + 1, construct_scores_inner( Player, R, B, St, P1 ).
construct_scores_inner( Player, R, B, [2|St], P ) :-
blank_at_pos( B, P ), row_contains( R, P ), pickoutrow( R, B, PR ),
count_symb( PR, 3, b ), count_symb( PR, 1, Player ), !,
P1 is P + 1, construct_scores_inner( Player, R, B, St, P1 ).
construct_scores_inner( Player, R, B, [8|St], P ) :-
blank_at_pos( B, P ), row_contains( R, P ), pickoutrow( R, B, PR ),
36
count_symb( PR, 2, b ), count_symb( PR, 2, Player ), !,
P1 is P + 1, construct_scores_inner( Player, R, B, St, P1 ).
construct_scores_inner( Player, R, B, [0|St], P ) :-
P1 is P + 1, construct_scores_inner( Player, R, B, St, P1 ).
construct_scores_2( P, B ) :- row( R ), construct_scores_inner( P, R,
B, S, 1 ),
sumvec( SUM ), add_lists( SUM, S, New ), abolish( sumvec/1 ),
asserta( sumvec( New ) ), fail.
construct_scores_2( P, B ) :- true.
construct_scores( P, B, S ) :- abolish( sumvec/1 ),
asserta( sumvec( [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0] ) ), !,
construct_scores_2( P, B ), sumvec( S ).
max_list_inner( [], M, M ).
max_list_inner( [H|T], N, M ) :- H > N, !, max_list_inner( T, H, M ).
max_list_inner( [H|T], N, M ) :- max_list_inner( T, N, M ).
max_list( [H|T], M ) :- max_list_inner( [H|T], H, M ).
play_in_first_max( P, [], [], M, [] ) :- !, M = -1.
play_in_first_max( P, [b|Bt], [M|St], M, [P|NBt] ) :- !,
play_in_first_max( P, Bt, St, -1, NBt ).
play_in_first_max( P, [Bh|Bt], [_|St], M, [Bh|NBt] ) :-
play_in_first_max( P, Bt, St, M, NBt ).
rule( Player, Board, NewBoard ) :-
construct_scores( Player, Board, Scores ), max_list( Scores, Max ),
play_in_first_max( Player, Board, Scores, Max, NewBoard ).
play_in_given_place_inner( P, [], [], Pos, A ) :- !, Pos = -1.
play_in_given_place_inner( P, [b|Bt], [P|St], Pos, Pos ) :-
!, A1 is Pos + 1, play_in_given_place_inner( P, Bt, St, -1, A1 ).
play_in_given_place_inner( P, [Bh|Bt], [Bh|St], Pos, A ) :-
A1 is A + 1, play_in_given_place_inner( P, Bt, St, Pos, A1 ).
play_in_given_place( Player, Board, NewBoard, Position ) :-
play_in_given_place_inner( Player, Board, NewBoard, Position, 1 ).
play_me_inner :-
current( B ),
rule( o, B, B2 ),
write( B2 ), nl,
write( 'Play where? ' ), read( Pos ),
play_in_given_place( x, B2, B3, Pos ),
write( B3 ), nl,
abolish( current/1 ),
asserta( current( B3 ) ),
play_me_inner.
play_me :-
abolish( current/1 ), blank( B ), asserta( current( B ) ),
play_me_inner.
37
play_self_inner :-
current( B ),
rule( o, B, B2 ),
write( B2 ), nl,
rule( x, B2, B3 ),
write( B3 ), nl,
abolish( current/1 ),
asserta( current( B3 ) ),
play_self_inner.
play_self :-
abolish( current/1 ), blank( B ), asserta( current( B ) ),
play_self_inner.
% sucelje za pamcenje stanja
% ---------------------------
reset_board( B ) :- abolish( current/1 ), blank( B ), asserta( current(
B ) ), abolish( x_won/0 ), abolish( o_won/0 ).
human_x_move( Position, NewBoard ) :- current( B ),
play_in_given_place( x, B, NewBoard, Position ),
abolish( current/1 ), asserta( current( NewBoard ) ).
computer_move( NewBoard ) :- current( B ), rule( o, B, NewBoard ),
abolish( current/1 ), asserta( current( NewBoard ) ).
% POTEZ RACUNALA
% ---------------
% PRAVILO 1: ako u ovom pokusaju mozes pobijediti, ucini tako.
% PRAVILO 2: ako drugi igrac moze pobijediti u iducem potezu, blokiraj
ga.
% PRAVILO 3: sada za svako moguce polje,
% count 1 za mogucu pobjedu koja jos nije pocela.
% count 2 za mogucu pobjedu ako je jedno polje vec zauzeto.
38
Dodatak C – C# izvorni kod igre “Križić-kružić”
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using JJC.Psharp.Lang;
using JJC.Psharp.Predicates;
using JJC.Psharp.Lang.Resource;
using JJC.Psharp.Resources;
namespace ox4_pado
{
public class Form1 : System.Windows.Forms.Form
{
public static int nacin_igre;
public static bool kontrolna=false;
private System.ComponentModel.Container components = null;
private System.Windows.Forms.Button Cells1;
private System.Windows.Forms.Button Cells2;
private System.Windows.Forms.Button Cells6;
private System.Windows.Forms.Button Cells7;
private System.Windows.Forms.Button Cells5;
private System.Windows.Forms.Button Cells8;
private System.Windows.Forms.Button Cells4;
private System.Windows.Forms.Button Cells3;
private System.Windows.Forms.Button Cells11;
private System.Windows.Forms.Button Cells12;
private System.Windows.Forms.Button Cells16;
private System.Windows.Forms.Button Cells13;
private System.Windows.Forms.Button Cells15;
private System.Windows.Forms.Button Cells14;
private System.Windows.Forms.Button Cells10;
private System.Windows.Forms.Button Cells9;
public SymbolTerm currentPlayer =
SymbolTerm.MakeSymbol("o");
public Term currentBoard;
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.Windows.Forms.MenuItem menuItem2;
private System.Windows.Forms.MenuItem menuItem3;
private System.Windows.Forms.MenuItem menuItem4;
private System.Windows.Forms.MenuItem menuItem5;
private System.Windows.Forms.MenuItem menuItem6;
private System.Windows.Forms.Button[] Cellovi;
39
public Form1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.Cells1 = new System.Windows.Forms.Button();
this.Cells2 = new System.Windows.Forms.Button();
this.Cells6 = new System.Windows.Forms.Button();
this.Cells7 = new System.Windows.Forms.Button();
this.Cells5 = new System.Windows.Forms.Button();
this.Cells8 = new System.Windows.Forms.Button();
this.Cells4 = new System.Windows.Forms.Button();
this.Cells3 = new System.Windows.Forms.Button();
this.Cells11 = new System.Windows.Forms.Button();
this.Cells12 = new System.Windows.Forms.Button();
this.Cells16 = new System.Windows.Forms.Button();
this.Cells13 = new System.Windows.Forms.Button();
this.Cells15 = new System.Windows.Forms.Button();
this.Cells14 = new System.Windows.Forms.Button();
this.Cells10 = new System.Windows.Forms.Button();
this.Cells9 = new System.Windows.Forms.Button();
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.menuItem3 = new System.Windows.Forms.MenuItem();
this.menuItem2 = new System.Windows.Forms.MenuItem();
this.menuItem4 = new System.Windows.Forms.MenuItem();
this.menuItem5 = new System.Windows.Forms.MenuItem();
this.menuItem6 = new System.Windows.Forms.MenuItem();
this.SuspendLayout();
//
// Cells1
//
40
this.Cells1.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells1.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells1.Location = new System.Drawing.Point(40,
40);
this.Cells1.Name = "Cells1";
this.Cells1.Size = new System.Drawing.Size(72, 48);
this.Cells1.TabIndex = 5;
this.Cells1.Click += new
System.EventHandler(this.Cells1_Click);
//
// Cells2
//
this.Cells2.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells2.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells2.Location = new System.Drawing.Point(128,
40);
this.Cells2.Name = "Cells2";
this.Cells2.Size = new System.Drawing.Size(75, 48);
this.Cells2.TabIndex = 6;
this.Cells2.Click += new
System.EventHandler(this.Cells2_Click);
//
// Cells6
//
this.Cells6.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells6.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells6.Location = new System.Drawing.Point(128,
104);
this.Cells6.Name = "Cells6";
this.Cells6.Size = new System.Drawing.Size(75, 48);
this.Cells6.TabIndex = 7;
this.Cells6.Click += new
System.EventHandler(this.Cells6_Click);
//
// Cells7
//
this.Cells7.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells7.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells7.Location = new System.Drawing.Point(216,
104);
this.Cells7.Name = "Cells7";
this.Cells7.Size = new System.Drawing.Size(75, 48);
this.Cells7.TabIndex = 10;
this.Cells7.Click += new
System.EventHandler(this.Cells7_Click);
41
//
// Cells5
//
this.Cells5.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells5.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells5.Location = new System.Drawing.Point(40,
104);
this.Cells5.Name = "Cells5";
this.Cells5.Size = new System.Drawing.Size(75, 48);
this.Cells5.TabIndex = 11;
this.Cells5.Click += new
System.EventHandler(this.Cells5_Click);
//
// Cells8
//
this.Cells8.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells8.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells8.Location = new System.Drawing.Point(304,
104);
this.Cells8.Name = "Cells8";
this.Cells8.Size = new System.Drawing.Size(75, 48);
this.Cells8.TabIndex = 13;
this.Cells8.Click += new
System.EventHandler(this.Cells8_Click);
//
// Cells4
//
this.Cells4.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells4.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells4.Location = new System.Drawing.Point(304,
40);
this.Cells4.Name = "Cells4";
this.Cells4.Size = new System.Drawing.Size(75, 48);
this.Cells4.TabIndex = 14;
this.Cells4.Click += new
System.EventHandler(this.Cells4_Click);
//
// Cells3
//
this.Cells3.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells3.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells3.Location = new System.Drawing.Point(216,
40);
this.Cells3.Name = "Cells3";
this.Cells3.Size = new System.Drawing.Size(75, 48);
42
this.Cells3.TabIndex = 15;
this.Cells3.Click += new
System.EventHandler(this.Cells3_Click);
//
// Cells11
//
this.Cells11.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells11.Font = new
System.Drawing.Font("Microsoft Sans Serif", 20F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(238)));
this.Cells11.Location = new System.Drawing.Point(216,
160);
this.Cells11.Name = "Cells11";
this.Cells11.Size = new System.Drawing.Size(75, 48);
this.Cells11.TabIndex = 23;
this.Cells11.Click += new
System.EventHandler(this.Cells11_Click);
//
// Cells12
//
this.Cells12.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells12.Font = new
System.Drawing.Font("Microsoft Sans Serif", 20F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(238)));
this.Cells12.Location = new System.Drawing.Point(304,
160);
this.Cells12.Name = "Cells12";
this.Cells12.Size = new System.Drawing.Size(75, 48);
this.Cells12.TabIndex = 22;
this.Cells12.Click += new
System.EventHandler(this.Cells12_Click);
//
// Cells16
//
this.Cells16.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells16.Font = new
System.Drawing.Font("Microsoft Sans Serif", 20F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(238)));
this.Cells16.Location = new System.Drawing.Point(304,
224);
this.Cells16.Name = "Cells16";
this.Cells16.Size = new System.Drawing.Size(75, 48);
this.Cells16.TabIndex = 21;
this.Cells16.Click += new
System.EventHandler(this.Cells16_Click);
//
// Cells13
//
this.Cells13.Cursor =
System.Windows.Forms.Cursors.Hand;
43
this.Cells13.Font = new
System.Drawing.Font("Microsoft Sans Serif", 20F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(238)));
this.Cells13.Location = new System.Drawing.Point(40,
224);
this.Cells13.Name = "Cells13";
this.Cells13.Size = new System.Drawing.Size(75, 48);
this.Cells13.TabIndex = 20;
this.Cells13.Click += new
System.EventHandler(this.Cells13_Click);
//
// Cells15
//
this.Cells15.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells15.Font = new
System.Drawing.Font("Microsoft Sans Serif", 20F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(238)));
this.Cells15.Location = new System.Drawing.Point(216,
224);
this.Cells15.Name = "Cells15";
this.Cells15.Size = new System.Drawing.Size(75, 48);
this.Cells15.TabIndex = 19;
this.Cells15.Click += new
System.EventHandler(this.Cells15_Click);
//
// Cells14
//
this.Cells14.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells14.Font = new
System.Drawing.Font("Microsoft Sans Serif", 20F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(238)));
this.Cells14.Location = new System.Drawing.Point(128,
224);
this.Cells14.Name = "Cells14";
this.Cells14.Size = new System.Drawing.Size(75, 48);
this.Cells14.TabIndex = 18;
this.Cells14.Click += new
System.EventHandler(this.Cells14_Click);
//
// Cells10
//
this.Cells10.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells10.Font = new
System.Drawing.Font("Microsoft Sans Serif", 20F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(238)));
this.Cells10.Location = new System.Drawing.Point(128,
160);
this.Cells10.Name = "Cells10";
this.Cells10.Size = new System.Drawing.Size(75, 48);
this.Cells10.TabIndex = 17;
44
this.Cells10.Click += new
System.EventHandler(this.Cells10_Click);
//
// Cells9
//
this.Cells9.Cursor =
System.Windows.Forms.Cursors.Hand;
this.Cells9.Font = new System.Drawing.Font("Microsoft
Sans Serif", 20F, System.Drawing.FontStyle.Regular,
System.Drawing.GraphicsUnit.Point, ((System.Byte)(238)));
this.Cells9.Location = new System.Drawing.Point(40,
160);
this.Cells9.Name = "Cells9";
this.Cells9.Size = new System.Drawing.Size(72, 48);
this.Cells9.TabIndex = 16;
this.Cells9.Click += new
System.EventHandler(this.Cells9_Click);
//
// mainMenu1
//
this.mainMenu1.MenuItems.AddRange(new
System.Windows.Forms.MenuItem[] {
this.menuItem1,
this.menuItem6});
//
// menuItem1
//
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new
System.Windows.Forms.MenuItem[] {
this.menuItem3,
this.menuItem2,
this.menuItem4,
this.menuItem5});
this.menuItem1.Text = "&Igra";
//
// menuItem3
//
this.menuItem3.Index = 0;
this.menuItem3.Text = "&Nova Igra";
this.menuItem3.Click += new
System.EventHandler(this.menuItem3_Click);
//
// menuItem2
//
this.menuItem2.Index = 1;
this.menuItem2.Text = "&Osvježi ploču";
this.menuItem2.Click += new
System.EventHandler(this.menuItem2_Click);
45
//
// menuItem4
//
this.menuItem4.Index = 2;
this.menuItem4.Text = "-";
//
// menuItem5
//
this.menuItem5.Index = 3;
this.menuItem5.Text = "I&zlaz";
this.menuItem5.Click += new
System.EventHandler(this.menuItem5_Click);
//
// menuItem6
//
this.menuItem6.Index = 1;
this.menuItem6.Text = "Pomoć";
this.menuItem6.Click += new
System.EventHandler(this.menuItem6_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5,
13);
this.ClientSize = new System.Drawing.Size(414, 304);
this.Controls.Add(this.Cells11);
this.Controls.Add(this.Cells12);
this.Controls.Add(this.Cells16);
this.Controls.Add(this.Cells13);
this.Controls.Add(this.Cells15);
this.Controls.Add(this.Cells14);
this.Controls.Add(this.Cells10);
this.Controls.Add(this.Cells9);
this.Controls.Add(this.Cells3);
this.Controls.Add(this.Cells4);
this.Controls.Add(this.Cells8);
this.Controls.Add(this.Cells5);
this.Controls.Add(this.Cells7);
this.Controls.Add(this.Cells6);
this.Controls.Add(this.Cells2);
this.Controls.Add(this.Cells1);
this.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.Fixed3D;
this.Menu = this.mainMenu1;
this.Name = "Form1";
this.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Križić - kružić";
this.Load += new
System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
[STAThread]
46
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs
e)
{
resetiraj();
}
private void korisnik(int broj)
{
PrologInterface sharp = new PrologInterface( );
Term a1 = new IntegerTerm( broj );
Term a2 = new VariableTerm( );
Predicate humanMove = new PlayInGivenPlace_4(
currentPlayer, currentBoard,
a2, a1, new ReturnCs( sharp ) );
sharp.SetPredicate( humanMove );
sharp.Call( );
Term result = a2.Dereference();
currentBoard = a2.Dereference();
Term elm;
elm = ((ListTerm)result).cdr.Dereference();
DrawBoard( (ListTerm)currentBoard );
CheckForWinningLine();
SwapPlayer();
if (kontrolna==false)
ComputerMove();
}
private void CheckForWinningLine( )
{
PrologInterface sharp = new PrologInterface( );
Term a2 = new VariableTerm( );
Predicate win = new WinningLine_2( currentBoard, a2,
new ReturnCs( sharp ) );
sharp.SetPredicate( win );
sharp.Call( );
Term result = a2.Dereference();
if ( !result.IsList() || ((ListTerm)result).Length()
!= 16 )
{
return;
47
}
DrawWin( (ListTerm)result );
kontrolna = true;
}
private void DrawWin( ListTerm newBoard )
{
Term result = newBoard;
int brojac=0;
string ploca=result.ToString();
for (int i=1;i<=31;i=i+2)
{
if (ploca[i].ToString() != "b" &&
ploca[i].ToString() != "," && ploca[i].ToString() != "[" &&
ploca[i].ToString() !="]")
{
Cellovi[ brojac ].BackColor =
Color.Beige;
}
brojac++;
}
int gumb=0;
for (gumb=0; gumb<16; gumb++)
Cellovi[gumb].Enabled=false;
System.Windows.Forms.MessageBox.Show("Pobjeda igrača
"+currentPlayer.ToString()+" !");
}
private void SwapPlayer( )
{
if (currentPlayer.name.Equals("x"))
{
currentPlayer = SymbolTerm.MakeSymbol( "o" );
}
else
{
currentPlayer = SymbolTerm.MakeSymbol( "x" );
}
}
private void ComputerMove( )
{
if (nacin_igre == 1)
{
PrologInterface sharp = new PrologInterface( );
Term a3 = new VariableTerm( );
Predicate compMove = new Rule_3( currentPlayer,
currentBoard,
48
a3, new ReturnCs( sharp ) );
sharp.SetPredicate( compMove );
sharp.Call( );
Term result = a3.Dereference();
if ( !result.IsList() ||
((ListTerm)result).Length() != 16 )
{
return;
}
currentBoard = a3.Dereference();
Term elm2;
elm2 = ((ListTerm)result).cdr.Dereference();
DrawBoard( (ListTerm)currentBoard );
CheckForWinningLine( );
SwapPlayer( );
}
}
private void button3_Click(object sender, System.EventArgs
e)
{
ComputerMove();
}
public void postavi (int vrijednost, bool logika)
{
nacin_igre=vrijednost;
kontrolna = logika;
}
private void Form1_Load(object sender, System.EventArgs e)
{
this.Show();
Pocetak p = new Pocetak( );
p.ShowDialog();
Cellovi = new Button[] {Cells1, Cells2, Cells3,
Cells4, Cells5, Cells6, Cells7, Cells8,
Cells9, Cells10, Cells11, Cells12, Cells13, Cells14, Cells15,
Cells16 };
resetiraj();
}
private void resetiraj()
{
kontrolna = false;
49
currentPlayer = SymbolTerm.MakeSymbol( "o" );
VariableTerm ispis = new VariableTerm();
PrologInterface sharp = new PrologInterface( );
sharp.AddAssembly
(System.Reflection.Assembly.GetExecutingAssembly());
Term a1 = new VariableTerm( );
Predicate reset = new Blank_1( a1, new ReturnCs(
sharp ) );
sharp.SetPredicate( reset );
sharp.Call( );
Term result = a1.Dereference();
Term elm;
elm = ((ListTerm)result).cdr.Dereference();
currentBoard = result.Dereference();
DrawBoard( (ListTerm)currentBoard );
for (int i = 0; i < 16; i++)
{
if (Cellovi[i].Text != "")
{
Cellovi[ i ].Text = "";
}
}
int brojac=0;
string ploca=result.ToString();
for (int i=1;i<=31;i=i+2)
{
Cellovi[ brojac ].BackColor = Color.LightGray;
brojac++;
}
int gumb=0;
for (gumb=0; gumb<16; gumb++)
Cellovi[gumb].Enabled=true;
}
private void DrawBoard( ListTerm newBoard )
{
Term result = newBoard;
Term elm;
for (int i = 0; i < 16; i++)
{
elm = ((ListTerm)result).car.Dereference();
if (elm.ToString() != "b")
{
Cellovi[ i ].Text = elm.ToString();
}
result =
((ListTerm)result).cdr.Dereference();
50
if( !( result is ListTerm ) )
break;
}
}
private void CelloviClick(object sender, System.EventArgs
e)
{
int cell = -1;
for( int i = 1; i <= 16; ++i )
{
if( Cellovi[ i - 1 ] == sender )
cell = i;
}
if( cell == -1 )
return;
korisnik(cell);
}
private void Cells1_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells2_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells3_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells4_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells5_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells6_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells7_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells8_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells9_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells10_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells11_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells12_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells13_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells14_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells15_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void Cells16_Click(object sender, System.EventArgs
e) { CelloviClick( sender, e ); }
private void menuItem2_Click(object sender,
System.EventArgs e)
{
51
resetiraj();
}
private void menuItem3_Click(object sender,
System.EventArgs e)
{
Pocetak p = new Pocetak();
p.ShowDialog();
resetiraj();
}
private void menuItem5_Click(object sender,
System.EventArgs e)
{
this.Close();
}
private void menuItem6_Click(object sender,
System.EventArgs e)
{
Form1 neka = new Form1();
string put = Directory.GetCurrentDirectory();
Help.ShowHelp(neka, @put + "\\neki.htm","Help");
}
}
}
52
Dodatak D - Action Script izvorni kod grafičkog sučelja
_root.pocetni = "o";
_root.trenutni = _root.pocetni;
_root.kursoro._visible = false;
_root.kursorx._visible = false;
_root.pobjeda2 = null;
_root.pobjeda = null;
_root.watch("varijabla",function(id,oldval,newval)
{
varijabla2 = newval;
if (varijabla2 ne "reset"){
_root.petlja.gotoAndPlay(2);
_root.onemoguciklik();
//postavi(varijabla2,"komp");
}
else
{
resetiraj();
}
});
_root.watch("pobjeda",function(id,oldval,newval){
pobjeda2 = newval;
_root.petlja2.gotoAndPlay(2);
});
/////////////////////////////////////////////////////////////////
function postavi (broj,tko){
if (_root.trenutni eq "o"){
duplicateMovieClip(_root.ploca.krug,"krug"+broj,1000-broj);
novi = _root.ploca["krug"+broj];
gumb = _root.ploca["btn"+broj];
}
if (_root.trenutni eq "x"){
duplicateMovieClip(_root.ploca.xic,"xic"+broj,1000-broj);
novi = _root.ploca["xic"+broj];
gumb = _root.ploca["btn"+broj];
}
_root.zamjena_igraca();
novi._x = gumb._x+70;
novi._y = gumb._y+45;
gumb.enabled = false;
novi._visible = true;
novi.start();
_root.mySound.start("", 1);
if (tko ne "komp"){
fscommand("flashMessage", broj);
53
}
//trace (broj);
//trace (novi);
//trace (gumb);
}
function zamjena_igraca(){
if (_root.trenutni eq "x")
_root.trenutni = "o";
else
_root.trenutni = "x";
}
function resetiraj(){
for (i=1; i<=16; i++){
brisix = _root.ploca["xic"+i];
brisio = _root.ploca["krug"+i];
gumbic = _root.ploca["btn"+i];
if (brisix ne "undefined"){
brisix.removeMovieClip();
gumbic.enabled = true;
}
if (brisio ne "undefined"){
brisio.removeMovieClip();
gumbic.enabled = true;
}
}
}
/////////////////////////////////////////// ZVUKOVI
mySound = new Sound();
mySound.attachSound("Ping");
/////////////////////////////////////////////
_root.onMouseMove = function(){
_root.kursoro._x = _root._xmouse;
_root.kursoro._y = _root._ymouse;
_root.kursorx._x = _root._xmouse;
_root.kursorx._y = _root._ymouse;
}
/////////////////////////////////////////////
function onemoguciklik(){
for (i=1; i<=16; i++){
gumbic = _root.ploca["btn"+i];
gumbic.enabled = false;
}
}
//////////////////////////////////////////////
function omoguciklik(){
for (i=1; i<=16; i++){
gumbic = _root.ploca["btn"+i];
brisix = _root.ploca["xic"+i];
brisio = _root.ploca["krug"+i];
if ((brisio eq "undefined") && (brisix eq "undefined")){
gumbic.enabled = true;
54
}
}
}
function oznaci_pobjedu(kod_dilimiter){
onemoguciklik();
polje_pobjede = kod_dilimiter.split("|");
if(_root.trenutni eq "o"){
prvi = _root.ploca["xic"+polje_pobjede[0]];
drugi = _root.ploca["xic"+polje_pobjede[1]];
treci = _root.ploca["xic"+polje_pobjede[2]];
cetvrti = _root.ploca["xic"+polje_pobjede[3]];
}
else
{
prvi = _root.ploca["krug"+polje_pobjede[0]];
drugi = _root.ploca["krug"+polje_pobjede[1]];
treci = _root.ploca["krug"+polje_pobjede[2]];
cetvrti = _root.ploca["krug"+polje_pobjede[3]];
}
pobjeda2 = prvi;
prvi.gotoAndStop(13);
drugi.gotoAndStop(13);
treci.gotoAndStop(13);
cetvrti.gotoAndStop(13);
_root.ploca.obrub._visible = false;
_root.kursoro._visible = false;
_root.kursorx._visible = false;
Mouse.show();
}
55
Dodatak E - Ostvarenje igre putem Interneta
E.1. Action Script – klijentski dio
//------globalne varijable--------------------------------------
niz = new Array();
var otvoreni=0;
var zastava=0;
var globalna;
var privatna = 0;
var tkosamja;
var komesaljem="svima";
var skroll = 0;
//--------------------------------------------------------------
function login_ok(arg){
var nadimak = arg;
var stanje = "Uspješno ste logirani!";
_root.login.unos.fade.stanje = stanje;
_root.login.unos.fade.prolaz = 1;
trazi_listu();
}
function login_err(broj){
if (broj eq "2"){
var stanje = "Nepostojeće korisničko ime!";
_root.login.unos.fade.stanje = stanje;
}
if (broj eq "3"){
var stanje = "Upisali ste krivu zaporku!";
_root.login.unos.fade.stanje = stanje;
}
if (broj eq "4"){
var stanje = "Korisnik je već prijavljen!";
_root.login.unos.fade.stanje = stanje;
}
}
function provjeri_liniju(linija){
kod = linija.substr(0,3);
if (kod eq "500"){
odgovor = linija.substr(4,length(linija)-4);
niz = odgovor.split("|");
_root.tkosamja = niz[0];
if (niz[1] eq "1"){login_ok(niz[0]);}
if (niz[1] eq "2"){login_err(2);}
if (niz[1] eq "3"){login_err(3);}
if (niz[1] eq "4"){login_err(4);}
}
56
if (kod eq "503"){
odgovor = linija.substr (4,length(linija)-4);
niz = odgovor.split("|");
sortiraj_niz();
}
if (kod eq "504"){
odgovor = linija.substr (4,length(linija)-4);
dodaj_na_listu(odgovor);
}
if (kod eq "505"){
odgovor = linija.substr (4,length(linija)-4);
makni_sa_liste(odgovor);
makni_tab(odgovor);
}
if (kod eq "501"){
odgovor = linija.substr (4,length(linija)-4);
arr = odgovor.split("|");
poruka = arr[0]+ ": " + arr[1]+newline;
dodaj_u_chatbox(poruka);
}
if (kod eq "502"){
odgovor = linija.substr(4,length(linija)-4);
arr = odgovor.split("|");
_root.sredi_tabove.zastava = 1;
_root.globalna = arr[0];
poruka = arr[1];
gdje = _root.prozor[_root.globalna];
gdje.server += _root.globalna + ":" + poruka + newline;
gdje.server.scroll = gdje.server.maxscroll;
gdje.server.scroll +=1;
_root.sredi_tabove.gotoAndPlay(2);
_root.privatna = 1;
}
}
function trazi_listu(){
var zalistu = "303" //303 kod
trazenje liste
saljem = new XML(zalistu);
socket.send(saljem);
}
function sortiraj_niz(){
niz.sort();
}
function dodaj_na_listu(koga){
niz.push(koga);
niz.sort();
_root.prozor.lista.koji_put = 0;
_root.prozor.lista.gotoAndPlay(1);
}
function makni_sa_liste(koga){
for (var i = 0; i<niz.length; i++){
if (niz[i] eq koga){
pozicija = i;
}
57
}
niz.splice(pozicija,1);
_root.prozor.lista.i=1;
_root.prozor.lista.koji_put = 1;
_root.prozor.lista.gotoAndPlay(2);
}
function dodaj_u_chatbox(poruka){
_root.prozor.chat.server += poruka;
_root.prozor.chat.server.scroll =
_root.prozor.chat.server.maxscroll;
_root.prozor.chat.server.scroll +=1;
}
function makni_tab(koga){
var zz = 1;
var obrisan =0;
for (var j=1; j<=_root.sredi_tabove.i;j++){
tabek = _root.prozor.tabovi["tab"+j];
if (tabek.korisnik eq koga){
chatzabrisat = _root.prozor[tabek.korisnik];
chatzabrisat.removeMovieClip();
obrisan = 1;
tabek.removeMovieClip();
_root.sredi_tabove.i--;
}
if (obrisan eq "0"){zz++;}
}
var r = zz-1;
trace ("RRRRRRR = "+r);
if (r ne "0"){
prijasnji = _root.prozor.tabovi["tab"+r];
_root.komesaljem = prijasnji.korisnik;
}
else
{
_root.komesaljem = "svima";
}
if (zz < _root.sredi_tabove.i){
for (var x=zz; x<=j;x++){
tabek = _root.prozor.tabovi["tab"+x];
tabek._x -=70;
}
}
}
function skrolaj_tabove_ljevo(){
hi = _root.sredi_tabove.i - 1;
if (_root.prozor.tabovi.tab._x ne (-70 * hi)){
_root.prozor.tabovi.tab._x-=70;
for (var j=1; j<=_root.sredi_tabove.i;j++){
tabek = _root.prozor.tabovi["tab"+j];
tabek._x -=70;
}
}
}
58
function skrolaj_tabove_desno(){
if (_root.prozor.tabovi.tab._x ne "0"){
_root.prozor.tabovi.tab._x+=70;
for (var j=1; j<=_root.sredi_tabove.i;j++){
tabek = _root.prozor.tabovi["tab"+j];
tabek._x +=70;
}
}
}
function skrolaj_listu_gore(){
if (niz.length > 15){
if (_root.prozor.lista.puc._y ne "3"){
_root.prozor.lista.puc._y +=14;
for (var j=1; j<=niz.length; j++){
pucek = _root.prozor.lista["puc"+j];
pucek._y +=14;
}
}
}
}
function skrolaj_listu_dolje(){
if (niz.length > 15){
hi = niz.length - 1;
tt = hi - 13;
stani = _root.prozor.lista["puc"+tt];
if (stani._y ne "-10"){
_root.prozor.lista.puc._y-=14;
for (var j=1; j<=niz.length;j++){
pucek = _root.prozor.lista["puc"+j];
pucek._y -=14;
}
}
}
}
function spoji(){
socket = new XMLSocket();// Otvara novi XMLSocket objekt
socket.connect("kalkulator",7777); // Konekcija na server
socket.onXML = noviXML;
socket.onConnect = newConnection;
socket.onClose = endConnection;
}
//funkcija se pokrece svaki puta kada klijent promi poruku od servera
function noviXML(doc){
/////////////// kodovi koje server vraca prilikom logiranja
// kodovi
// 1 - Sve je u redu
// 2 - Korisnik ne postoji
// 3 - Kriva zaporka
////////////////////////////////////
linija = doc.toString();
provjeri_liniju(linija);
}
59
//prva konekcija na server....salje se korisnicko ime i lozinka
function newConnection(success){
if (success){
if (_root.login.stisnuto eq "ok"){
var logiranje = "300 " +
login.unos.korisnik+"|"+login.unos.zaporka; //300 kod
logiranja
saljem = new XML(logiranje);
socket.send(saljem);
}
if (_root.login.stisnuto eq "gost")
{
var logiranje = "300 gost"; //saljem gosta
saljem = new XML(logiranje);
socket.send(saljem);
}
}
}
function endConnection() {
trace("------------------------------------------" );
trace("Hvala vam na koristenju ovog programa");
}
60
E.2. Perl – serverski dio
use IO::Socket;
use IO::Select;
$cc = 0; # Broj konekcija
$p_guest = pack("B*", "0" x 512); # Broj gostiju
%users = (); # Hash kod korisnika
$/ = "\0";
$terminator = "\0";
# $lsn - socket prikljucnica servera postavljena na slusanje
$lsn = new IO::Socket::INET(Listen => 1,LocalPort => 7777, Reuse => 1,
Proto => 'tcp' ) or die ("Nisam se uspio pokrenuti: $!");
$lsn->blocking(0);
$lsn->autoflush(1);
warn "Server je podignut...\n";
# $sel - slekcija dolaznih konekcija
$sel = IO::Select->new($lsn);
while (@r_ready = $sel->can_read) {
foreach $client (@r_ready) {
if($client == $lsn) { #Kreiraj novog klijenta
$clnew = $client->accept;
$clnew->blocking(0);
$sel->add($clnew);
$cc++;
warn "101 Konekcija #$cc od ".$clnew->peerhost." na
portu ".$clnew->peerport . "\n";
my $msg = "100 Pozdrav ".$clnew->peerhost.", i dobro
nam dosli!".$terminator;
syswrite($clnew, $msg, length($msg));
}else{
$nread = sysread($client, $input, 1024);
chomp $input;
if($nread == 0) { bye(); next;}
warn "input=$input\n";
#-------
# Kodovi klijenta:
# 300 - login
# 301 - obicna poruka
# 302 - privatna poruka
# 303 - klijent trazi da mu se posalje lista
korisnika
#
# Kodovi servera:
# 500 login odgovor
# 501 - obicna poruka
# 502 - privatna poruka
# 503 - server salje listu korisnika klijentu
61
# 504 - dosao je novi korisnik (salje svima poruku da
ga dodaju na listu)
# 505 - izasao je korisnik (salje svima poruku da ga
maknu s liste)
#
#-------
my $code = substr($input, 0, 3);
my $value = substr($input, 4);
#authorization
if($code == 300) {
my @login = split(/\|/, $value);
my $res = checkpass($login[0], $login[1]);
my $key, $val;
#Normal login
if($res == 1) {
my $usr = {
UNAME => $login[0],
ITIME => time(),
SOCKREF => $client
};
$users{$client} = $usr;
my $msg = "500 $login[0]\|1$terminator";
syswrite($users{$client}->{SOCKREF},
$msg, length($msg));
warn "User \"$login[0]\" login
uspjesan\n";
# -- salji svima poruku da je dosao
korisnik gost
sendall("504 ".$login[0]);
#Guest login
}elsif($res == 5) {
my $gnum = addguest();
if($gnum != -1) {
my $usr = {
UNAME =>
"Gost".sprintf('%03d', $gnum),
ITIME => time(),
SOCKREF => $client
};
$users{$client} = $usr;
my $msg = "500 ".$usr-
>{UNAME}."\|1$terminator";
syswrite($users{$client}-
>{SOCKREF}, $msg, length($msg));
warn "User \"".$usr->{UNAME}."\"
login uspjesan\n";
# -- salji svima poruku da je dosao
korisnik gost
sendall("504 ".$users{$client}-
>{UNAME});
}else{
warn "Previse gostiju.. ljudi
registrirajte se";
}
#Other cases
62
}else{
warn "Error login $res occured\n";
my $msg = "500
$login[0]\|$res$terminator";
syswrite($client, $msg, length($msg));
bye();
}
#obicna poruka
}elsif($code == 301) {
sendall("501 ".$users{$client}-
>{UNAME}."\|".$value);
#privatna poruka
}elsif($code == 302) {
my @pvt = split(/\|/, $value, 2);
pvt($pvt[0], $pvt[1]);
# klijent je trazio listu
}elsif($code == 303) {
saljilistu();
}
}
}
}
#------------------------------------------------
#Funkcije
#------------------------------------------------
# $res values
# 1 - sve ok
# 2 - korisnik ne postoji
# 3 - krivi password
# 4 - korisnik vec logiran
sub checkpass {
my $user = shift;
my $pass = shift;
my $go = 1;
my $ret = 2; #korisnik ne postoji
my $len, $line, $ret, $key, $val, @usr_data;
if(lc($user) eq "gost") { return 5; } #gost se ne treba
provjeravat
## provjeri jel vec unutra
while (($key, $val) = each %users) {
warn "ret= $ret --provjeravam $user i $val->{UNAME} \n";
if ($user eq $val->{UNAME}) {return 4;} #korisnik vec
logiran
warn "sad je ret = $ret \n";
}
####
$/ = "\012";
$len = length($user);
if($len == 0) { return $ret; } #prazno polje user
open(DAT, "<korisnici.dat");
63
while(($line = <DAT>) && ($go == 1)) {
if(substr($line, 0, $len) eq $user) {
@usr_data = split(/\|/, $line);
if($usr_data[1] eq $pass) {
$ret = 1; # password ok
$go = 0;
}else{
$ret = 3; #krivi password
$go = 0;
}
}
}
close(DAT);
$/ = "\0";
return $ret;
}
sub sendall {
my $msg = shift;
my $nw, $key, $val;
$msg .=$terminator;
if(length($users{$client}->{UNAME}) == 0) { return; } # ako nisi
logiran bjezi ca
while (($key, $val) = each %users) {
if((time() - $val->{ITIME}) > 600) { #timeout
warn "timeout\n";
}else{ # normalno
$nw = syswrite($val->{SOCKREF}, $msg, length($msg));
warn "Wrote $nw b to ", $val->{UNAME}, ",
key=$key\n";
if($nw > 0) { # nesto je posalo clientu
$val->{ITIME} = time();
}
}
}
}
sub pvt {
my $user = shift;
my $msg = shift;
my $nw, $key, $val;
if(length($users{$client}->{UNAME}) == 0) { return; } # ako nisi
logiran bjezi ca
$msg = "502 ".$users{$client}->{UNAME}."\|".$msg.$terminator;
#print "got private\n";
while (($key, $val) = each %users){ # mora odvrtit do kraja
liste, neznam zasto :(
print "compare: \"", $val->{UNAME}, "\" with \"$user\"\n";
if($val->{UNAME} eq $user) {
$nw = syswrite($val->{SOCKREF}, $msg, length($msg));
warn Privatna poruka za $user ($nw bytes)\n";
}
}
}
64
sub saljilistu {
# --- funkcija koja posalje cjelu listu trenutnih korisnika
klijentu koji se upravo spojio
my $nw, $key, $val;
my $count = 0;
my $msg = "503 ";
while (($key, $val) = each %users){
if ($count == 0) {
$msg .= $val->{UNAME};
} else {
$msg .= "|" . $val->{UNAME};
}
$count++;
} #while
$msg .= $terminator;
$nw = syswrite($users{$client}->{SOCKREF}, $msg, length($msg));
warn "Poslana lista korisniku: " . $users{$client}->{UNAME} . "
($nw bytes)\n";
}
sub addguest {
my $unp = unpack("B*", $p_guest);
my $i, $len;
$len = length($unp);
for($i = 0; $i < $len; $i++) {
if(substr($unp, $i, 1) == 0) {
substr $unp, $i, 1, "1";
$p_guest = pack("B*", $unp);
return $i;
}
}
return -1;
}
sub delguest {
my $g = shift;
my $gnum = substr($g, 4);
my $unp = unpack("B*", $p_guest);
substr $unp, $gnum, 1, "0";
$p_guest = pack("B*", $unp);
}
sub bye() {
my $clname = $users{$client}->{UNAME};
warn "Disconnection from " . $client->peerhost . " on port " .
$client->peerport
. ". Client \"".$clname."\".\n";
if($clname =~ /gost\d+/i) { # Smanji broj gostiju
delguest($clname);
}
sendall("505 ".$clname);
delete $users{$client};
$sel->remove($client);
$client->close;
$cc--;
}
65
Literatura
1. Beginning ASP.NET 1.1 with Visual C#® .NET 2003, Chris Ullman, John Kauffman,
Chris Hart, Dave Sussman, Daniel Maharry, Wiley Publishing, Inc., Indianapolis,
Indiana, 2004.
2. Jesse Liberty, Programming C#, 2nd
Edition, O’Reilly, 2002.
3. .NET Framework Essentials, 2nd
Edition, Thuan L. Thai, Hoang Lam, O’Reilly, 2002.
4. LOGIC PROGRAMMING AND PROLOG (2ED), Ulf Nilsson and Jan Maluszynski,
http://www.ida.liu.se/~ulfni/lpp (15. oţujka 2005)
5. Language Interoperability and Logic Programming Languages, Jonathan J. Cook,
University of Edinburgh, 2004
6. Prolog, A Tutorial Introduction, James Lu, Jerud J. Mead, Computer Science,
Department, Bucknell University, Lewisburg, PA 17387
7. P# manual, http://www.lfcs.ed.ac.uk/psharp [20. oţujka 2005]
8. Radovan Mario, Programiranje u Prologu, Informator, Zagreb, 1987.
9. http://www.dcs.ed.ac.uk/home/jjc/psharp/psharp-1.1/dlpsharp.html [20. oţujka 2005]
10. http://www.gnu.org/software/kawa [20. oţujka 2005]
11. http://www.gotdotnet.com/team/lang/ [20. oţujka 2005]
12. http://msdn.microsoft.com/net [23. travnja 2005]
13. http://kaminari.scitec.kobe-u.ac.jp/PrologCafe/ [23. travnja 2005]
14. http://www.ifcomputer.com/MINERVA/ [20. travnja 2005]
15. http://www.jython.org/ [7. svibnja2005]
16. http://pauillac.inria.fr/_diaz/gnu-prolog/ [20. oţujka, 2005.]
17. http://www.perl.org [26. travnja, 2005.]
18. http://www.perl.com [26. travnja, 2005]