[ Foro de Pascal ]
Como se estaba hablando de esto en otro hilo, abro uno específico para hablar del juego de las 3 en raya y, después, del de las 4 en raya.
Para el de las 3 en raya, se juega en un tablero de 3x3, así que se puede usar un array de 2 dimensiones para representarlo.
El pseudocódigo podría ser algo como
Repetir:
- Dibujar el tablero
- Preguntar movimiento al jugador 1
- Dibujar la casilla del jugador 1 (o todo el tablero)
- Si no ha terminado la partida:
+ Preguntar movimiento al jugador 2
+ Dibujar la casilla del jugador 2 (o todo el tablero)
+ Comprobar si ha terminado la partida
Hasta 3 en raya o empate (tablero lleno)
Un ejemplo de cómo se puede desarrollar el juego de las 3 en raya, convirtiendo el pseudocódigo anterior en funciones y procedimientos para que el cuerpo del programa no sea excesivamente largo:
(* Tres en raya basico en consola, por Nacho*)
program TresEnRaya1;
const
(* Simbolos del tablero: blanco, jug.1, jug.2*)
simbolo: array [0..2] of char = (' ', 'O', 'X');
var
tablero: array[1..3, 1..3] of integer; (* Tablero de juego*)
terminado: boolean;
procedure DibujarTablero;
var
fila, columna: integer;
begin
WriteLn;
WriteLn('-------------');
for fila := 1 to 3 do
begin
Write('|');
for columna := 1 to 3 do
Write(' '+simbolo[tablero[fila,columna]]+' |');
WriteLn;
WriteLn('-------------');
end
end;
(* ----- Pregunta donde mover y lo anota en el tablero ----- *)
procedure PreguntarPosicion( jugador: integer ); (* 1 := Jug.1, 2= Jug.2*)
var
fila, columna: integer;
begin
repeat
WriteLn;
(* Pido fila*)
repeat
Write('En que fila (1 a 3) ');
ReadLn(fila);
until fila in [1..3];
(* Pido columna*)
repeat
Write('En que columna (1 a 3) ');
ReadLn(columna);
until columna in [1..3];
if (tablero[fila,columna] <> 0) then
WriteLn('Casilla ocupada!');
until (tablero[fila,columna] = 0);
(* Si todo es correcto, se la asigno*)
tablero[fila,columna] := jugador;
end;
(* ----- Devuelve "true" si hay tres en raya ----- *)
function ComprobarGanador: boolean;
var
hay3enRaya: boolean;
fila, columna: integer;
begin
hay3enRaya := false;
(* Si en alguna fila todas las casillas son iguales y no vac?¡as*)
for fila := 1 to 3 do
if ((tablero[fila, 1] = tablero[fila, 2])
and (tablero[fila, 1] = tablero[fila, 3])
and (tablero[fila, 1] <> 0)) then
hay3enRaya := true;
(* Lo mismo para las columnas*)
for columna := 1 to 3 do
if ((tablero[1,columna] = tablero[2,columna])
and (tablero[1,columna] = tablero[3,columna])
and (tablero[1,columna] <> 0)) then
hay3enRaya := true;
(* Y finalmente miro las dos diagonales*)
if ((tablero[1, 1] = tablero[2, 2])
and (tablero[1, 1] = tablero[3, 3])
and (tablero[1, 1] <> 0)) then
hay3enRaya := true;
if ((tablero[1, 3] = tablero[2, 2])
and (tablero[1, 3] = tablero[3, 1])
and (tablero[1, 3] <> 0)) then
hay3enRaya := true;
ComprobarGanador := hay3enRaya;
end;
(* ----- Devuelve "true" si hay empate ----- *)
function ComprobarEmpate: boolean;
var
algunHueco: boolean;
fila, columna: integer;
begin
(* Si no quedan huecos donde mover, es empate*)
algunHueco := false;
for fila := 1 to 3 do
for columna := 1 to 3 do
if(tablero[fila,columna] = 0) then
algunHueco := true;
ComprobarEmpate := not algunHueco;
end;
(* ----- Cuerpo del programa ----- *)
begin
begin
terminado := false;
(* Dibujar el tablero inicial*)
DibujarTablero;
repeat
(* Pedir al jugador 1*)
PreguntarPosicion( 1 );
(* Dibujar la casilla del jugador 1*)
DibujarTablero;
(* Comprobar si ha terminado la partida*)
terminado := ComprobarGanador;
if terminado then
WriteLn('Gana jugador 1')
else
begin
terminado := ComprobarEmpate;
if terminado then
WriteLn('Empate!')
else
begin
(* Pedir al jugador 2*)
PreguntarPosicion( 2 );
(* Dibujar la casilla del jugador 2*)
DibujarTablero;
(* Comprobar si ha terminado la partida*)
terminado := ComprobarGanador;
if terminado then
WriteLn('Gana jugador 2');
end
end
(* Repetir hasta 3 en raya o empate (tablero lleno)*)
until terminado;
end
end.
Yo lo hice así:
program tresEnRaya;
uses CRT;
var
matriz: array[1..3,1..3] of char;
i,cont: byte;
procedure inicializarMatriz;
begin
matriz[1,1]:='A';
matriz[1,2]:='B';
matriz[1,3]:='C';
matriz[2,1]:='D';
matriz[2,2]:='E';
matriz[2,3]:='F';
matriz[3,1]:='G';
matriz[3,2]:='H';
matriz[3,3]:='J';
end;
procedure mostrarCuadricula;
begin
gotoxy(31,7); writeln(' ³ ³ ');
gotoxy(31,8); writeln(' ³ ³ ');
gotoxy(31,9); writeln(' ÄÄÄÄÅÄÄÄÅÄÄÄÄ ');
gotoxy(31,10);writeln(' ³ ³ ');
gotoxy(31,11);writeln(' ³ ³ ');
gotoxy(31,12);writeln(' ÄÄÄÄÅÄÄÄÅÄÄÄÄ ');
gotoxy(31,13);writeln(' ³ ³ ');
gotoxy(31,14);writeln(' ³ ³ ');
end;
procedure ubicacion(x: byte; y: byte);
begin
if x=1 then
begin
case y of
1: gotoxy(34,8);
2: gotoxy(34,11);
3: gotoxy(34,14);
end;
end;
if x=2 then
begin
case y of
1: gotoxy(38,8);
2: gotoxy(38,11);
3: gotoxy(38,14);
end;
end;
if x=3 then
begin
case y of
1: gotoxy(42,8);
2: gotoxy(42,11);
3: gotoxy(42,14);
end;
end;
end;
procedure mostrarJugadores;
begin
gotoxy(20,18);writeln('JUGADOR 1: ');
gotoxy(20,19);writeln('columna: ');
gotoxy(20,20);writeln('fila: ');
gotoxy(48,18);writeln('JUGADOR 2: ');
gotoxy(48,19);writeln('columna: ');
gotoxy(48,20);writeln('fila: ');
end;
procedure pedirDatos;
var
X,Y: byte;
begin
if cont mod 2 = 1 then
begin
gotoxy(29,19); readln(X);
gotoxy(26,20); readln(Y);
matriz[X,Y]:= 'O';
ubicacion(X,Y);
writeln('O');
inc(cont);
end
else
begin
gotoxy(57,19); readln(X);
gotoxy(54,20); readln(Y);
matriz[X,Y]:='X';
ubicacion(X,Y);
writeln('X');
inc(cont);
end
end;
function noTresEnRaya: boolean;
begin
noTresEnRaya:= true;
if (matriz[1,1]=matriz[1,2]) and (matriz[1,2]=matriz[1,3]) then
begin
noTresEnRaya:= false;
if matriz[1,1]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
if (matriz[2,1]=matriz[2,2]) and (matriz[2,2]=matriz[2,3]) then
begin
noTresEnRaya:= false;
if matriz[2,1]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
if (matriz[3,1]=matriz[3,2]) and (matriz[3,2]=matriz[3,3]) then
begin
noTresEnRaya:= false;
if matriz[3,1]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
if (matriz[1,1]=matriz[2,1]) and (matriz[2,1]=matriz[3,1]) then
begin
noTresEnRaya:= false;
if matriz[1,1]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
if (matriz[1,2]=matriz[2,2]) and (matriz[2,2]=matriz[3,2]) then
begin
noTresEnRaya:= false;
if matriz[1,2]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
if (matriz[1,3]=matriz[2,3]) and (matriz[2,3]=matriz[3,3]) then
begin
noTresEnRaya:= false;
if matriz[1,3]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
if (matriz[1,1]=matriz[2,2]) and (matriz[2,2]=matriz[3,3]) then
begin
noTresEnRaya:= false;
if matriz[1,1]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
if (matriz[3,1]=matriz[2,2]) and (matriz[2,2]=matriz[1,3]) then
begin
noTresEnRaya:= false;
if matriz[3,1]='O' then
begin
gotoxy(50,11);
writeln('Gano el Jugador 1!')
end
else
begin
gotoxy(50,11);
writeln('Gano el Jugador 2!');
end
end;
end;
Begin
ClrScr;
cont:= 1;
inicializarMatriz;
gotoxy(20,3);writeln('* BIENVENIDO AL JUEGO LAS TRES EN RAYA *');
mostrarCuadricula;
mostrarJugadores;
while noTresEnRaya and (cont<=9) do
pedirDatos;
readln;
End.
También lo dejo como adjunto.
Saludos.
Ahora me gustaría que nos presentara el algoritmo del "4 en Raya". Saludos.
Cordial saludo profesor nacho y compañeros.
Profesor es que no se si como una modesta sugerencia podrias modificar el programa del tres en raya para que por cada accion no se genere un nuevo tablero, sino que las jugadas se visualicen en uno solo y que modificaciones se deben hacer si se juega contra el pc.
mil gracias
Ya entiendo lo que me decías, el profesor sí validó las entradas. Lo acabo de correr y lo constaté. Lo malo es que muestra el cuadro nuevamente en diferente posición después de pedir una nueva entrada. Saludos.
Lo de que muestre el tablero en diferente posición es para que funcione (casi) con cualquier compilador, aunque no tenga la unidad "crt".
Si preferís que siempre se vea sólo el tablero en su estado actual, basta poner "uses crt;" al principio del programa y "clrscr;" antes de dibujar el tablero.
Lo de jugar contra el PC es más trabajoso, y quería que fuera un fuente razonablemente breve. Aun así, os doy pistas por si alguien quiere intentarlo:
- Se podría escoger entre tres niveles de dificultad: fácil, medio, difícil
- El fácil es (casi) trivial de programar: se mueve en cualquier casilla al azar, siempre y cuando esté libre.
- El medio podría mirar si en alguna casilla hace tres en raya; en caso contrario mira si en alguna bloquea tres en raya inminentes del contrario; en caso contrario, mueve al azar.
- El difícil es bastante más complejo (y más trabajoso de programar): supone elegir el tablero que lleva a una secuencia más favorable, usando MiniMax: se estudian todos los posibles tableros que se pueden generar a partir de la posición actual, tomando los que mejor resultado dan para "nosotros" (el ordenador, que piensa, por eso lo de "max") y/o peor resultado para el contrario (por eso lo de "min"). Así, el ordenador siempre toma "la mejor decisión posible" (en juegos sencillos, como éste, en los que sí se pueden llegar a probar todas las combinaciones posibles, mientras que puede no ser factible en juegos como el ajedrez, por la enorme cantidad de memoria que consume).
SIN MAS PALABRAS QUE DECIRTE PROFESOR NACHO CABANES EXCELENTES!!! IDEAS LAS QUE NOS DAS PARA JUGAR CONTRA EL ORDENADOR Y DE IGUAL MANERA GRACIAS POR LA EXPLICACION QUE ME DAS RESPECTO A MOSTRAR UNA SOLA VEZ EL TABLERO PUES NO HABIA CAIDO EN CUENTA LO REFERENTE A LA VISUALIZACION EN DISTINTOS COMPILADORES.
MIL GRACIAS PROFESOR.
cordial saludo profesor nacho cabanes y compañeros.
profesor podrias orientarnos en una forma o algoritmo de poder ir iniciando con el programa del 4 en raya, mil gracias por tu generosa ayuda.
Hola profesor nacho cabanes.
profesor nos olvidaste en tu orientacion para poder realizar el juego del 4 en raya, ojala nos des tu valiosa ayuda que siempre esperamos con mucho agradecimiento.
Es cierto. Para las 4 en raya, normalmente se juega en un tablero de 7 (ancho) x 6 (alto), así que se puede tambiénusar un array de 2 dimensiones para representarlo.
El pseudocódigo sería idéntico (o casi, según el nivel de detalles) al de las 3 en raya, con la diferencia de que el apartado de "comprobar si ha terminado la partida" es más trabajoso de realizar:
Repetir:
- Dibujar el tablero
- Preguntar movimiento al jugador 1
- Dibujar la casilla del jugador 1 (o todo el tablero)
- Si no ha terminado la partida:
+ Preguntar movimiento al jugador 2
+ Dibujar la casilla del jugador 2 (o todo el tablero)
+ Comprobar si ha terminado la partida
Hasta 4 en raya o empate (tablero lleno)
Esperaba mucho esta respueta, prof. Nacho Cabanes. La verdad es que el pseudocódigo que acaba de colocar es más o menos como yo lo había pensado; pero la parte más complicada, tal como lo menciona, es comprobar que alguno de los jugadores ha colocado cuatro fichas en seguidas o cuando el tablero esté lleno. ¿Podría indicarme un pseudocódigo para lograr esta comprobación?, ¿cómo sería más o menos esto?, deme alguna orientación, por favor. Muchas Gracias por su valiosa y oportuna ayuda.
Saludos.
Una forma simple, aunque algo larga y engorrosa, de hacer un primer acercamiento a la comprobación de si hay 4 en raya sería:
Para cada columna
- Si casilla1 = casilla2 = casilla3 = casilla4
o casilla2 = casilla3 = casilla4 = casilla5
o casilla3 = casilla4 = casilla5 = casilla6
y casilla4 no esta vacia
- Entonces ganador = casilla4
Para cada fila
[Similar]
Para cada diagonal ascendente
[Similar]
Para cada diagonal descendente
[Similar]
Se puede simplificar usando "while" y un contador en vez de "if" tan largos, pero yo te recomendaría que primero lo implementaras así, que es fácil aunque suponga "copiar y pegar" varias veces con cuidado, y que lo mejores después (si quieres), cuando ya todo funcione.
Lo de saber si el tablero está lleno es tan sencillo como recorrer todo el tablero contar la cantidad de casillas ocupadas. Si son 42 (6x7) y antes no se ha encontrado un ganador, la partida queda en empate. Una alternativa es no contar sino usar un boolean "quedanCasillasEnBlanco", que sea "true" si encuentras alguna casilla no ocupada.
Ok. Gracias por la respuesta. Trataré de implementarla tal como lo indica. Si tengo problemas vuelvo a llamarlo.
Tengo otra pregunta: ¿cómo debe verse en pantalla el juego de 4 en raya?, la parte gráfica es muy limitada en Pascal. ¿Cuál sería la mejor forma de presentarlo?.
Saludos.
Lo ideal es tratar de que el programa sea modular: un procedimiento "dibujarTablero", un procedimiento "pedirColumna", y el resto serían los que se encargan de la lógica del juego. Así, cuando crees una versión en modo gráfico, reharías el "pedirColumna" y el "dibujarTablero", pero el resto del programa no tendría cambios (al menos en principio).
(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)