BatalhaNaval GUI

Boa noite,
estou fazendo um jogo de Batalha Naval com interface gráfica.
O tabuleiro está montado e os navios da IA estão posicionados aleatoriamente, mas não consigo posicionar os navios do player com o mouse.
Eu fiz um antes que usava JOptionPane para pegar a linha e a coluna que o player queria para posicionar o navio, mas assim fica muito ruim.

Quando boto no método pra pegar a linha e a coluna do botão selecionado, ele da um nullPointerException.

Consequentemente, o mesmo acontece no método para atirar…

Alguém pode me ajudar?

Como não temos seu código aqui, fica extremamente difícil saber o motivo do nullPointerException. Se ele não for muito extenso, poderia postá-lo?

Ou ao menos explique qual era a sua ideia de como fazer isso, para que possamos sugerir algo em cima do seu plano.

Particularmente, eu não usaria botões para isso, mas um JPanel com desenho personalizado, usando Java2D. Para saber em qual parte o usuário clicou, basta usar um mouselistener, pegando as coordenadas X e Y do evento mousepressed, por exemplo. O tabuleiro poderia ser armazenado internamente no programa, em uma matriz, e o desenho seria feito a partir de imagens representando os pedaços das embarcações.

Abraço.

Só conseguirei postar o código amanhã, mas fiz mais ou menos do jeito que você falou.
“Botão” foi só um mode de falar. Fiz uma matriz de “botões” e todos com evento de mouselistener. Porém, quando eu tento pegar as coordenadas, ele dá NPE, porque não espera o clique.
Quando eu clico em “Novo Jogo”, ele posiciona os navios da IA e entra no loop pra posicionar os navios do player, mas, nesse momento, X e Y ainda estão vazios, ai ele da NPE.
Não sei se expliquei muito bem. Caso tenha ficado alguma dúvida, amanhã eu posto uma parte do código, já que completo não tem como.

Obrigado pela força!

Abraço.

Você está tentando acessar membros de uma variável que não foi inicializada

Bom dia…
Todas as variáveis estão inicializadas.
Quando li seu post, pensei: “Será que fiz isso?”
Mas fui verificar e vi que estão inicializadas.

A linha selecionada:
Botao btn = new Botao()
selecionado //clique do mouse na classe Botao
getLinha() //auto explicativo

Bom dia, em cima da linha 38, faz assim:

if(btn == null){
System.out.prinln("btn nulo");
}
if(btn.selecionado == null){
System.out.prinln("selecionado nulo");
}

Ai você tira a suas próprias conclusoes.

PS: Se Btn foi inicializado, então diria que selecionado ta nulo então

Bom dia Mike, obrigado pela resposta.
Botei os if’s e ele fala que o “selecionado” está null. Como ele é criado dentro da classe Botao, realmente não inicializei.

Quando coloco:
Botao selecionado = new Botao();
Ele gera StackOverflowError

Tentei agora sem o selecionado:
btn.getLinha();
Mas aí ele pega sempre a posição [0][0] do tabuleiro e entra em loop infinito.

O JOptionPane foi só um teste para ver se os “botões” estavam funcionando.

Alguém me ajuda?
Qualquer coisa posto outras partes do código aqui.

O problema não parece estar aí, essa exceção geralmente acontece quando há recursão.

Por que pega sempre a posição [0][0]?

Boa tarde diego12,
obrigado pela resposta.

Porque o programa não “espera” o clique do mouse, aí ele vem com os valores que eu inicializei as variáveis ‘linha’ e ‘coluna’.
Quando entra no método ‘posicionaNavio()’, ele já entra direto no loop e não deixa com que eu selecione um ‘botão’ onde quero posicionar o navio.
Essa é a minha dúvida, como fazer para ele ‘esperar’ o clique.

    public void posicionaPlayer() {

		int navios = 1, orientacao = 0, linha = 0, coluna = 0;
		
		while(navios <= 5) {
			
			navio = navio.constroiNavio(navios);
			
			JOptionPane.showMessageDialog(
					null, "Posicione o " + navio.getNome() + "."
						+ "\nEsse navio ocupa " + navio.getTamanho() + " espaços."
						+ "\nEscolha o primeiro espaço que ele irá ocupar...");
		
			Object[] opcoes = {"Horizontal", "Vertical"};
			
			orientacao = JOptionPane.showOptionDialog(null,
								"Escolha a orientação do navio",
								"Escolha",
								JOptionPane.YES_NO_CANCEL_OPTION,
								JOptionPane.QUESTION_MESSAGE,
								null,
								opcoes,
								opcoes[1]);
				
			linha = btn.getLinha();
			coluna = btn.getColuna();
			
			if(navio.getTamanho() != 0) {

				if(orientacao < 2) {
					
					if(linha < 10) {
					
						if(coluna < 10) {
							
							if(navio.posicionaNavio("C", orientacao, linha, coluna, navio, tabuleiroPlayer)) {

								navios++;
							}
						}
						else
							posicionaPlayer();
					}
					else
						posicionaPlayer();
				}
				else
					posicionaPlayer();
			}
			else
				posicionaPlayer();
		}
		
		navio.posicionaNavio("P", orientacao, linha, coluna, navio, tabuleiroPlayer);
	}

Coloquei pra pegar a orientação (horizontal ou vertical) pelo JOptionPane pra ver se facilitava, mas a única coisa que faz é colocar o primeiro navio, na posição 0,0.

Dei uma lida no link que você botou. Se eu entendi bem, tá dando o StackOverFlowError pq eu instanciei o ‘selecionado’ dentro da classe Botão?

coloca algum tipo de wait();

Fala Ofidomundo,[quote=“Ofidomundo, post:11, topic:372144, full:true”]
coloca algum tipo de wait();
[/quote]

Já procurei métodos parecidos mas não achei. Sabe de algum?

Pelo que me lembro o JOP retorna um valor, põe num while vaziu que resolve eu acho

Eu tenho uma BatalhaNaval pronta que faz tudo por JOptionPane.
Eu digito linha e coluna tanto pra colocar os navios quanto para atirar, mas não é o que eu quero.
Se eu não me engano, JOptionPane não pega click.

Sobe pro Git que eu olho amanhã às 8 pdc? Sai da empresa agr

De onde é chamado esse posicionaPlayer()? É dentro de algum evento de clique? Não acho que é uma boa ideia você colocar um while dentro de um evento da interface (mouseClick, etc).

O que é essa classe Botao? Ela deriva de algum componente visual (ex: Jbutton) ou é uma classe mais simples?

Abraço.

Não, o problema seria a recursão, quando chama um mesmo método infinitas vezes, exemplo:

void posicionaPlayer(){
  posicionaPlayer();
}

Ou seja, provavelmente esta caindo no “else posicionaPlayer()” até acontecer esse erro.

Sugestão, remova todos os “else posicionaPlayer()”, coloque um System.out.print para cada if verificando se está certo, como exemplo abaixo:

System.out.println("Coluna: " + coluna);
if(coluna < 10) {
	boolean posicionouNavioC = navio.posicionaNavio("C", orientacao, linha, coluna, navio, tabuleiroPlayer);
	System.out.println("Posicionou navio C? " + posicionouNavioC);
	if(posicionouNavioC) {
		navios++;
	}
}

Fala TerraSkilll, valeu pela atenção…

A classe Botao que eu criei estende JLabel, foi a forma que eu encontrei pra fazer o tabuleiro.
O posicionaPlayer() é chamado que eu clico em “Novo Jogo” no menu.
O posicionaPlayer() ta dentro da classe player, só a chamada do método tá dentro do evento.

Fala Diego, obrigado mais uma vez.
Amanhã eu vou tirar os else’s para ver, mas acho que só resolveria o problema do StackOverFlow. Não resolveria o problema do click. Certo?
Mas vou colocar os Sysout pra ver até onde está indo.

1 curtida

@IghorSantiago se quiser colocar o codigo em algum repositório para eu te ajudar fique a vontade