Hola.
Me ha parecido interesante este ejercicio y he hallado una solución. La explico aquí a ver si te sirve.
Sobre la matriz que representa el lienzo
Usar booleanos no es mala idea del todo.
Tambien se podría usar directamente char y llenar la matriz con '-' y '#'
Pero ambos casos presentan un problemita.
El enunciado no lo especifica, pero supongo que las figuras NO se pueden solapar. Es decir, no se podría dibujar un rectangulo encima de otro. O tal vez si...
Pero en el caso de que NO se pueda, aunque se utilicen solo
dos símbolos para representar el lienzo, en realidad cada "punto" del lienzo tiene
tres posibles estados.
- Vacio, porque no hay nada. Se representa con '-'
- Ocupado, si es el borde de la figura, se representa con '#'
- Ocupado, pero si es el area interna de la figura, no el borde, se representa tambien con '-'
Este tercer estado es el que complica un poco la cosa. El char '-' en realidad no implica que el espacio este vacío, puede tratarse del area interna de una figura ya dibujada.
Así que puesto que tenemos tres posibles estados: vacio, ocupado por borde u ocupado por area interna.... no nos va a servir rellenar la matriz con boolean ni tampoco directamente con los dos char usados para dibujar.
Necesitamos idear otra forma que nos indique las tres posibilidades.
Por ejemplo, podemos usar un valor numerico, un int o un byte, para rellenar la matriz.
Y podemos establecer que solo tenga tres posibles valores: 0, 1 y 2
0 -> Espacio libre, se representa en pantalla con "-"
1 -> Area interior de la figura, espacio ocupado, pero se representa tambien con "-"
2 -> Borde exterior de la figura, espacio ocupado, se representa con "#"Así ya solucionamos el como representar los tres posibles estados.
Bueno, dicho esto. Para separar código, he escrito una clase llamada
Lienzo (luego la mostraré) cuyo atributo es precisamente la matriz que representa el lienzo.
Esta clase tiene métodos que se encargan de dibujar en pantalla el lienzo y otro, el más importante y un pelín complicado, el método que se encarga de insertar un rectángulo en el lienzo a partir de dos puntos.
Cada punto, requiere de dos coordenados, una
X para la vertical y otra
Y para la horizontal.
Es decir, el usuario para "pintar" un rectángulo tendrá que proporcionar cuatro valores.
El X e Y del punto de "inicio" y el X e Y del punto de "fin"
Con ese inicio y ese fin, podemos dibujar un rectangulo dentro del lienzo.
Bien, aunque no es del todo necesario, para que el programa sea más legible he escrito una clase llamada
Punto. Es posiblemente la clase más simplona de la historia de la programación xD , pero ayuda a que luego el programa se entienda mejor que está haciendo.
Es basicamente dos atributos X e Y, y sus correspondientes getters
Puntopackage pintaLienzo;
public final class Punto {
private byte puntoX;
private byte puntoY;
public Punto(byte x, byte y) {
puntoX = x;
puntoY = y;
}
public byte getX() {
return puntoX;
}
public byte getY() {
return puntoY;
}
}
A continuacion explico la clase
Lienzo.
-Tiene tres atributos, una matriz de byte y dos constantes para fijar los limites horizontales y verticales de la matriz/lienzo.
- El constructor, lo que hace es inicalizar la matriz y rellenarla con el valor 0, es decir, el lienzo se inicia completamente vacio
- el metodo mostrarLienzo() es muy simple. Recorre la matriz y si encuentra el valor 2, dibuja el char '#' que es el que representa el borde de las figuras.
Si no, dibujará un char '-', ya sea espacio vacio o area interna de alguna figura.
- el metodo insertarRectangulo() es un pelin complicado.
Recibe por parametros dos
Puntos, el de inicio y el de fin.
Se podría haber simplificado si hubieramos decidido que el punto de inicio siempre va a representar la esquina superior izquierda del rectangulo, y el punto de fin siempre será la esquina inferior derecha.
Por ejemplo, inicio = 1,1 ; fin = 10,10
De este modo, siempre recorreriamos la matriz, desde las coordenadas indicadas, de izquierda a derecha y de arriba a abajo.
Pero no he podido resistirme ha dar cierta libertad al usuario para que el decida que esquina representará el punto de inicio y fin.
Así que puede ocurrir que los puntos sean, por ejemplo, inicio 10,1; fin = 1,10
EStas coordenadas en realidad van a dibujar exactamente el mismo rectangulo que las coordenadas del ejemplo anterior, solo que habrá que empezar a dibujar desde una esquina distinta.
Y averiguar donde esta la esquina de inicio, donde la de fin y decidir que direccion van a tomar los bucles que recorren la matriz, ha de hacerlo el código.
Por eso este metodo tiene varios if else anidados. Porque comparo los valores X e Y de ambos puntos, para discernir si inicio esta arriba o abajo respecto a fin, y si además está a la derecha o a la izquierda de este.
Esto significa cuatro posibilidades, y para cada posibilidad, los bucles harán el recorrido en un sentido o en otro.
Otra cosa importante que hace este método es, antes de insertar la figura y modificar ningún valor, comprueba que realmente el area que va a ocupar la figura está libre y no se va a solapar con ninguna otra figura.
Es un metodo de tipo booleano, así que si no puede insertar la figura, devolverá FALSE.
Si no hubo problema en insertar, devolverá TRUE
Lienzopackage pintaLienzo;
public final class Lienzo {
private final int VERTICAL = 30;
private final int HORIZONTAL = 60;
private byte[][] lienzo;
/*
* La matriz que representa el lienzo tendrá 3 posibles valores.
* 0 -> Espacio libre, se representa en pantalla con "-"
* 1 -> Area interior de la figura, espacio ocupado, pero se representa tambien con "-"
* 2 -> Borde exterior de la figura, espacio ocupado, se representa con "#"
*/
public Lienzo() {
lienzo = new byte[VERTICAL][HORIZONTAL];
for (int i = 0; i < VERTICAL; i++)
for (int j = 0; j < HORIZONTAL; j++)
lienzo[i][j] = 0;
}
/**
* Muestra el lienzo en pantalla segun los valores de la matriz
*/
public void mostrarLienzo() {
for (int i = 0; i < VERTICAL; i++) {
for (int j = 0; j < HORIZONTAL; j++)
System.out.print(lienzo[i][j] == 2?"#":"-");//Si es borde, pintamos "#", sino pintamos "-"
System.out.println();
}
}
public boolean insertarRectangulo(Punto inicio, Punto fin) {
/*
* Nos han proporcionado dos Puntos entre los que debemos crear un rectangulo.
* Lo logico sería que el Punto inicio represente la esquina superior izquierda de la figura y
* el Punto fin represente la esquina inferior derecha.
* Pero no tiene por que ser así, podemos dar libertad para que el usuario proporcione los Puntos
* como quiera y el programa se encargue de discenir como orientar la figura
*/
if (inicio.getX() < fin.getX())//Punto de inicio esta por ENCIMA del Punto fin
if (inicio.getY() < fin.getY()) {//Punto de inicio esta a la IZQUIERDA del Punto fin
//inicio es esquina sup-izq, fin es esquina inf-der
/*
* Antes de insertar, comprobamos que el area que va a ocupar el rectangulo
* no está ocupada ya por otra figura
*/
for (int i = inicio.getX(); i <= fin.getX(); i++)
for (int j = inicio.getY(); j <= fin.getY(); j++)
if (lienzo[i][j] != 0) return false;//Se ha encontrado algun espacio ocupado, no se puede insertar figura
//Comprobado que el area esta libre, insertamos la figura
for (int i = inicio.getX(); i <= fin.getX(); i++)
for (int j = inicio.getY(); j <= fin.getY(); j++)
//Si es borde insertamos 2, si es area interior insertamos 1
if (j == inicio.getY() || j == fin.getY() || i == inicio.getX() || i == fin.getX())
lienzo[i][j] = 2;//Es un borde
else
lienzo[i][j] = 1;//Es area interna
}
else {//Punto de inicio esta a la DERECHA del Punto fin
//inicio es esquina sup-der, fin es esquina inf-izq
for (int i = inicio.getX(); i <= fin.getX(); i++)
for (int j = inicio.getY(); j >= fin.getY(); j--)
if (lienzo[i][j] != 0) return false;
//Insertamos
for (int i = inicio.getX(); i >= fin.getX(); i--)
for (int j = inicio.getY(); j <= fin.getY(); j++)
if (j == inicio.getY() || j == fin.getY() || i == inicio.getX() || i == fin.getX())
lienzo[i][j] = 2;
else
lienzo[i][j] = 1;
}
else//Punto de inicio esta por DEBAJO del Punto fin
if (inicio.getY() < fin.getY()) {
//inicio es esquina inf-izq, fin es sup-der
for (int i = inicio.getX(); i >= fin.getX(); i--)
for (int j = inicio.getY(); j <= fin.getY(); j++)
if (lienzo[i][j] != 0) return false;
//Insertamos
for (int i = inicio.getX(); i >= fin.getX(); i--)
for (int j = inicio.getY(); j <= fin.getY(); j++)
if (j == inicio.getY() || j == fin.getY() || i == inicio.getX() || i == fin.getX())
lienzo[i][j] = 2;
else
lienzo[i][j] = 1;
}
else {
//inicio es esquina inf-der, fin es sup-izq
for (int i = inicio.getX(); i >= fin.getX(); i--)
for (int j = inicio.getY(); j >= fin.getY(); j--)
if (lienzo[i][j] != 0) return false;
//Insertamos
for (int i = inicio.getX(); i >= fin.getX(); i--)
for (int j = inicio.getY(); j >= fin.getY(); j--)
if (j == inicio.getY() || j == fin.getY() || i == inicio.getX() || i == fin.getX())
lienzo[i][j] = 2;
else
lienzo[i][j] = 1;
}
//Llegados a este punto, es que la insercion ha sido correcta
return true;
}
}
Y por ultimo, una pequeña clase Test para comprobar si funciona.
Muestra un pequeño menu para que el usuario escoja entre mostrar el Lienzo, insertar un Rectangulo o finalizar el programa.
Para insertar el Rectangulo, se le piden los valores X e y para el
Punto inicio y el
Punto fin. Para pedir estos valores uso un par de metodos que solo aceptan valores acordes a las dimensiones del lienzo.
Una vez obtenido los
Puntos, se los paso a la clase
Lienzo para que intente insertar la figura y me devolverá TRUE o FALSE segun si pudo insertarla o no.
Testpackage pintaLienzo;
import java.util.Scanner;
public final class Test {
static Lienzo lienzo = new Lienzo();
static Scanner teclado = new Scanner(System.in);
static byte pedirX() {
byte x = -1;
do {
System.out.print("\nInserte coordenada X entre 0 y 29: ");
x = teclado.nextByte();
} while(x < 0 || x > 29);
return x;
}
static byte pedirY() {
byte y = -1;
do {
System.out.print("\nInserte coordenada Y entre 0 y 59: ");
y = teclado.nextByte();
} while(y < 0 || y > 59);
return y;
}
static void mostrarMenu() {
System.out.println("\n\n\t\tMENU LIENZO JAVA");
System.out.println("-1- Mostrar lienzo actual");
System.out.println("-2- Insertar un RECTANGULO");
System.out.println("-0- FIN DE PROGRAMA");
System.out.print("Elija opcion: ");
}
static void dibujarRectangulo() {
System.out.println("\n\tPUNTO DE INICIO");
byte inicioX = pedirX();
byte inicioY = pedirY();
System.out.println("\n\tPUNTO DE FIN");
byte finX = pedirX();
byte finY = pedirY();
Punto inicio = new Punto(inicioX, inicioY);
Punto fin = new Punto(finX, finY);
System.out.println(lienzo.insertarRectangulo(inicio, fin)?"\nRECTANGULO insertado":"NO se pudo insertar, pruebe otras coordenadas");
}
public static void main(String[] args) {
int opcion = -1;
do {
mostrarMenu();
opcion = teclado.nextInt();
switch (opcion) {
case 0:
System.out.println("\n\n\t\tFIN DE PROGRAMA");
break;
case 1:
lienzo.mostrarLienzo();
break;
case 2:
dibujarRectangulo();
break;
default:
System.out.println("\nOpcion invalida");
}
}while(opcion != 0);
}
}
Creo que esto cumple con el enunciado.
Siempre y cuando, NO se permita el solapamiendo de figuras.
Si no hubiera problema en dibujar figuras una encima de otras, todo sería más simple y no necesitariamos controlar tres posibles estados.
Echale un ojo y pregunta lo que no entiendas.