12
I don’t know if this is allowed here on the site, so in case I’m breaking any rules let me know!
I recently started learning the JAVA language. I made a naval battle game (human x computer) using everything I have learned so far and would like to hear opinions of more experienced programmers on the game in order to improve my knowledge.
Some points like what would you have done differently? How would you optimize existing code? I made some redundancy or wrote more than necessary?
How I thought the game schedule?
I created two arrays 5x5. One stores the game board. It starts with the default value of 0 for all elements. With one method, I draw three of these elements, which will represent the position of the boats to be sunk. To them I assign the value 1. The other array stores the positions where the player fired, 0 symbolizes an area where it has not yet attacked and 1 an area where it attacked.
To display the board, I cross the two arrays in a check. Where it has not yet attacked, it is listed as "~", where it was attacked and there is no ship as "*" and where it attacked and sank a ship as "X". I created a method so that at each turn a hint is displayed informing if the amount of existing ships in the row and column of the last shot performed.
Code:
Battalanaval.java
package batalhanaval;
import java.util.Scanner;
public class BatalhaNaval
{
public static void main(String[] args)
{
Scanner entrada = new Scanner(System.in);
Tabuleiro tab = new Tabuleiro();
char option; //Opção do menu principal
do
{
showMenu();
option = entrada.next().charAt(0);
System.out.println("\n\n");
switch(option)
{
case '1': //Novo jogo
{
initGame(entrada, tab);
break;
}
case '2':
{
System.out.println("O seu objetivo no jogo é afundar os 3 navios inimigos que encontram-se no seu litoral.\n"
+ "Para fazer um disparo, informe a posição(linha e coluna) do seu mapa na qual deseja lançar o míssel.\n"
+ "O símbolo ~ indica uma área ainda não conhecida.\n"
+ "O símbolo * indica uma área na qual você disparou e não havia nenhum navio.\n"
+ "O símbolo X indica uma área onde você afundou um navio inimigo.\n"
+ "A cada disparo realizado você receberá uma dica informando se há navios na linha e na coluna nas quais você realizou o disparo.");
break;
}
case '3': //Recorde
{
if(tab.recorde == 1000)
{
System.out.println("<Recorde atual: nenhum>");
}
else
{
System.out.println("<Recorde atual: " + tab.recorde + " turnos>");
}
break;
}
case '4':
{
System.out.println("Finalizando...");
break;
}
default:
{
System.out.println("Opção inválida!");
}
}
System.out.println("\n");
}while(option != '4');
}
//Método que retorna true caso a String seja um número inteiro
public static boolean isInt(String str)
{
try
{
Integer.parseInt(str.trim());
return true;
}
catch (NumberFormatException ex)
{
return false;
}
}
//Main menu
public static void showMenu()
{
System.out.println("Bem vindo ao jogo <Batalha Naval>!!! (Criado por Talendar)\nEscolha uma opção:");
System.out.println("1 - Novo jogo");
System.out.println("2 - Tutorial");
System.out.println("3 - Recorde");
System.out.println("4 - Sair");
}
//Jogo
public static void initGame(Scanner entrada, Tabuleiro tab)
{
String linha = ""; //As variáveis linha e coluna foram criadas como String para poderem ser submetidas a checagem do método isInt(str) localizado abaixo.
String coluna = "";
tab.initTab();
tab.initShips();
do
{
System.out.println("\n");
//Exibe a dica a partir do segundo turno
if(tab.turno > 1)
{
tab.dica(Integer.parseInt(linha), Integer.parseInt(coluna));
}
System.out.println();
//Exibe o tabuleiro em seu estado atual
tab.printTab();
//Pede a linha
System.out.print("Linha:");
linha = entrada.next();
while(!isInt(linha))
{
System.out.println("Apenas números inteiros de 1 a 5!\nLinha:");
linha = entrada.next();
}
while(Integer.parseInt(linha) < 1 || Integer.parseInt(linha) > 5)
{
System.out.println("Apenas números inteiros de 1 a 5!\nLinha:");
linha = entrada.next();
}
//Pede a coluna
System.out.print("Coluna:");
coluna = entrada.next();
while(!isInt(coluna))
{
System.out.println("Apenas números inteiros de 1 a 5!\nColuna:");
coluna = entrada.next();
}
while(Integer.parseInt(coluna) < 1 || Integer.parseInt(coluna) > 5)
{
System.out.println("Apenas números inteiros de 1 a 5!\nColuna:");
coluna = entrada.next();
}
System.out.println("\n\n");
//Tiro
tab.tiro(Integer.parseInt(linha), Integer.parseInt(coluna));
System.out.println();
}while(tab.acertos != 3);
System.out.println("\nVOCÊ DERROTOU O INIMIGO!!!! Turnos: " + tab.turno);
if(tab.turno < tab.recorde)
{
tab.recorde = tab.turno;
System.out.println("\nNOVO RECORDE (" + tab.recorde + ")!!!!");
}
}
}
Java board.
/* Água não descoberta(~)
Água vazia(*): 0
Navio(X): 1
*/
package batalhanaval;
import java.util.Random;
public class Tabuleiro
{
int turno = 1; //Turno em questão
int acertos = 0; //Armazena o número de acertos
int recorde = 1000; //Armazena o recorde
int[][] tab = new int[5][5]; //Tabuleiro
int[][] tiros = new int[5][5]; //Armazeana as posições dos tiros dados: 0 para área desconhecida e 1 para área onde se atirou.
// Inicia o tabuleiro com o valor padrão 0
public void initTab()
{
acertos = 0;
turno = 1;
for(int[] i: tab)
{
for(int j = 0; j < i.length; j++)
{
i[j] = 0;
}
}
}
//Sorteia os navios
public void initShips()
{
Random rand = new Random();
int i; //Linha
int j; //Coluna
for(int n = 0; n < 3; n++)
{
do
{
i = rand.nextInt(5);
j = rand.nextInt(5);
}while(tab[i][j] != 0);
tab[i][j] = 1;
}
}
//Mostra o tabuleiro de inteiros
public void printTabInt()
{
System.out.print(" (1) (2) (3) (4) (5)\n\n");
for(int i = 0; i < tab.length; i++)
{
System.out.print("("+ (i+1) + ") ");
for(int j = 0; j < tab[i].length; j++)
{
System.out.print(" "+tab[i][j]+" ");
}
System.out.println("\n");
}
}
//Mostra o tabuleiro de jogo
public void printTab()
{
System.out.print(" (1) (2) (3) (4) (5)\n\n");
for(int i = 0; i < tab.length; i++)
{
System.out.print("("+ (i+1) + ") ");
for(int j = 0; j < tab[i].length; j++)
{
if(tiros[i][j] == 1)
{
if(tab[i][j] == 1)
{
System.out.print(" X ");
}
else
{
System.out.print(" * ");
}
}
else
{
System.out.print(" ~ ");
}
}
System.out.println("\n");
}
}
//Tiro
public void tiro(int linha, int coluna)
{
if(tiros[linha-1][coluna-1] == 0) //Checa se já foi dado tiro na posição fornecida
{
tiros[linha-1][coluna-1] = 1; //Muda o valor da posição fornecida para que conste como uma área atirada
if(tab[linha-1][coluna-1] == 1) //Checa se há um navio na posição fornecida
{
System.out.println("Você afundou um navio inimigo!!!");
acertos++; //Aumenta +1 em acertos
}
else
{
System.out.println("Você atingiu a água...");
}
turno++; //Avança o turno
}
else
{
System.out.println("Você já atirou nessa posição!");
}
}
//Dica: informa o turno e se há alguma navio na linha e na coluna do último tiro disparado
public void dica(int linha, int coluna)
{
System.out.println("Turno: " + turno);
int countL = 0;
for(int i: tab[linha-1])
{
if(i == 1)
{
countL++;
}
}
System.out.println("Dica: há " + countL + " navio(s) na linha " + linha);
int countC = 0;
for(int[] i: tab)
{
if(i[coluna-1] == 1)
{
countC++;
}
}
System.out.println(" há " + countC + " navio(s) na coluna " + coluna);
}
}
If you can rewrite the question in English, I suggest moving it to http:/codereview.stackexchange.com, this site was made with the purpose of reviewing codes in the questions. You can also ask questions about something specific in relation to Stackoverflow performance (en, es, en, jp, etc)
– Klaider
Or you can wait to see if anyone can help, since the question is totally within the rules and scope of this site. The text could be more organized to favor those who try to help. Separating each part in a paragraph would help, but you could put yourself in the shoes of anyone who would help in a code that he’s never seen and try to pass on the information in a better way.
– Maniero
I agree with @bigown: your question is part of the scope of the site. It’s just that it’s hard to answer objectively. You mention "optimization" (which, by principle, I understand "performance"), but your game is pretty simple and doesn’t seem to have any serious performance issues. About how you implemented it, it is correct and serves you your need current.
– Luiz Vieira
Then you ask if someone would have done something different. Possibly. But a question that is perhaps more appropriate would be: how to make this code easier to evolve? (to include vessels with different shapes of only one cell, for example). Then the question ceases to be so opinionated, but it is still broad. I would start by representing each ship by a class and implement in that class the detection of "collision" (whether a shot hit or not). It can be a good exercise for you, and maybe even generate other questions from you here on the site. :)
– Luiz Vieira