Consulta Pascal

Iniciado por Pascaloro, 22 Noviembre 2018, 16:11 PM

0 Miembros y 1 Visitante están viendo este tema.

Pascaloro

Buenos días!! disculpen que lo publique acá pero no se donde publicarlo no encontré ninguna sección de pascal... Estoy haciendo un batalla naval para la facultad (estoy en primer año) y tengo que hacer que los barcos se carguen random en la matriz, sin que colapsen entre si y sin que sean contiguos(No importa si son contiguos en diagonal) logre hacer prácticamente todo pero tengo un problema y es que aveces me carga perfectamente la matriz con los barcos sin que se choquen entre si, pero aveces también me tira un runtime 201 como si se saliera de rango en algún momento pero no logro ver/entender cuando pasa eso y como debería corregirlo... Muchas gracias!! y perdón por publicarlo acá necesito ayuda urgente.
program BatallaNaval;
const
        MinF=1;
        MaxF=15;
        MinC=1;
        MaxC=15;
        CantBarcos=5;
        MaxJugadas=10;
type
        Matriz=Array[MinF..MaxF,MinC..MaxC] of char;
Function BarcoValidoHorizontal(Tablero:matriz;c,f,t:integer):boolean;
var
b:integer;
begin
    b:=1;
    BarcoValidoHorizontal:=False;
    If c+t<MaxC then begin
        If ((Tablero[f,c]<>'B') and (Tablero[f,c-1]<>'B')) then begin
            If Tablero[f,c+1]<>'B' then begin
                While b<>t do begin
                    if (((Tablero[f,c+1]<>'B') and (Tablero[f-1,c]<>'B')) and (Tablero[f+1,c]<>'B')) then begin
                        c:=c+1;
                        b:=b+1;
                    end
                    else
                        BarcoValidoHorizontal:=False;
                end;
                If b=t then
                    BarcoValidoHorizontal:=True;
            end;
        end
        else
            BarcoValidoHorizontal:=False;
    end
    else
        BarcoValidoHorizontal:=false;
end;
Function BarcoValidoVertical(Tablero:matriz;c,f,t:integer):boolean;
var
b:integer;
begin
    b:=1;
    BarcoValidoVertical:=False;
    If f+t<Maxf then begin
        If ((Tablero[f,c]<>'B') and (Tablero[f-1,c]<>'B')) then begin
            If Tablero[f+1,c]<>'B' then begin
                While b<>t do begin
                    if (((Tablero[f+1,c]<>'B') and (Tablero[f,c-1]<>'B')) and (Tablero[f,c+1]<>'B')) then begin
                        f:=f+1;
                        b:=b+1;
                    end
                    else
                        BarcoValidoVertical:=False;
                end;
                If b=t then
                    BarcoValidoVertical:=True;
            end;
        end
        else
            BarcoValidoVertical:=False;
    end
    else
        BarcoValidoVertical:=false;
end;
procedure GenerarTablero(var Tablero:Matriz);
var
       c,f,i,j,b,t,p,k:integer;
begin
        For i:=1 to MaxC do
                For j:=1 to MaxF do
                        Tablero[i,j]:='*';
        k:=0;
        While k<CantBarcos do begin
                b:=0;
                randomize;
                c:=Random(14)+1;
                f:=Random(14)+1;
                t:=Random(4)+2;
                p:=Random(2);
                If p=1 then begin
                    If BarcoValidoHorizontal(Tablero,c,f,t)=True then begin
                        While (b<=t) do begin
                               Tablero[f,c]:='B';
                                c:=c+1;
                                b:=b+1;
                        end;
                    end
                    else
                        k:=k-1;
                end
                else
                    If BarcoValidoVertical(Tablero,c,f,t)=true then begin
                        While (b<=t) do begin
                                Tablero[f,c]:='B';
                                f:=f+1;
                                b:=b+1;
                        end;
                    end
                    else
                        k:=k-1;
                k:=k+1;
        end;
end;
procedure Mostrar(Tablero:matriz);
var
        c,f:integer;
begin
        For c:=1 to maxC do begin
                For f:=1 to MaxF do
                        write(Tablero[c,f]);
                        writeln;
        end;
end;
var
Tablero:matriz;
begin
GenerarTablero(Tablero);
Mostrar(Tablero);
end.

Serapis

#1
No lo he revisado a fondo...
Aseguraría que tu fallo consiste en tus bucles While... ya que los condicionas para acabar cuando alcancen el valor de 't', pero anterior al bucle no verificas si el 'barco' cabe a partir de ahí. Tu sumas filas o columnas hasta que posiblemente desborde el array...
Citar
   While b<>t do begin
       if (((Tablero[f+1,c]<>'B') and (Tablero[f,c-1]<>'B')) and (Tablero[f,c+1]<>'B')) then begin
           f:=f+1;

Tendrías que revisar varios bucles.

La lógica es que crees algunas funciones de revisión...
Te aclaro un poco por encima, bueno las 3 funciones principales del tema que te trae...

- Primero creamos el mapa, además cuando se inicie una nueva partida, también se invoca.
- Básicamente borramos el mapa, marcando cada casilla con 'agua', vacía, un valor 0 si usas bytes,o un char "0"...

funcion GenerarBorrarMapa(integer Filas, integer Columnas)
   integer j, k
   MAXCOLUMNA = (columnas-1)   //Maxcolumna y maxfila se DEBEN declarar a nivel de modulo... lo mismo que los arrays de Mapa (tableros).
   MAXFILA = (filas-1)

   // Hay 2 mapas el propioy el del enemigo...
   Dimensionar array MapaA(0 a MAXFILA , 0 a MAXCOLUMNA ) //es el array de las casillas, el tablero...
   Dimensionar array MapaB(0 a MAXFILA , 0 a MAXCOLUMNA )

   Bucle para j desde 0 a MAXFILA
       bucle para k desde 0 hasta MAXCOLUMNA
           MapaA(j,k) = 0 // marcamos la casilla como vacía
           MapaB(j,k) = 0 // marcamos la casilla como vacía
       siguiente
   siguiente
fin funcion


- Ahora se posicionan todos los barcos en un mapa  (MapaA o MapaB)
- Es decir se debe invocar dos veces cada vez con un mapa distinto.
- Hemos supuesto que la flota se compone de (por ejemplo); Un barco de 5 casillas, 2 de 4, 3 de 3 y 1 de 2 casillas... total la flota tiene 7 barcos... (24 casillas)

funcion PosicionarFlota(array Mapa)
    PosicionarBarco(5, Mapa)  // es preferible posicionar primero los barcos más grandes,
      //los pequeños luego caben mejor en medias que si se hace al revés...
     // por eso los vamos colocando en este orden de mayor a menor...

    PosicionarBarco(4, Mapa)
    PosicionarBarco(4, Mapa)
    PosicionarBarco(3, Mapa)
    PosicionarBarco(3, Mapa)
    PosicionarBarco(3, Mapa)
    PosicionarBarco(2, Mapa)
fin funcion


- Aquí la función que reposiciona un solo barco... nota que se elige si colocarlo vertical u horizontal
- Luego se elige al azar la fila donde ponerlo, después se verifica si cabe en dicha fila, si no cabe se busca otra... Se supone que el mapa es lo suficientemente grande para que quepan todos los barcos holgadamente... si no es así... fallará.
- Al comprobar que un barco cabe en una fila, devuelve la posición donde cabe... pero intentamos colocarlo al azar, solo si tras 5 intentos al azar no fue osible ubicarlo, usamos la posición devuelta.
- Notar que la misma función para verificar si cabe el barco se usa dos veces, perimero recorriendo toda la fila, luego solo desde la posición elegida al azar.
- Solo se pone el pseudocódigo para el caso horizontal, el vertical es solo cambiar donde proceda...

funcion PosicionarBarco( integer piezas , array Mapa)
   buleano b = random(entre 0 y 1)
   integer cabe, pos, n, k
 
   Si b=1 // elegimos ponerlo en horizontal
       Hacer
           fila = random(entre 0 y MAXFILA)
           cabe = BarcoCabeEnFila(piezas, fila, 0, TRUE)
       Repetir mientras (cabe= -1)

       hacer   // haremos 5 reintentos de ubicalro al azar, si fallan, se posicionará en 'cabe'.
           pos = Random(entre 0 y MAXCOLUMNA)
           pos = BarcoCabeEnFila(Piezas, Fila, pos, FALSO)
           n = (n+1)    
       Repetir mientras ((pos=-1) y (n < 5))

       // si se intentó 5 veces al azar y no encajó, lo posicionamos donde se encontró en la fila
       Si (pos= -1) luego pos = cabe
       
       // Finalmente marcamos las casillas donde se colca el barco, con el valor del barco.
       bucle para k desde pos hasta (pos + piezas-1)    
           Mapa(fila, k) = piezas  // una casilla ocupada la marcamos con el número de piezas que tiene ese barco... un barco de 2, con el valor-char 2, uno de 4 con valor o char 4, etc... la vacía tiene valor 0.
       fin si
   Sino // b=0 , se coloca en vertical
        // similar a lo de horizontal, cambiando donde proceda.
   fin si
fin funcion



- Esta función trata de ver si un barco de x piezas de tamaño, cabe en la fila dada... a partir de la posición que se pide. Para ello basta saber si tiene el números de casillas consecutivas libres que tiene 'piezas' de barco.
- La fila ya puede tener casillas ocupadas... cuando se vaya a colocar el barco, primero lo intentará al azar, tras x intentos fallidos, se tomaría el hueco encontrado y devuelto por esta funcion.
- La función se usa con dos usos bien diferenciados al inicio, se recorre la fila entera si es necesario... buscando que quepa. En la otra funcionalidad solo se recorre hasta encontrarlo o se sale... es decir no comprueba más alla de la posición de inicio recibida si se haya alguna ocupada. El parámetro 'Reubicable' se encarga de esto... fíjate en la llamada quien lo llama con TRUE y quien con FALSE
- La función Gemela- BarcoCabeEnColumna, es casi idéntica, cambia solo la comprobación del mapa: If Mapa(k, Columna)  ... MAXCOLUMNA

integer = funcion BarcoCabeEnFila(integer Piezas, integer Fila, Integer Pos, buleano Reubicable)
   integer k, n

   Bucle para k desde Pos hasta MAXFILA
       If Mapa(fila, k) = 0  // " " "Agua" , casilla no ocupada actualmente.
            n = (n+1)
            Si n=Piezas devolver (k-piezas)  // devuelve el punto donde comienza a estar libre
       sino
           si Reubicable=FALSO salir del bucle // o devolver -1 saliendo de la funcion.
           n = 0
       fin si        
   fin bucle

   devolver -1  // no cabe un barco de ese tamaño.
fin funcion


Listo... ya tienes por donde seguir...