Hola Luis.
Te propongo la siguiente solución.
En el siguiente código, hay un método que explora las 8 posibles direcciones:
- horizontal hacia la derecha
- horizontal hacia la izquierda
- vertical hacia abajo
- vertical hacia arriba
- diagonal superior derecha
- diagonal superior izquierda
- diagonal inferior derecha
- diagonal inferior izquierda
Para hacer esto, lo que hacemos es, con dos bucles anidados, recorrer la matriz buscando una letra que coincida con la primera letra (posición 0) de la palabra que buscamos.
Cuando encontramos dicha letra, se empieza a comprobar cada posible dirección. ¿Cómo?
Iniciamos un tercer bucle que recorrerá las siguientes posiciones de la palabra, es decir, la posición 1, la 2,... hasta terminar la palabra.
Para poder comparar con las letras correspondientes a la dirección que estamos comprobando, lo que haremos será hacer una suma o una resta con el índice que está recorriendo la palabra y con el índice, o índices, que recorren las letras de la matriz.
Es decir, la matriz la estaremos recorriendo con dos índices, los clásicos i y j ...
El índice i recorre las "filas" de la matriz, es decir, hace el recorrido vertical
El índice j recorre las "columnas", o sea, el recorrido horizontal.
Entonces, si yo quiero comprobar la dirección "Vertical hacia abajo", lo que haré será hacer una suma del valor del indice i + el valor del índice que recorre la palabra.
De esa manera, estoy recorriendo la palabra y al mismo tiempo las letras en vertical hacia abajo, a partir de la letra que había coincidido.
Te pongo un fragmento del código porque seguro se entiende mejor.
Fíjate en lo que marco en negrita, a la matriz (que yo llamo sopa, por ser una Sopa de Letras), con su indice i hago una suma con el indice v, que es que recorre la palabra
.
Si encuentro que la siguiente letra coincide, a un boolean llamado encontrad le mantengo el valor true. Esto me ayuda a saber si al terminar de recorrer la palabra, me han coincidido todas las letras.
En cambio, si encuentro una letra que NO coincide, ese boolean pasa a ser false, y además hago un
break. Ese break lo que hace es interrumpir, este tercer bucle, porque si me ha fallado una letra no vale la pena seguir comprobando las demás.
Bien, esto es para buscar en
vertical hacia abajo.
Si quiero buscar en la
vertical hacia arriba, el código es el mismo, solo que ahora en lugar de una suma, hago una resta.
Porque así recorro las "filas" de la matriz a la inversa, es decir, hacia arriba
Si quiero buscar en las horizontales, las sumas restas, se las hago a j que es quien recorre las columnas:
¿Y si quiero buscar en las diagonales?
Pues hago las operaciones en ambos índices. Sumaré o restaré según la dirección que quiero comprobar.
Por ejemplo, si quiero mirar la
diagonal inferior derecha, necesito sumar tanto las filas como las columnas:
En cambio, si quiero mirar la diagonal inferior izquierda, sumo a las filas pero resto a las columnas:
En definitiva, jugando con estas sumas y restas, podemos movernos en todos los sentidos posibles dentro de las dos dimensiones que tiene la matriz.
Pero, ojo cuidado, hay que tener en cuenta una cosa.
En nuestras exploraciones de las distintas direcciones, corremos el riesgo de salirnos de los límites de la matriz, lo cuál producirá una excepción y el programa terminará de forma brusca.
Para evitarlo, en cada dirección explorada, debemos usar
TRY CATCH para capturar esa posible excepción y que el programa pueda continuar.
Si una dirección explorada provoca excepción, es que en esa dirección no vamos a encontrar la palabra que buscamos, por tanto al capturar la excepción, el boolean que nos dice si estamos encontrando lo que buscamos, pasará a false.
Así, cada vez que acabemos de explorar una dirección, ya sea porque los bucles han terminado bien o porque se ha producido una excepción, comprobaremos que valor tiene el boolean "encontrado".
Si es true, nuestra búsqueda ha terminado y hacemos que nuestro método retorne "Verdadero".
Si no es true, pues entonces el método continua para comprobar la siguiente posible dirección de búsqueda:
Todo esto lo aplicamos en el siguiente programa ya completo, donde podemos comprobar que funciona perfectamente:
Sí, es un código bastante largo.
Pero lo importante es que funciona y sobre todo que lo entiendas.
Prueba, revisa y pregunta tanto como necesites para que comprendas la lógica que se ha aplicado.
Una vez lo hayas entendido, vamos a hacer algo para mejorar este código.
Es un código muy largo, pero sobre todo, muy repetitivo.
Fíjate que lo que hacemos es repetir 8 veces el mismo patrón de búsqueda, solo varía ligeramente en que aplicamos sumas y/o restas a unos índices o a otros.
Cuando un programa repite tantas veces un código que es prácticamente lo mismo, seguramente existe una forma de poder simplificarlo y evitar tantas repeticiones.
Solo hace falta un poco de imaginación para encontrar la forma de simplificarlo.
Lo que podemos hacer es escribir un segundo método al que por argumentos, podamos decirle en que dirección ha de dirigir la búsqueda.
Podemos usar dos enteros con los que sepa a que índice tiene que hacer suma, o resta, o no hacer nada.
Este podría ser el método, fíjate en la parte que marco en negrita
Aquí a los índices (que también han de llegar por argumentos) siempre les aplicamos una suma, pero les estamos sumando el resultado de un producto.
Este producto se calcula según el índice de la palabra y unos enteros que llegan como argumentos, llamados
dI y dJ.
Estos enteros indican la "dirección" a la que han de ir los indices i y j.
Y pueden tener tres posibles valores: 1, -1 y 0
Si queremos que la i avance (vertical hacia abajo), lo que haremos será multiplicar el índice de la palabra por 1, y así tendremos una suma positiva.
Si queremos que la i retroceda (vertical hacia arriba), multiplicaremos por -1 para tener una suma negativa, es decir, una resta.
Y si queremos que la i no se mueva (busquedas en horizontal) entonces multiplicamos por 0, para así anular el valor del índice de la palabra y así no habrá ningún recorrido en vertical.
De esta forma, el método anterior que nos había quedado tan grande y largo, ahora se reduce a solo esto:
Fíjate como con un único método, podemos hacer búsquedas en las 8 direcciones simplemente indicándole con 0, 1 y -1 hacia dónde ha de dirigir la búsqueda.
Esto hace que el programa final, quede mucho más reducido, y eso que estamos aplicando exactamente la misma lógica que en la primera versión.
Pero un poco de imaginación y aplicando matemáticas básicas ( ¡¡tan solo multiplicar por 1 y 0!! (⊙_☉) ) conseguimos un código más compacto y óptimo.
Espero que se hayan entendido las explicaciones.
Sobre todo, antes de intentar entender el código "compactado", centra esfuerzos en el primer código que aunque sea más grande, posiblemente sea más fácil para entender la lógica del programa.
Un saludo.