Battleship Java

Asked

Viewed 2,443 times

0

Good morning, you guys, I’m doing an exercise in java on the game Battleship, I have a good part of the code but I’m locked on the part of validating the position of the boats. The exercise asks that 4 bardos of different sizes (2,3,4,5) be created in vertical and horizontal position (calling the method) and that the position be random, until ai ok. The problem is that sometimes one boat is built inside the other, sometimes it seems that it leaves the board (even without the outofbounds message). The method to validate is called estaLivre (I couldn’t do much in it...) Can someone give me a hint? Thanks.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Random;

public class BatallaNaval {

/**
 * @param args the command line arguments
 */
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

static int cont = 0;
static int miss = 50;
static int[][] field = new int[10][10];

public static void main(String[] args) {

    int acertos = 0;
    iniciarField();
    colocarBarco(2, 'H');
    colocarBarco(3, 'V');
    colocarBarco(4, 'H');
    colocarBarco(5, 'V');
    mostraTabuleiro();

    while(cont<14 || miss>0){
    if(cont==14||miss==0){break;}
    jogar();
    System.out.println();
    mostraTabuleiro();

    }

}

public static void iniciarField() {

    for (int i = 0; i < field.length; i++) {

        for (int j = 0; j < field.length; j++) {

            field[i][j] = -1;
        }

    }
}

public static void colocarBarco(int longitud, char orientacion) {
     Random r = new Random();
int X;
int Y;
boolean livre = false;

if (orientacion == 'H') {

    do { 
        X = r.nextInt(9);
        Y = r.nextInt(9);
        livre = estaLivre(X, Y, longitud, 1); // 1 = horizontal
    } while(!livre); //podes alterar e colocar um limite mximo de iterações para precaver ciclos infinitos

    // se chegou aqui significa que encontraste uma posição para colocar o navio       
    for ( int i = Y; i <= Y + (longitud - 1); ++i) 
        field[X][i] = 2;

}

if (orientacion == 'V') {
  do { 
        X = r.nextInt(9);
        Y = r.nextInt(9);
        livre = estaLivre(X, Y, longitud, 0); 
    } while(!livre); 
  for ( int i = X; i <= X + (longitud - 1); ++i) 
        field[i][Y] = 2;
}
}

public static void mostraTabuleiro() {
    System.out.println("\t0\t1 \t2 \t3 \t4 \t5\t6\t7\t8\t9");
    System.out.println();

    for (int i = 0; i < 10; i++) {
        System.out.print((i) + "");
        for (int j = 0; j < 10; j++) {
            if (field[i][j] == 0) {
                System.out.print("\t" + "*");
            } else if (field[i][j] == 1) {
                System.out.print("\t" + "X");
            } else if (field[i][j] == 2) {
                System.out.print("\t" + "B");
            } else {
                System.out.print("\t" + "~");
            }

        }
        System.out.println();
    }

}

public static void jogar() {
    try {
        System.out.print("Linha: ");
        String num1Str = in.readLine();
        int linha = Integer.parseInt(num1Str);
        System.out.print("Coluna: ");
        String numStr = in.readLine();
        int coluna = Integer.parseInt(numStr);

        if (field[linha][coluna] == 2) {
            System.out.print("Barco tocado!");
            field[linha][coluna] = 1;
            cont++;
        }
        if (field[linha][coluna] == -1) {
            System.out.print("Agua!");
            field[linha][coluna] = 0;
            miss--;
        }
        if (cont == 14) {

            System.out.print("Has ganado!");

        }
        if (miss==0){
            System.out.print("GAME OVER!");
        }

    } catch (Exception e) {
        e.printStackTrace();

    }
}

// comprueba se o barco cabe

public static boolean estaLivre(int fila, int coluna, int tamanho, int direcao) {
   boolean eValido = true;

switch (direcao) {
    case 0: // Vertical
        if (fila + (tamanho - 1) >= 10) //valida se existe espaço suficiente na vertical para colocar o navio
            eValido = false;
        else
            for (int i = fila; i <= fila + (tamanho - 1) && eValido; i++)
                eValido  = eValido & (field[i][coluna] == -1);
        break;

    default: // Horizontal
        if (coluna - (tamanho - 1) >= 10) 
            eValido = false;
        else
            for (int i = coluna; i >= coluna - (tamanho- 1) && eValido; i++) 
                eValido = eValido & (field[fila][i] == -1);
        break;
}
return eValido;

}

}

  • I thought the question was cleared up but you opened the question again. New doubt has arisen?

  • Yes, it was bad for the delay, but putting exactly how you posted almost always comes off the board (outofbounds Exception) or keeps putting one over the other, I will edit.

  • I made a version based on your suggestion but I wasn’t successful either...

  • In the stable methodLivre replaces "eValido = eValido & (field[i][column] == -1);" with "eValido = eValido && (field[i][column] == -1);". Two && instead of one.

  • It’s still the same, it’s very strange... I will look at all the code to make sure that nothing else is influencing the result, no matter what is placed it seems that does not change and I have created several versions of this code. Thank you for your patience and help.

  • I believe that in if(column - (size - 1) >= 10) is column + size and in i<= column + size -1, no? Even changing these signals remains the same.

  • You can see the edited answer. I think it’s working now.

Show 2 more comments

1 answer

0


Here is a sketch of what you can do to validate whether the ship can be placed on the board.

private boolean estaLivre(int fila, int coluna, int tamanho, int direcao) {

    boolean eValido = true;

    switch (direcao) {
        case 0: // horizontal
            if (coluna + (tamanho - 1) >= 10) //valida se existe espaço suficiente na horizontal para colocar o navio
                eValido = false;
            else
                for (int i = coluna; i <= coluna + (tamanho - 1) && eValido; i++)
                    eValido  = eValido && (field[fila][i] == -1);
            break;

        default: // vertical
            if (linha + (tamanho - 1) >= 10) 
                eValido = false;
            else
                for (int i = linha; i <= linha+ (tamanho - 1) && eValido; i++) 
                    eValido = eValido && (field[i][coluna] == -1);
            break;
    }
    return eValido;
 }

Explanation of the code:

  • Take as parameters the row (row) and column where you want to place the first position of the ship;
  • It also receives the direction (Vertical/Horizontal) and the size of the ship;
  • If you want to place it vertically: First validate if the board has enough space: row + (size - 1) has to be less than 10 (assume that the Indice starts at 0 and has 10 positions in total);
  • If you passed the previous test it means there is room to place the ship. It remains to check that each of the following positions is free;

The validation to position a vessel horizontally is similar.

Important detail: This code does not check whether there are "sided ships". It’s just a starting point to help you understand the logic of validation.

Like I said, your function is not working well:

public static void colocarBarco(int longitud, char orientacion) {

    Random r = new Random();
    int X;
    int Y;
    boolean livre = false;

    if (orientacion == 'H') {

        do { 
            X = r.nextInt(9);
            Y = r.nextInt(9);
            livre = estaLivre(X, Y, longitud, 0); // 0 = Horizontal            
        } while(!livre); 

        // se chegou aqui significa que encontraste uma posição para colocar o navio       
        for ( int i = Y; i <= Y + (tamanho - 1); ++i) 
            field[X][i] = 2;

    }

    if (orientacion == 'V') {
      do { 
            X = r.nextInt(9);
            Y = r.nextInt(9);
            livre = estaLivre(X, Y, longitud, 1); // 1 = Vertical            
      } while(!livre); 

      // se chegou aqui significa que encontraste uma posição para colocar o navio       
        for ( int i = X; i <= X + (tamanho - 1); ++1) 
            field[i][Y] = 2;   
    }
}

I have tested this implementation and it seems that everything is working correctly.

  • Thank you very much, that code solves the off-board part, right? As for being "leaning over" it is permissible that what you cannot do is occupy the same position...

  • Yes, it is one of the validations performed: row + (size - 1) >= 10

  • In theory when you put eValido = eValido & (field[row][i] == -1); (considering that -1 is "áqua" and 2 is "boat") should solve this problem of two boats occupying the same position, no? I was thinking about something like this too but it still doesn’t solve. I’ll break my head a little more, thanks for the help!!

  • Yes. That’s the point. Why, it didn’t work?

  • See if I’ve done anything foolish:

  • You have a problem with the placeBarco function: You are not correctly marking the positions occupied by the ships. You keep dialing the same: field[X][Y] = 2;

  • I thought that by putting while(!free) (while there is not a correct position ) and using the Random again, this problem is solved...

  • I updated my answer with ideas to change your function placeBarco. Please try to delete your answer.

  • 1

    Removed, thank you for everything!!

  • That ++1 no for would be ++i, no?

  • I put with ++i, which seems the right and nothing different, I will ask the people of my room if someone managed to do and put here the result. Thank you

  • I just made a small change to the placeBarco method. I tested the implementation and it’s working.

  • Wonderful, I will test and look better. Thank you.

  • 1

    Yes, all right!!!! Thank you very much!!

Show 9 more comments

Browser other questions tagged

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