Bom, tentar ajustar o seu código pode ser complicado, mas pode ver se o Ofidomundo te ajuda, se você enviar.
O que posso fazer é sugerir uma alternativa, de como eu faria isso.
O tabuleiro eu faria criando uma classe que estendesse JPanel, sobrescrevendo ao menos o método paintComponent pra fazer o desenho do tabuleiro, ao invés de JLabels. Com dois loops for (um pra linhas e outro pra colunas), é possível desenhar um tabuleiro facilmente.
Esse JPanel poderia receber o evento mouseCliked ou mousePressed, pra saber que posição foi clicada e o que fazer: inserir o um navio, por exemplo. Internamente, esse tabuleiro pode ser armazenado numa matriz de inteiros por exemplo, em que 1 indica posição ocupada e zero uma posição livre (água).
Exemplo:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class ExemploTabuleiro extends JFrame{
public static int TAMANHO = 20;
private int[][] matrizTabuleiro = new int[10][10];
public ExemploTabuleiro(){
super("Exemplo");
setExtendedState(JFrame.MAXIMIZED_BOTH);
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(500, 500));
setSize(getPreferredSize());
PainelTabuleiro tb = new PainelTabuleiro();
getContentPane().add(tb, BorderLayout.CENTER);
for (int i = 0; i < matrizTabuleiro.length; i++){
for (int j = 0; j < matrizTabuleiro[i].length; j++){
matrizTabuleiro[i][j] = 0;
}
}
}
public static void main(String[] args){
java.awt.EventQueue.invokeLater(() -> {
ExemploTabuleiro e = new ExemploTabuleiro();
e.setVisible(true);
});
}
class PainelTabuleiro extends JPanel{
public PainelTabuleiro(){
// adiciona o mouselistener
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
tratarClique(me.getX(), me.getY());
}
});
}
private void tratarClique(int x, int y){
if (x < 100 || y < 100){
return;
}
// verifica se o clique foi na área de desenho
int cx = (x - 100) / ExemploTabuleiro.TAMANHO;
int cy = (y - 100) / ExemploTabuleiro.TAMANHO;
// verifica se foi numa posição válida
if (cx >= 0 && cx < matrizTabuleiro.length &&
cy >= 0 && cy < matrizTabuleiro[1].length){
// troca o valor na matriz do tabuleiro
if (matrizTabuleiro[cx][cy] == 0){
matrizTabuleiro[cx][cy] = 1;
}else{
matrizTabuleiro[cx][cy] = 0;
}
}
// força o painel a redesenhar/atualizar
this.repaint();
}
@Override
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g.create();
// desenha o tabuleiro
for (int i = 0; i < matrizTabuleiro.length; i++){
for (int j = 0; j < matrizTabuleiro[i].length; j++){
// muda a cor pra desenhar se é agua ou não
if(matrizTabuleiro[i][j] == 0){
g2.setColor(Color.BLUE);
}else{
g2.setColor(Color.YELLOW);
}
// desenha retangulos de 40x40, a 100 pixels da borda
g2.fillRect(
i * ExemploTabuleiro.TAMANHO + 100,
j * ExemploTabuleiro.TAMANHO + 100,
ExemploTabuleiro.TAMANHO,
ExemploTabuleiro.TAMANHO);
// linhas divisorias
g2.setColor(Color.WHITE);
g2.drawRect(
i * ExemploTabuleiro.TAMANHO + 100,
j * ExemploTabuleiro.TAMANHO + 100,
ExemploTabuleiro.TAMANHO,
ExemploTabuleiro.TAMANHO);
}
}
g2.dispose();
}
}
}
Obs: pode haver alguns problemas, foi um código rápido.
Durante a partida, você pode armazenar qual o turno atual (do jogador ou do adversário) e reagir de acordo. Ex: na vez do adversário, os cliques do jogador são ignorados.
O bom é que com Java2D você consegue desenhar o que quiser: imagens, linhas retângulos, elipses, adicionar alguns efeitos, etc. E não depende de muitos componentes visuais do Swing. Veja mais aqui: http://pontov.com.br/site/java/48-java2d/93-uma-visao-rapida-sobre-o-java-2d
Abraço.