Practica de diseño 2, "El juego de la vida",Realizada por Ram¢n Uriol Prieto Grupo 12, puesto 3 Primero explicaré que para representar el tablero e definido el tipo Tmatriz, que es un vector que tiene dos valores que haran de coordenadas x e y, en principio lo hize de 1 a 20, pero al usar mundo toroidal necesito hacer calculos en los que valen x e y valen de 0 a 21. Tmatriz = Array [0..21,0..21] of byte; A continuación explicaré los diferentes modulos del programa: {La funci¢n ladotablero simplemente pide al usuario que indique el n£mero de casillas de lado del mundo, teniendo encuenta que el valor introducido este entre 4 y 20} Function ladotablero : integer; Var lado: integer; Begin Clrscr; {$I-} Writeln(''); Write(' Seleccione el n£mero de celulas de lado del mundo aleatorio: '); Readln(lado); While ((IOResult<>0) OR (lado<4) OR (lado>20)) do Begin Writeln(' Valor introducido no valido, tiene que ser un n£mero entero entre 4 y 20.'); Write(' Introduzca otro valor: '); Readln(lado); End; {$I+} ladotablero:=lado; End; {La funci¢n SIoNO pide al usuario que seleccione si o no, la e usado despues en varios prodecimientos} Function SIoNO : boolean; Var sino: string; Begin {$I-} Writeln(''); Write(' Escriba si o no: '); Readln(sino); While ((sino<>'si') AND (sino<>'SI') AND (sino<>'no') AND (sino<>'NO')) DO Begin Write(' Opci¢n introducida no valida, introduzca si o no: '); Readln(sino); End; {$I+} If ((sino='si') OR (sino='SI')) then SIoNO:=true; If ((sino='no') OR (sino='NO')) then SIoNO:=false; End; {La funci¢n probabilidad pide al usuario que le indique la probabilidad de que cada celula este viva o muerta al inicio del juego} Function probabilidad : integer; Var prob: real; Begin Clrscr; {$I-} Writeln(''); Writeln(' Seleccione la probabilidad de que cada celula este viva al generar el mundo'); Write(' aleatorio (numero real de 0 a 1): '); Readln(prob); While ((IOResult<>0) OR (prob<0) OR (prob>1)) do Begin Writeln(' Valor introducido no valido, tiene que ser un n£mero real entre 0 y 1.'); Write(' Introduzca otro valor: '); Readln(prob); End; {$I+} {Lo multiplico por 100 porque el numero aleatorio que uso luego para comparar es de 0 a 100} probabilidad:=Round(prob*100); End; {El procedimiento reglas pide al usuario que indique los turnos y las reglas del juego (X,Y y Z) he impuesto las condiciones que Y tenga que ser menor o igual que X y Z mayor o igual que X, tambien he puesto la opci¢n de que el usuario pueda elegir valores por defecto} Procedure reglas (var turnos,x,y,z : integer); Var pordefecto: boolean; Begin Clrscr; {$I-} Writeln(''); Write(' Seleccione el n£mero de turnos de juego: '); Readln(turnos); While ((IOResult<>0) OR (turnos<1)) do Begin Writeln(' Valor introducido no valido, tiene que ser un n£mero entero y positivo.'); Write(' Introduzca otro valor: '); Readln(turnos); End; Clrscr; Writeln(''); Writeln(' ¨Desea usar las reglas por defecto del juego ( X=3, Y=2 y Z=3)?'); pordefecto:=SIoNO; If pordefecto=true then Begin x:=3; y:=2; z:=3; End Else Begin Write(' Seleccione el valor de X: '); Readln(x); While ((IOResult<>0) OR (x<1) OR (x>8)) do Begin Writeln(' Valor introducido no valido, tiene que ser un n£mero entero entre 1 y 8.'); Write(' Introduzca otro valor: '); Readln(x); End; Clrscr; Writeln(''); Write(' Seleccione el valor de Y: '); Readln(y); While ((IOResult<>0) OR (y<1) OR (y>x)) do Begin Writeln(' Valor introducido no valido, tiene que ser un n£mero entero entre 1 y ',x,'.'); Write(' Introduzca otro valor: '); Readln(y); End; Clrscr; Writeln(''); Write(' Seleccione el valor de Z: '); Readln(z); While ((IOResult<>0) OR (z8)) do Begin Writeln(' Valor introducido no valido, tiene que ser un n£mero entre ',x,' y 8.'); Write(' Introduzca otro valor: '); Readln(z); End; {$I+} End; End; {Esta es la funci¢n que se nos suministro para convertir un archivo txt en un string le e a¤adido {$I-} y {$I+} para evitar que el programa salte si el archivo que introduzca el usuario no existe} Function cargar_mundo(nombreFich: string): string; var fichero:text; linea:string; mundo:String[200]; i,j: integer; begin mundo:=''; assign(fichero,nombreFich); {$I-} Reset(fichero); i := 1; while not eof(fichero) do begin Readln(fichero,linea); mundo:=mundo+linea+'|'; end; cargar_mundo:=mundo; {$I+} end; {En el procedimiento cargarmatriz convierto el string generado en cargar_mundo en una matriz que representara mi mundo, tambien compruebo las caracteristicas del mundo cargado} Procedure cargarmatriz ( archivo:string ; var mundomatriz:Tmatriz ; var lado:integer; var errorC,errorP,errorL:boolean ); Var mundostring : string; total, i, j, k, l, m, cont : integer ; Begin errorP:=false; errorC:=false; errorL:=false; cont:=0; k:=1; l:=0; mundostring:=cargar_mundo(archivo); total:=Length(mundostring); lado:=Round(sqrt(total)); {Compruebo si el mundo tiene entre 4 y 20 casillas de lado} If ((lado<4) OR (lado>20)) then errorL:=true; {Compruebo si el mundo es cuadrado} For m:=1 to total do If mundostring[m]='|' then cont:= cont +1; If cont<>lado then errorC:=true; For j:=1 to lado do for i:=1 to lado do Begin If mundostring[k]='|' then k:=k+1; If mundostring[k]='1' then mundomatriz[i,j]:=1 else mundomatriz[i,j]:=0; k:=k+1 End; {Compruebo si las filas de los lados son 0 (para mundos planos)} for i:=1 to lado do Begin If (mundomatriz[i,1]<>0) OR (mundomatriz[i,lado]<>0) then errorP:=True; End; for j:=1 to lado do Begin If (mundomatriz[1,j]<>0) OR (mundomatriz[lado,j]<>0) then errorP:=True; End; End; {El procedimiento dibujamatriz muestra el mundo por pantalla} Procedure dibujamatriz(mundomatriz : Tmatriz ; lado : integer); Var x, y : byte; Begin for x:=1 to lado do for y:=1 to lado do Begin GotoXY(x+27,y+5); If mundomatriz[x,y]=0 then TextColor(LightGray) Else TextColor(Green); write('0') End; TextColor(Green); GotoXY(2,10); Write('0'); TextColor(LightGray); GotoXY(4,10); Writeln('- C‚lula viva'); Writeln(''); Writeln(' 0 - C‚lula muerta'); End; {El procedimiento mundoAleatorio genera un mundo plano (sin celulas vivas en los bordes) aleatorio segun la probabilidad que a introducido el usuario mediante la funci¢n probabilidad} Procedure mundoAleatorio( var mundo : Tmatriz ; var lado : integer ); Var prob, i, j : integer; Begin prob:=probabilidad; lado:=ladotablero; {Primero genera las celulas muertas de los bordes} for i:=1 to lado do Begin mundo[i,1]:=0; mundo[i,lado]:=0; End; for j:=1 to lado do Begin mundo[1,j]:=0; mundo[lado,j]:=0; End; {Ahora genera el interior del tablero} for i:=2 to lado-1 do for j:=2 to lado-1 do Begin If Random(101)<=prob then mundo[i,j]:=1 else mundo[i,j]:=0; End; End; {El procedimiento mundoAleatorioToroidal genera un mundo toroidal (con celulas vivas en los bordes) aleatorio segun la probabilidad que a introducido el usuario mediante la funci¢n probabilidad} Procedure mundoAleatorioToroidal( var mundo : Tmatriz ; var lado : integer ); Var prob, i, j : integer; Begin prob:=probabilidad; lado:=ladotablero; for i:=1 to lado do for j:=1 to lado do Begin If Random(101)<=prob then mundo[i,j]:=1 else mundo[i,j]:=0; End; End; {En el procedimiento pasaTurno se introduce un mundo plano (sin celulas vivas en los bordes) y lo convierte en el del turno siguiente teniendo en cuenta las reglas (X,Y y Z), funciona contando las celulas vivas de las 8 "vecinas" de cada celula y cambiando su estado seg£n las reglas} Procedure pasaTurno( var mundo : Tmatriz ; lado, x, y, z : integer); Var mundosig : Tmatriz; i, j, k : integer; Begin {Puesto que es un mundo plano, no mira el estado de las celulas de los bordes} for j:=2 to lado-1 do for i:=2 to lado-1 do Begin k:=0; If mundo[i-1,j-1]=1 then k:=k + 1; If mundo[i,j-1]=1 then k:=k + 1; If mundo[i+1,j-1]=1 then k:=k + 1; If mundo[i-1,j]=1 then k:=k + 1; If mundo[i+1,j]=1 then k:=k + 1; If mundo[i-1,j+1]=1 then k:=k + 1; If mundo[i,j+1]=1 then k:=k + 1; If mundo[i+1,j+1]=1 then k:=k + 1; If mundo[i,j]=0 then If k=x then mundosig[i,j]:=1 else mundosig[i,j]:=0; If mundo[i,j]=1 then If ((k>=y) AND (k<=z)) then mundosig[i,j]:=1 else mundosig[i,j]:=0; End; {Pone las celulas de los bordes como muertas} for i:=1 to lado do Begin; mundosig[i,1]:=0; mundosig[i,lado]:=0; End; for j:=1 to lado do Begin; mundosig[1,j]:=0; mundosig[lado,j]:=0; End; mundo:=mundosig; End; {En el procedimiento pasaTurnoToroidal se introduce un mundo toroidal (con celulas vivas en los bordes) y lo convierte en el del turno siguiente teniendo en cuenta las reglas (X,Y y Z), funciona contando las celulas vivas de las 8 "vecinas" de cada celula y cambiando su estado seg£n las reglas} Procedure pasaTurnoToroidal( var mundo : Tmatriz ; lado, a, b, c : integer); Var mundosig : Tmatriz; i, j, k, x, y : integer; Begin {Para hacerlo toroidal, se comprueba si la celula que estamos analizando esta en un borde, si es as¡ se tiene encuenta para cambiar sus celulas "vecinas"} for x:=1 to lado do for y:=1 to lado do Begin k:=0; i:=x; j:=y; If x=1 then i:=lado + 1; If y=0 then j:=lado + 1; If mundo[i-1,j-1]=1 then k:=k + 1; i:=x; j:=y; If y=0 then j:=lado + 1; If mundo[i,j-1]=1 then k:=k + 1; i:=x; j:=y; If x=lado then i:=0; If y=0 then j:=lado + 1; If mundo[i+1,j-1]=1 then k:=k + 1; i:=x; j:=y; If x=1 then i:=lado + 1; If mundo[i-1,j]=1 then k:=k + 1; i:=x; j:=y; If x=lado then i:=0; If mundo[i+1,j]=1 then k:=k + 1; i:=x; j:=y; If x=1 then i:=lado + 1; If y=lado then j:=0; If mundo[i-1,j+1]=1 then k:=k + 1; i:=x; j:=y; If y=lado then j:=0; If mundo[i,j+1]=1 then k:=k + 1; i:=x; j:=y; If x=lado then i:=0; If y=lado then j:=0; If mundo[i+1,j+1]=1 then k:=k + 1; i:=x; j:=y; If mundo[i,j]=0 then If k=a then mundosig[i,j]:=1 else mundosig[i,j]:=0; If mundo[i,j]=1 then If ((k>=b) AND (k<=c)) then mundosig[i,j]:=1 else mundosig[i,j]:=0; End; mundo:=mundosig; End; {El procedimiento generar pregunta al usuario que tipo de mundo se desea generar y segun su respuesta usa los procedimientos antes explicados de mundoAleatorio y mundoAleatorioToroidal} Procedure generar(var mundo:Tmatriz ; var lado:integer ; var toroidal:boolean); Begin Clrscr; Writeln(''); Writeln(' ¨Desea generar un mundo toroidal (con celulas vivas en los bordes)?'); toroidal:=SIoNO; If toroidal=true then mundoAleatorioToroidal(mundo,lado) Else mundoAleatorio(mundo,lado); Clrscr; Writeln(''); Writeln(' Se ha generado el siguiente mundo aleatorio:'); Writeln(''); Writeln( ' Pulse ENTER para volver al men£ principal.'); dibujamatriz(mundo,lado); Readln; End; {El procedimiento cargar pide al usuario que le indique si el archivo a cargar corresponde a un mundo plano o toroidal, y comprueba que ese archivo existe y que cumple con todas las condiciones: matriz cuadrada, ceros en los bordes (si es plano), entre 4 y 20 casillas de lado y archivo de menos de 9 caracteres. Ademas da la opci¢n de cargar el mundo por defecto "inicial.txt"} Procedure cargar(var mundo:Tmatriz ; var lado:integer ; var toroidal:boolean); Var archivo : string; errorC, errorP, errorL, error: boolean; Begin Clrscr; Writeln(''); Writeln(' ¨El mundo que va a cargar es toroidal (con celulas vivas en los bordes)?'); toroidal:=SIoNO; Clrscr; Writeln(''); Writeln(' Escriba el nombre del archivo (8 car cteres m ximo) seguido de ".txt" del cual se cargara el mundo.'); Writeln(''); Write(' Si no escribe nada se cargar  el archivo por defecto (inicial.txt):'); Repeat Begin Readln(archivo); error:=false; errorC:=false; errorP:=false; errorL:=false; If Length(archivo)>12 then Begin Writeln(''); Writeln(' Nombre de archivo no valido, tiene que ser de menos de 9 car cteres.'); Write(' Introduzca otro nombre: '); error:=true End; If archivo='' then archivo:='inicial.txt'; {$I-} If error=false then Begin cargarmatriz (archivo,mundo,lado,errorC,errorP,errorL); If IOResult<>0 then Begin Repeat Write(' Archivo no encontrado, escribe otro: '); Readln(archivo); If archivo='' then archivo:='inicial.txt'; cargarmatriz (archivo,mundo,lado,errorC,errorP,errorL); Until IOResult=0; End; End; {$I+} If ErrorC=true then Begin Writeln(''); Writeln(' El mundo que a introducido no es cuadrado.'); Write(' Introduzca el nombre de otro mundo: '); error:=true; End; If ((ErrorP=true) AND (toroidal=false)) then Begin Writeln(''); Writeln(' El mundo que a introducido no es plano (tiene celulas vivas en los bordes).'); Write(' Introduzca el nombre de otro mundo: '); error:=true; End; If ErrorL=true then Begin Writeln(''); Writeln(' El mundo que a introducido no tiene entre 4 y 20 casillas de lado.'); Write(' Introduzca el nombre de otro mundo: '); error:=true; End; End; Until error=false; Clrscr; Writeln(''); Writeln(' Se ha cargado el siguiente mundo:'); Writeln(''); Writeln( ' Pulse ENTER para volver al men£ principal.'); dibujamatriz(mundo,lado); Readln; End; {El procedimiento ejecucion pregunta al usuario si quiere usar o no un mundo toroidal y comprueba que el mundo que hay cargado coincide con el tipo, usa el procedimiento reglas para que el usuario introduzca las reglas del juego, y pide el modo de ejecucion. Para ejecutar el programa usa los procedimientos pasaTurno y pasaTurnoToroidal.} Procedure ejecucion (var mundo:Tmatriz ; lado:integer ; toroidal:boolean); Var tor, error : boolean; turnos, x, y, z, opcion, i: integer; Begin error:=false; Clrscr; Repeat Writeln(''); Writeln(' ¨Desea ejecutar un mundo toroidal?'); tor:=SIoNO; If ((toroidal=true) AND (tor=false)) then Begin error:=true; Writeln(' El mundo que esta preparado para ejecutarse es toroidal, solo se puede ejecutar en modo mundo toroidal.'); End Else error:=false; Until error=false; reglas(turnos,x,y,z); Clrscr; Writeln(''); Writeln(' ¨Que modo de ejecuci¢n desea utilizar?'); Writeln(''); Writeln(' 1 - Modo "Paso a paso".'); Writeln(''); Writeln(' 2 - Modo "Solo resultados".'); Writeln(''); Write(' Seleccione el n£mero del modo a utilizar: '); {$I-} Readln(opcion); While ((IOResult<>0) OR (opcion<1) OR (opcion>2)) do Begin Writeln(' Valor introducido no valido, tiene que ser 1 o 2.'); Write(' Introduzca otro valor: '); Readln(opcion); End; {$I+} If opcion=1 then {Modo paso a paso} Begin For i:=0 to turnos do Begin Clrscr; Writeln(''); TextColor(Yellow); Writeln(' Turno n£mero: ',i); Writeln(''); TextColor(LightGray); Writeln( ' Pulse ENTER para pasar de turno.'); dibujamatriz(mundo,lado); Readln; If tor=true then pasaTurnoToroidal(mundo,lado,x,y,z) Else pasaTurno(mundo,lado,x,y,z); End; End Else {Modo solo resultados} Begin Clrscr; Writeln(''); TextColor(Yellow); Writeln(' MUNDO INICIAL'); Writeln(''); TextColor(LightGray); Writeln( ' Pulse ENTER para avanzar al mundo final.'); dibujamatriz(mundo,lado); Readln; For i:=0 to turnos do Begin If tor=true then pasaTurnoToroidal(mundo,lado,x,y,z) Else pasaTurno(mundo,lado,x,y,z); End; Clrscr; Writeln(''); TextColor(Yellow); Writeln(' MUNDO FINAL'); Writeln(''); TextColor(LightGray); Writeln( ' Pulse ENTER para volver al men£ principal.'); dibujamatriz(mundo,lado); Readln; End; End; {Variables del programa principal} Var mundo : Tmatriz; opcion, lado : integer; toroidal, vacio : boolean; {Programa principal} Begin Randomize; vacio:=true; Repeat Begin {Dibuja en pantalla el men£ principal} Clrscr; Writeln(''); TextColor(Yellow); Writeln(' PRACTICA DE DISE¥O 2 : "EL JUEGO DE LA VIDA"'); Writeln(' Realizada por Ram¢n Uriol Prieto G12 P3'); Writeln(''); Writeln(''); TextColor(LightGray); Writeln(' 1 - Generar mundo aleatorio.'); Writeln(''); Writeln(' 2 - Ejecuci¢n.'); Writeln(''); Writeln(' 3 - Cargar estado inicial.'); Writeln(''); Writeln(' 4 - Salir.'); Writeln(''); Writeln(''); {Se selecciona la opci¢n} Write(' Seleccione el n£mero de la operaci¢n que desea ejecutar: '); {$I-} Readln(opcion); While ((IOResult<>0) OR (opcion<1) OR (opcion>4)) do Begin Writeln(' Valor introducido no valido, tiene que ser un n£mero entero entre 1 y 4.'); Write(' Introduzca otro valor: '); Readln(opcion); End; {Antes de ejecutar comprueba que haya un mundo cargado} If ((opcion=2) AND (vacio=true)) then Begin opcion:=0; Writeln(''); Writeln(' Antes de ejecutar, tiene que cargar o generar un mundo.'); While ((IOResult<>0) OR (opcion<1) OR (opcion>4)) do Begin Write(' Seleccione otra opci¢n: '); Readln(opcion); End; End; {$I+} If opcion=1 then Begin generar(mundo,lado,toroidal); vacio:=false; End; If opcion=2 then ejecucion(mundo,lado,toroidal); If opcion=3 then Begin cargar(mundo,lado,toroidal); vacio:=false; End; End; {Termina el programa al seleccionar Salir(4)} Until(opcion=4); End. ---------------------------- (añadido tras someter) ---------------------------- 20:18:16 11/12/09 -> Segun los datos introducidos los ficheros son: G12P03D2 -> Los autores del trabajo son: Uriol Prieto, Ramón Maria Nombres originales de los archivos entregados -> G12P3D2.PAS, G12P3D2.txt