{--------------------------------| Reversi |---------------------------------} { Programado por Ronald Bernal } { Fecha de Comienzo 03-12-02 } { Ultima Revisi¢n 27-12-02 } {----------------------------------------------------------------------------} Program Reversi (input, output); const N = 8; CAR_NEGRO = 'x'; CAR_BLANCO = 'o'; CAR_VACIO = ' '; cant_turnos = 30; type linea = 1..N; encerradas = 0..N; casillas = 1..N*N; posiciones = 0..N*N; direccion = -1..1; tipo_color = (NEGRO, BLANCO); tipo_casilla = record case ocupado : boolean of true : (ficha : tipo_color); false : (); end; tipo_tablero = array [linea,linea] of tipo_casilla; tipo_jugada = record fila, columna : linea; end; lista_jugadas = record vector : array [casillas] of tipo_jugada; tope : posiciones; end; var turno : tipo_color; jugada : tipo_jugada; tablero1 : tipo_tablero; cantidad_fichas : array [tipo_color] of posiciones; dirx, diry : direccion; x, y : linea; turnos: 0..cant_turnos; bloqueado : 0..2; termina, jugada_encierra, vale : boolean; jugada_valida : lista_jugadas; procedure mostrar_tablero(tablero : tipo_tablero); var i, j : integer; begin (* mostrar_tablero *) writeln('Tablero:'); writeln; write(' |'); for i := 1 to N do write(i,'|'); writeln; for i := 1 to N do begin write(i,'|'); for j := 1 to N do with tablero[i,j] do begin if ocupado then case ficha of NEGRO : write(CAR_NEGRO); BLANCO : write(CAR_BLANCO); end else write(CAR_VACIO); write('|'); end; writeln; end; writeln; end; (* mostrar_tablero *) function direccion_encierra(tur : tipo_color; jug : tipo_jugada; tabla : tipo_tablero; inc_i, inc_j : direccion) : integer; (* funcion que cuenta la cantidad de fichas del oponente encerradas en la direccion establecida (inc_i, inc_j) *) var i, j : integer; salir : boolean; fichas : encerradas; begin (* direccion_encierra *) direccion_encierra := 0; i := jug.fila; (* coordenadas iniciales *) j := jug.columna; salir := false; fichas := 0; (* cero fichas del oponente encerradas *) if not tabla[i,j].ocupado then (* sale si el incremento (direccion) en ambos sentidos es cero (evita un loop infinito) *) if (inc_i <> 0) or (inc_j <> 0) then begin repeat i := i + inc_i; j := j + inc_j; (* las coordenadas deben estar dentro del tablero *) if (i < 1) or (i > N) or (j < 1) or (j > N) then begin (* si estan fuera, no acumula fichas *) fichas := 0; salir := true; end else with tabla[i,j] do begin (* acumula fichas hasta encontrar una del color del turno o una casilla vacia *) if ocupado then case ficha = tur of true : salir := true; false : fichas := fichas + 1; end (* case *) else begin (* esta vacia, no acumula fichas *) fichas := 0; salir := true; end; end; (* with *) until salir; direccion_encierra := fichas; end; end; (* direccion_encierra *) function es_valida(jug : tipo_jugada; valida : lista_jugadas) : boolean; (* funcion que evalua si la jugada ingresada es valida (true) o no (false) en base a una lista de jugadas validas *) var i : integer; begin (* es_valida *) es_valida := false; (* la jugada debe estar dentro del tablero *) if (jug.fila > 0) and (jug.fila <= N) and (jug.columna > 0) and (jug.columna <= N) then (* busca en toda la lista de jugadas validas *) for i := 1 to valida.tope do if (valida.vector[i].fila = jug.fila) and (valida.vector[i].columna = jug.columna) then es_valida := true; end; (* es_valida *) procedure jugadas_posibles(tabla : tipo_tablero; tur : tipo_color; var posible : lista_jugadas); (* procedimiento que guarda la lista de jugadas posibles *) var jug : tipo_jugada; jugadas: casillas; begin (* jugadas_posibles *) jugadas := 1; (* inicio la cantidad de jugadas posibles y el tope *) posible.tope := 0; (* evalua toda la matriz (tablero) *) for jug.fila := 1 to N do for jug.columna := 1 to N do begin jugada_encierra := (direccion_encierra(tur,jug,tabla,1,1) > 0) or (direccion_encierra(tur,jug,tabla,1,0) > 0) or (direccion_encierra(tur,jug,tabla,1,-1) > 0) or (direccion_encierra(tur,jug,tabla,0,1) > 0) or (direccion_encierra(tur,jug,tabla,0,-1) > 0) or (direccion_encierra(tur,jug,tabla,-1,1) > 0) or (direccion_encierra(tur,jug,tabla,-1,0) > 0) or (direccion_encierra(tur,jug,tabla,-1,-1) > 0); (* cuando encierra fichas del oponente se agrega la jugada a la lista y aumenta el tope de jugadas posibles *) if jugada_encierra then begin with posible do begin vector[jugadas] := jug; tope := tope + 1; end; (* with *) jugadas := jugadas + 1; end; end; (* for *) end; (* jugadas_posibles *) procedure cuenta_fichas(tur : tipo_color; tablero: tipo_tablero; var fichas_jugador : posiciones); (* procedimiento que cuenta las fichas del jugador (tur) *) var i, j : integer; begin (* cuenta_fichas *) fichas_jugador := 0; (* busca en todo el tablero *) for i := 1 to N do for j := 1 to N do with tablero[i,j] do if (ocupado) and (ficha = tur) then fichas_jugador := fichas_jugador + 1; end; (* cuenta_fichas *) procedure cambia_fichas(tur : tipo_color; jug : tipo_jugada; inc_i, inc_j : direccion; var tablero : tipo_tablero); (* procedimento que "da vuelta" las fichas del tablero en la direccion establecida *) var i, j : integer; salir : boolean; begin (* cambia_fichas *) i := jug.fila; (* coordenadas iniciales *) j := jug.columna; salir := false; (* sale si el incremento (direccion) en ambos sentidos es cero (evita un loop infinito) *) if (inc_i <> 0) or (inc_j <> 0) then begin repeat i := i + inc_i; j := j + inc_j; (* "da vuelta" las fichas hasta encontrar una ficha del mismo color del turno *) with tablero[i,j] do case ficha = tur of true : salir := true; false : ficha := tur; end (* case *) until salir; end; end; (* cambia_fichas *) begin (* tarea2 *) (* inicio el tablero vacio *) for x := 1 to N do for y := 1 to N do with tablero1[x,y] do ocupado := false; (* ubico las fichas iniciales *) for x := N div 2 to (N div 2) + 1 do for y := N div 2 to (N div 2) + 1 do with tablero1[x,y] do begin if x = y then ficha := BLANCO else ficha := NEGRO; ocupado := true; end; (* with *) termina := false; (* la partida no termina aun *) turnos := cant_turnos; bloqueado := 0; repeat (* bucle pricipal *) for turno := NEGRO to BLANCO do if not termina then (* esta condicion impide que se imprima el tablero 2 veces al finalizar *) begin mostrar_tablero(tablero1); (* condiciones de finalizacion del juego *) cuenta_fichas(NEGRO, tablero1, cantidad_fichas[NEGRO]); cuenta_fichas(BLANCO, tablero1, cantidad_fichas[BLANCO]); (* si se completa el tablero termina la partida *) if cantidad_fichas[NEGRO] + cantidad_fichas[BLANCO] = N * N then termina := true; if turnos = 0 then begin termina := true; writeln('Se jugaron todos los turnos...'); end; if bloqueado = 2 then begin termina := true; writeln('Ambos jugadores se han quedado bloqueados...'); end; (* imprime la cantidad de fichas de los jugadores *) writeln('Negras ('+CAR_NEGRO+'): ', cantidad_fichas[NEGRO]); writeln('Blancas ('+CAR_BLANCO+'): ', cantidad_fichas[BLANCO]); if not termina then begin writeln('Quedan ', turnos, ' turnos'); (* registra las jugadas validas *) jugadas_posibles(tablero1, turno, jugada_valida); (* si tiene jugada pide que se ingrese de lo contrario debe pasar *) if jugada_valida.tope > 0 then begin bloqueado := 0; repeat if turno = NEGRO then write('Juega Negro: ') else write('Juega Blanco: '); (* lee la jugada ingresada, si no es valida se repite hasta que sea valida *) read(jugada.fila, jugada.columna); vale := es_valida(jugada, jugada_valida); if not vale then writeln('Jugada invalida, realice otra.'); until vale; (* "da vuelta" las fichas que quedan ecerradas en todas las direcciones posibles *) for dirx := -1 to 1 do for diry := -1 to 1 do if direccion_encierra(turno,jugada,tablero1,dirx,diry) > 0 then cambia_fichas(turno,jugada,dirx,diry,tablero1); (* coloca la ficha jugada *) with tablero1[jugada.fila,jugada.columna] do begin ficha := turno; ocupado := true; end; (* with *) end else begin (* cuando no tiene jugada *) bloqueado := bloqueado + 1; if turno = NEGRO then writeln('Juega Negro: ') else writeln('Juega Blanco: '); writeln('No tiene jugada...'); end; end else begin (* termina la partida *) (* resultados finales *) if cantidad_fichas[NEGRO] > cantidad_fichas[BLANCO] then writeln('Gano Negro'); if cantidad_fichas[NEGRO] < cantidad_fichas[BLANCO] then writeln('Gano Blanco'); if cantidad_fichas[NEGRO] = cantidad_fichas[BLANCO] then writeln('Empataron'); end; end; turnos := turnos - 1; until termina; end. (* Reversi *)