/* Universidad Iberoamericana, 14 de Octubre 1996, Programaci¢n L¢gica
Prof. Manuel L¢pez Michelone, Segunda Tarea, V¡ctor Manuel Iniestra Alvarez*/
Domains
elem=integer
lis_elem=integer*
/* Definiciones de los elementos (enteros) y la lista que representa el gato */
Predicates
append(lis_elem,lis_elem,lis_elem)
/* Entran dos listas, sale una con los elementos de ambas */
lon_lis(lis_elem,elem)
/* Regresa la longitud (n£mero de elementos) de una lista */
member(elem,lis_elem)
/* Verifica si un elemento se encuentra o no a una lista */
pon_tablero(lis_elem,lis_elem)
/* Lee las dos listas (X y O) y despliega el tablero */
checa(elem,lis_elem,lis_elem)
/* Verifica que existe en el juego X,O o libre */
juega_tu(lis_elem,lis_elem)
juega_yo(lis_elem,lis_elem)
/* Procedimientos que calculan donde tirar o permiten tirar incrementando
las listas */
pon(lis_elem,lis_elem,string)
/* Se agrega a la lista el elemento que es del tipo string */
gano(lis_elem,symbol)
/* Verifica si ya gano alguien */
gato(lis_elem,lis_elem)
/* Verifica si ya se hizo gato */
tiros(lis_elem,lis_elem,elem)
/* Secuencia de tiros programada: Primero para hacer gato, segundo para
ponerle una "trampa" (tir¢ en una impar) al contrario, luego para
evitar que el contrario nos ponga una "trampa", y al final intenta
ganar el centro o las esquinas */
tiro(lis_elem,lis_elem,elem,elem)
/* Implementaci¢n del tiro: Matem tica */
trans(elem,string)
/* Traduce de integer a string */
juguemos(string)
empieza()
Clauses
append([],List,List).
append([X|List1],List2,[X|List3]):-append(List1,List2,List3).
lon_lis([],0).
lon_lis([_|Tail],Number):-lon_lis(Tail,Count),Number=Count+1.
member(X,[X|_]).
member(X,[_|Y]):-member(X,Y).
checa(N,X,_):-member(N,X),write(" X ").
checa(N,_,O):-member(N,O),write(" O ").
checa(N,_,_):-write(" ",N," ").
pon_tablero(X,O):-checa(8,X,O),write(" | "),checa(3,X,O),write(" | "),checa(4,X,O),nl,
write("----+-----+----"),nl,
checa(1,X,O),write(" | "),checa(5,X,O),write(" | "),checa(9,X,O),nl,
write("----+-----+----"),nl,
checa(6,X,O),write(" | "),checa(7,X,O),write(" | "),checa(2,X,O),nl.
/* checa y pon_tablero leen dos listas: X y O y dependiendo de que haya en
dichas listas despliegan el tablero */
trans(1,"1").trans(2,"2").trans(3,"3").trans(4,"4").trans(5,"5").trans(6,"6").
trans(7,"7").trans(8,"8").trans(9,"9").
pon(Z,[1|Z],"1").pon(Z,[2|Z],"2").pon(Z,[3|Z],"3").pon(Z,[4|Z],"4").pon(Z,[5|Z],"5").
pon(Z,[6|Z],"6").pon(Z,[7|Z],"7").pon(Z,[8|Z],"8").pon(Z,[9|Z],"9").
juega_tu(X,O):-nl,not(gato(X,O)),write("¨D¢nde quieres poner tu marca? "),
readln(R),trans(I,R),not(member(I,X)),not(member(I,O)),
pon(X,X1,R),!,not(gano(X1,x)),juega_yo(X1,O).
juega_tu(X,O):-write("Esa casilla ya esta ocupada"),juega_tu(X,O).
/* juega_tu recibe las dos listas (X,O), verifica que no se haya hecho gato,
pregunta y lee donde quiere tirar, traduce lo leido de string a integer,
verifica que la marca no se haya hecho ya (ni por la computadora ni por el otro),
agrega a la lista X la marca, ve si x ya gan¢, de lo contrario juega la computadora.*/
tiros(X,O,I):-tiro(X,O,I,15).
tiros([3],[5],2).tiros([1],[5],4).tiros([7],[5],8).tiros([9],[5],6).
tiros(X,O,I):-tiro(X,O,I,21).tiros(X,O,I):-tiro(X,O,I,17). /* Para entender el concepto "poner trampa" se sugiere poner */
tiros(X,O,I):-tiro(X,O,I,13).tiros(X,O,I):-tiro(X,O,I,9). /* este par de l¡neas en comentarios y empezar el juego con 7,4,2...*/
tiros(_,_,5).tiros(_,_,8).tiros(_,_,6).tiros(_,_,2).tiros(_,_,4).
tiro(_,[A,B|_],I,N):-A<>N-A-B,B<>N-A-B,N-A-B<=9,I=N-A-B.
tiro(X,[A,_|O],I,N):-tiro(X,[A|O],I,N).
tiro(X,[_,B|O],I,N):-tiro(X,[B|O],I,N).
tiro([A,B|_],_,I,N):-A<>N-A-B,B<>N-A-B,N-A-B<=9,I=N-A-B.
tiro([A,_|X],O,I,N):-tiro([A|X],O,I,N).
tiro([_,B|X],O,I,N):-tiro([B|X],O,I,N).
/* tiro analiza primero la lista de marcas del contrario tomando dos n£meros
cada vez y verificando si se puede hacer una marca que sumadas a las dos ya
hechas de como resultado el n£mero N. Si N=15 entonces evita que el contrario
gane. 21,17,13, y 9 son secuencias para evitar "trampas". Los otros son tiros
directos para cuando no se cumplan ciertos requisitos en el tablero. Este
mismo an lisis se hace con la lista propia para ganar o intentar poner trampas.*/
juega_yo(X,O):-nl,not(gato(X,O)),tiros(X,O,I),trans(I,R),
not(member(I,X)),not(member(I,O)),pon(O,O1,R),
pon_tablero(X,O1),!,not(gano(O1,o)),juega_tu(X,O1).
/* juega_yo recibe las dos listas (X,O), verifica que no se haya hecho gato,
calcula la marca que debe jugar seg£n la secuencia explicada en tiros,
traduce lo calculado de integer a string, verifica que la marca no se haya hecho,
agrega la marca a la lista O, reescribe el tablero, ve si o ya gan¢, de lo
contrario le da el turno a juega_tu. */
gano([A,B,C|_],o):-A+B+C=15,nl,write(" Gan‚"),empieza.
gano([A,B,C|_],x):-A+B+C=15,nl,write(" Ganaste"),empieza.
gano([_,B,C|X],T):-gano([B,C|X],T).
gano([A,_,C|X],T):-gano([A,C|X],T).
gano([A,B,_|X],T):-gano([A,B|X],T).
/* Para ver si ya gan¢ alguien se analizan todas las combinaciones de 3 marcas
que est‚n en la lista. Si una de esas combinaciones da 15 entonces gan¢ el
due¤o de la lista (x,o). */
gato(A,B):-append(A,B,C),lon_lis(C,9),nl,
write(" Ya se hizo Gato."),empieza.
/* Para ver si ya se hizo gato £nicamente se hace un append de las marcas ya
hechas, si la lista resultante tiene una longitud de 9, ya se hizo gato. */
juguemos("yo"):-nl,pon_tablero([],[]),juega_tu([],[]).
juguemos("tu"):-juega_yo([],[]).
juguemos(_):-exit.
/* Lo importante aqui es empezar con listas vac¡as (o se podr¡a hacer trampa).*/
empieza:-nl,write("¨Quien empieza? (tu/yo) "),
readln(R),juguemos(R).
Goal makewindow(1,7,7,"Vamos a Jugar al Gato",1,16,22,58),empieza.
               (
geocities.com/v.iniestra/apuntes)                   (
geocities.com/v.iniestra)