Search words cannot find the word

Asked

Viewed 2,638 times

6

Guys, I’m trying to make a game of word hunting in java, but I can’t find the word, someone can help?

Follows the code:

import java.io.BufferedReader; 
import java.io.FileReader;
import java.io.IOException; 
import java.util.Scanner;

public class File {
public static void main(String[]args) throws Exception{
//        File arquivo = new File ("C:\\teste01.txt");

FileReader arquivo = new FileReader ("C:\\teste01.txt");
    BufferedReader br = new BufferedReader(arquivo);
    Scanner sc = new Scanner(System.in);

char[][] matriz = null;
    String entrada = null;
    int coluna = 0;
    boolean primeira = true;
    while (br.ready()){
        String linha = br.readLine();
        if(primeira) {
            String []b = linha.split(" ");
            int a = Integer.parseInt(b[0]);
            int d = Integer.parseInt(b[1]);
            matriz = new char[a][d];
            primeira = false;
        } else {
            char[] auxLinha = linha.toCharArray();

            for (int i = 0; i < auxLinha.length; i++) {
                matriz[coluna][i] = auxLinha[i];
            }

            coluna++;
        }
    }

    for (int i = 0; i < matriz.length; i++) {
        for (int j = 0; j < matriz[i].length; j++) {
            System.out.print(matriz[i][j]+" ");
        }
        System.out.println("\n");
    }

br.close();



   int i, j, k, n = 0, p = 0, t; //Contadores

int encontrada = 0; // SIM = 1. NÃO = 0.

 char palavra[][] = null ;
for (i = 0; i < p; i++)
     System.out.println("DIGITE A PALAVRA:\n");
        String palavraNextLine = sc.nextLine(); //Armazena as palavras que serão buscadas na matriz.

System.out.println("RESULTADO:\n");

for (k = 0; k < p; k++) //Para cada palavra
{
    //Inicialmente a palavra é considerada Não-Encontrada.
    encontrada = 0;

    for (i = 0; i < n; i++) //Para cada linha da matriz
    {
        for (j = 0; j < n; j++) //Para cada coluna da matriz
        {
            if (palavra[k][0] == matriz[i][j]) //Se a primeira letra for encontrada
            {
                if (palavra[k][1] == matriz[i - 1][j]) //Se a segunda letra for encontrada acima (Norte)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k]).length; t++)
                        if (palavra[k][t] != matriz[i - t][j])
                            encontrada = 0;

                    if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }

                if (palavra[k][1] == matriz[i + 1][j]) //Se a segunda letra for encontrada abaixo (Sul)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k].length); t++)
                        if (palavra[k][t] != matriz[i + t][j])
                            encontrada = 0;

                     if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }

                if (palavra[k][1] == matriz[i][j + 1]) //Se a segunda letra for encontrada a direita (Leste)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k].length); t++)
                        if (palavra[k][t] != matriz[i][j + t])
                            encontrada = 0;

                     if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }

                if (palavra[k][1] == matriz[i][j - 1]) //Se a segunda letra for encontrada a esquerda (Oeste)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k].length); t++)
                        if (palavra[k][t] != matriz[i][j - t])
                            encontrada = 0;

                    if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }

                if (palavra[k][1] == matriz[i - 1][j + 1]) //Se a segunda letra for encontrada acima-direita (Nordeste)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k].length); t++)
                        if (palavra[k][t] != matriz[i - t][j + t])
                            encontrada = 0;

                     if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }

                if (palavra[k][1] == matriz[i - 1][j - 1]) //Se a segunda letra for encontrada acima-esquerda (Noroeste)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k].length); t++)
                        if (palavra[k][t] != matriz[i - t][j - t])
                            encontrada = 0;

                    if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }

                if (palavra[k][1] == matriz[i + 1][j + 1]) //Se a segunda letra for encontrada abaixo-direita (Sudeste)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k].length); t++)
                        if (palavra[k][t] != matriz[i + t][j + t])
                            encontrada = 0;

                    if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }

                if (palavra[k][1] == matriz[i + 1][j - 1]) //Se a segunda letra for encontrada abaixo-esquerda (Sudoeste)
                {
                    encontrada = 1;

                    for (t = 0; t < (palavra[k].length); t++)
                        if (palavra[k][t] != matriz[i + t][j - t])
                            encontrada = 0;
                     if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }
            }
        }

                     if (encontrada == 1){
                        break;
                }else{
                    return;
                    }
                }
    }

    //Depois da verificação ele diz se a palavra foi encontrada ou não, então passa para a verificação da próxima palavra.
    if (encontrada == 1){
        System.out.println(" PALAVRA ENCONTRADA\n");
    }else{
        System.out.println(" PALAVRA NAO ENCONTRADA\n");
}
}
}
  • Did you give any prints? Tried debugging? Show which way your code is following given a controlled test set. Debugging alien code from scratch is difficult, your doubt should be directed!

  • Not error code, already debugged , but it does not find the word , always returns q the word was not found

2 answers

11


  1. Use the type boolean! He is your friend and serves to help! Do not use int with 0 and 1 to represent true/false values or yes/no.

  2. Learn how to code. Just see how you’ve positioned the blocks else, makes me understand that you put them in the wrong place and with that, you end up getting your own code wrong.

  3. This from here, which appears repeated nine times in your code DOES NOT do what you want:

            if (encontrada == 1) {
                break;
            } else {
                return;
            }
    

    In particular, the return within the method main makes your program abort immediately, no matter if it found the word or not. In the case of your program, you should not use return nowhere.

  4. You do not check the matrix boundaries before accessing your elements, and as a result will have some IndexOutOfBoundsException. For example, on this line:

    if (palavra[k][1] == matriz[i - 1][j]) //Se a segunda letra for encontrada acima (Norte)
    

    Guess what will happen if i has the value 0? The correct is to check this before trying to access the index:

    if (i > 0 && palavra[k][1] == matriz[i - 1][j]) //Se a segunda letra for encontrada acima (Norte)
    
  5. You can name your ties for, while and do-while. For example:

    a: for (int i = 0; i < n; i++) {
        b: for (int j = 0; j < n; j++) {
            // ... blablabla
            break a; // Interrompe o laço a (e também o laço b).
            // ... blablabla
        }
    }
    

    Using this, the logic of your program can be simplified a bit. The same goes for continue.

  6. Name your class of File is a bad idea, after all it will give you a headache when you need the class java.io.File. Use a different name, such as CacaPalavras.

  7. Use the syntax Try-with-Resources to read file data, just like you do with your BufferedReader.

  8. Prefer to declare the variables at the point where they will be used (inside the for) than all of them together on the outside. The golden rule is not to let them have a larger scope than necessary.

  9. The algorithm is much simpler if you divide it into several methods.

  • 2

    Look, that’s a hell of an answer, see? Not only for the work that must have been done to analyze the AP code, but also for the good knowledge of the language embedded in some of its topics.. :)

  • 1

    Seriously that this a: and this break a; work? (I am without IDE to test now), but if this works (which I believe it does), why has no one ever told me? = (. Now all I can say is, "I only know that I know nothing"(Socrates (right? I didn’t understand if it was he who spoke or she)), a and +1, very good explanation and patience in understanding and analyzing the AP algorithm.

  • @Fernando Yes, it really works. :)

  • I’ve been working with Java for more than a year and also never heard or read about the one about naming loops a: for(;). Rake a;. Every day we really learn something new!

  • Label the loop is new for me too. + 1 for suggesting reducing the scope of variables, among others.

9

An object-oriented approach

This problem can be solved also with a bit of good old object orientation, decreasing the repetition of code and the amount of loops and ifs in order to facilitate development and have a simpler end result:

public class CacaPalavras {

    public static boolean palavraEncontrada(char[][] tabuleiro, String palavra) {

        for (int posicaoY = 0; posicaoY < tabuleiro.length; posicaoY++) {

            for (int posicaoX = 0; posicaoX < tabuleiro[posicaoY].length; posicaoX++) {

                if (tabuleiro[posicaoY][posicaoX] == palavra.charAt(0)) {

                    for(Direcao direcao: Direcao.values()) {
                        if (TabuleiroNavegavel.existePalavra(palavra, tabuleiro, direcao, 
                                posicaoY, posicaoX)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}

I used the same logic you proposed: scrolling the board from left to right and from top to bottom and, when finding a letter that matches the first letter of the word sought, moves around the board in a variety of ways to see if you can find the full word.

The rest of the code that makes the magic happen is below:

class TabuleiroNavegavel {
    public static boolean existePalavra(String palavra, char[][] tabuleiro, 
                    Direcao direcao, int posicaoInicialY, int posicalInicialX) {

        StringBuilder palavraEncontrada = new StringBuilder();

        NavegadorLetras letras = direcao.letras(tabuleiro, 
                                    posicaoInicialY, posicalInicialX);
        
        int qtdLetrasLidas = 0;
        
        while(letras.temProxima() && qtdLetrasLidas <= palavra.length()) {
            palavraEncontrada.append(letras.proxima());
            qtdLetrasLidas++;
        }
        return palavraEncontrada.toString().equals(palavra);
    }
}

interface NavegadorLetras {
    boolean temProxima();
    char proxima();
}

interface LetrasNavegaveis {
    NavegadorLetras navegador(final char[][] tabuleiro, 
            final int posicaoInicialY, final int posicalInicialX);
}

enum Direcao {
    LESTE(new Leste()), 
    SUDESTE(new Sudeste()),
    SUL(new Sul()),
    NORDESTE(new Nordeste());
    
    private LetrasNavegaveis letrasNavegaveis;
    
    Direcao(LetrasNavegaveis letrasNavegaveis) {
        this.letrasNavegaveis = letrasNavegaveis; 
    }
    public NavegadorLetras letras(char[][] tabuleiro, 
                            int posicaoInicialY, int posicalInicialX){
        return letrasNavegaveis.navegador(tabuleiro, posicaoInicialY, posicalInicialX);
    }
}

class Leste implements LetrasNavegaveis {

    public NavegadorLetras navegador(final char[][] tabuleiro, 
                            final int posicaoInicialY, final int posicalInicialX) {
        
        return new NavegadorLetras() {
            int posicaoX = posicalInicialX; 
            int posicaoY = posicaoInicialY;
            
            public boolean temProxima() {
                return posicaoX < tabuleiro[posicaoY].length;
            }
            public char proxima() {
                char letra = tabuleiro[posicaoY][posicaoX];
                posicaoX++;
                return letra;
            }
        };
    }
}

class Sudeste implements LetrasNavegaveis {

    public NavegadorLetras navegador(final char[][] tabuleiro, 
                            final int posicaoInicialY, final int posicalInicialX) {
        
        return new NavegadorLetras() {
            
            int posicaoY = posicaoInicialY;
            int posicaoX = posicalInicialX;
            
            public boolean temProxima() {
                return posicaoY >= 0 && posicaoY < tabuleiro.length
                    && posicaoX >= 0 && posicaoX < tabuleiro[posicaoY].length;
            }
            public char proxima() {
                char letra = tabuleiro[posicaoY][posicaoX];
                posicaoY++;
                posicaoX++;
                return letra;
            }
        };
    }
}

class Sul implements LetrasNavegaveis {

    public NavegadorLetras navegador(final char[][] tabuleiro, final int posicaoInicialY,
                            final int posicalInicialX) {
        
        return new NavegadorLetras() {
            int posicaoY = posicaoInicialY;
            int posicaoX = posicalInicialX;

            public boolean temProxima() {
                return posicaoY >= 0 && posicaoY < tabuleiro.length;
            }
            public char proxima() {
                char letra = tabuleiro[posicaoY][posicaoX];
                posicaoY++;
                return letra;
            }
        };
    }
}

class Nordeste implements LetrasNavegaveis {

    public NavegadorLetras navegador(final char[][] tabuleiro, 
                            final int posicaoInicialY, final int posicalInicialX) {
        
        return new NavegadorLetras() {
            int posicaoY = posicaoInicialY;
            int posicaoX = posicalInicialX;
        
            public boolean temProxima() {
                return posicaoY >= 0 && posicaoY < tabuleiro.length
                    && posicaoX < tabuleiro[posicaoY].length;
            }
            public char proxima() {
                char letra = tabuleiro[posicaoY][posicaoX];
                posicaoY--;
                posicaoX++;
                return letra;
            }
        };
    }
}

An example of consumer code:

@Test
public void cacaPalavras() {
    
    char[][] tabuleiro = new char[][] { 
            {'R','X','L','X','A'},
            {'X','A','U','X','X'},
            {'R','U','I','V','A'},
            {'X','A','Z','V','X'},
            {'C','X','A','X','A'}};
    
    assertTrue(CacaPalavras.palavraEncontrada(tabuleiro, "RUIVA"));
    assertTrue(CacaPalavras.palavraEncontrada(tabuleiro, "RAIVA"));
    assertTrue(CacaPalavras.palavraEncontrada(tabuleiro, "LUIZA"));
    assertTrue(CacaPalavras.palavraEncontrada(tabuleiro, "CAIXA"));
    assertFalse(CacaPalavras.palavraEncontrada(tabuleiro, "INEXISTENTE"));
}

You can wrap this code with your logic of reading the board of a file and request a list of user words :-)

How to extend the solution

Note that I only implemented the westernmost reading pattern, so to speak: east, south, southeast, northeast.

But to implement more standards is very simple. You don’t need to enter code in the middle of a large, complex method or reprogram the program flow. Instead, you define a new reading direction in the enumeration and declare a class specialized in reading in this direction.

If you want for example to implement now the reading southwest direction, just declare the following class:

class Sudoeste implements LetrasNavegaveis {

    public NavegadorLetras navegador(final char[][] tabuleiro, final int posicaoInicialY,
                            final int posicalInicialX) {
        
        return new NavegadorLetras() {
            int posicaoY = posicaoInicialY;
            int posicaoX = posicalInicialX;
        
            public boolean temProxima() {
                return posicaoY < tabuleiro.length
                    && posicaoX >= 0;
            }
            public char proxima() {
                char letra = tabuleiro[posicaoY][posicaoX];
                posicaoY++;
                posicaoX--;
                return letra;
            }
        };
    }
}

And add this new reading direction in the enumeration:

SUDOESTE(new Sudoeste());

Now, in the test below, the word "Redhead" will be found:

@Test
public void sudoeste() {
    char[][] tabuleiro = new char[][] { 
            {' ',' ',' ',' ','R'},
            {' ',' ',' ','U',' '},
            {' ',' ','I',' ',' '},
            {' ','V',' ',' ',' '},
            {'A',' ',' ',' ',' '}};
    
    assertTrue(CacaPalavras.palavraEncontrada(tabuleiro, "RUIVA"));
}

And just like that :-)

Completion

I and many of our colleagues consider this code quite simple but I understand that you may not fully understand it yet.

My suggestion, of course, is that you try to understand.

Some Java resources that were used there:

  • Interface
  • Enumeration.
  • Enumeration Extension: I added an attribute to each item of the enumeration, which is the object specialized in traversing the board in that direction.

And although I don’t consider total number of lines very important, I note that although my code works it has even fewer lines than the original code of the question.

  • 1

    This is more of a tutorial than just an answer, not only an object-oriented tutorial, but also "logic" of the game +1, congratulations for the great answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.