Jogo da velha e threads

4 respostas
M

Estou criando um joguinho da velha em java. Os jogadores podem ser:

  1. humano
  2. computador burro(escolhe aleatoriamente uma posição vazia e joga ali)
  3. agente inteligente
    criei uma interface comum a todos os jogadores, assim eu posso manipular o jogo sem me preocupar se os jogadores são agentes, humanos ou burros.
    a interface é:
    import java.awt.event.ActionEvent;
public interface Jogador extends Runnable {

public boolean efetuaJogada();

public void eventoJogador(Jogador jogador, ActionEvent evento);

}

o método efetuaJogada() é chamado pela engine do jogo, é ele que vai, não interessa como, selecionar uma das posições disponíveis e jogar nela. no caso do jogador burro, esse método escolhe uma casa livre aleatoriamente. no caso do jogador humano, esse método vai fazer a jogada aonde o jogador escolheu.

Daí em tenho, então, 3 classes que implementam essa interface: JogadorBurro, JogadorHumano e, ainda não implementada, JogadorAgente.

O método eventoJogador é chamado em ambos os jogadores(o X e o O) sempre que vc clica em uma das posições do jogo(o tabuleiro do jogo da velha é representado por 9 JButtons, dispostos como em uma matriz 3x3). O parametro jogador é uma referencia ao objeto que representa o jogador atual no momento em que houve a ação, e o parametro evento é o ActionEvent gerado quando  ação de clique em um desses 9 JButtons.

Quando vc inicia uma nova partida, é rodado um algoritimo assim:
for (int i = 0; i < 9; ++i) {
 jogador[jogadorAtual].efetuaJogada(); /* os dois jogadores estão armazenados em um array de duas posições, e há uma variavel inteira chamada jogadorAtual que indica o indice do jogador que possui a vez de jogar */
 if (jogadorAtual == 0)
  jogadorAtual = 1;
 else
  jogadorAtual = 0;
}
sempre que é chamado o método efetuaJogada() do Jogador, é verificado se ocorreu essa vitória. se ocorreu, esse laço for aí de cima é interrompido.

Bom, toda essa enrolação até agora foi necessária para descrever a minha atual situação, para que assim haja a possibilidade de me indicarem uma solução. Agora vamos ao meu problema:
No jogador humano… no método efetuaJogada(), esse método só pode retornar depois que duas váriaveis que existem nessa classe, chamadas x e y(ambas são int) forem preenchidas. Esse preenchimento ocorre no método eventoJogador(), que vai analizar qual posição o usuario clicou e ver se há possibilidade de jogar ali(verifica se a posição está vazia). se houver possibilidade, ele preenche as tais variáveis x e y com as coordenadas adequadas. Aí então o método efetuaJogada(), que estava esperando, vai estar apto a finalmente efetuar a jogada.
no método efetuaJogada(), eu fiz assim para implementar essa espera:
while (x == -1); // usem -1 para indicar q a variável nao está preenchida
mas aí toda a execução ficou parada nesse ponto, nao era possivel clicar nos botões, consequentemente, nao seria gerado o ActionEvent, consequentemente nao seria chamado o método eventoJogador(), e assim o programa continuaria parado.
Foi então que pensei em usar threads(é por isso que a interface Jogador está estendendo a interface Runnable), para que apenas a thread do jogador ficasse parada esperando, mas o resto do programa poderia continuar. mas ainda assim nao funcionou.
será que alguém pode me dar uma ideia de como resolver isso?

4 Respostas

M

Cara sinceramento acho que vc está complicando seu algoritmo! Não vi necessidade nenhuma em colocar threads para o jogado! Afinal cada um joga separadamente! Uma hora é um jogador que joga outra hora é o outro.

Seria mais simples vc reestruturar seu algoritmo de outra forma, tipo assim:

Um listener para captar os clicks! depois dos clicks captados a posição seria validada! e ai vc chamaria ou não a função jogar que se encubiria apenas de marcar no tabuleiro! Quando o jogador fosse o computador a funcao jogar não seria chamada via click do mouse! mas sim pelo algoritmo inteligente!

O seu problema está na modelagem do seu sistema! Reestruture-o melhor!

M

eu tentei fazer sem threads, nao rolou.
eu imagino q, como a interface do jogo vai rodar ao mesmo tempo em que o objeto Jogador tem q ficar parado esperando, então achei necessário o uso de threads.
essa forma que vc falou, é mais ou menos assim que eu sempre usei qnd eu queria criar um jogo da velha em alguma linguagem. mas quero tentar nao fazer assim, pois quero que a engine(acho q engine é um termo mto pesado pra um simples jogo da velha hehehe) dê um tratamento igual para qq jogador, independente se o jogador é humano ou é computador. desta forma, se eu quiser futuramente adicionar um outro tipo de jogador, basta criar uma classe para ele que implemente a interface Jogador, adicionar a referencia a ela na engine, e pronto.

L

Não entendi sobre o tratamento igual para o humano ou o computador. Veja bem, repare que um jogo de xadrez para computador, você joga e na vez do computador ele já responde a jogada imediatamente a você, não é necessário um tratamento igual. O computador só precisa o tempo de processar a jogada, o que é relativamente muito rápido, por isso eu concordo com o maxwell_monteiro de que você precisa reestruturar o seu sistema e não usar threads.

M

eu poderia mto bem fazer:

inicio
se tipoJogador1 = humano então {
 espera usuário indicar a sua jogada
 enquanto a jogada nao for valida
  espera usuario indicar a sua jogada
 efetua a jogada indicada pelo usuário
}
senao, se tipoJogador1 = computador então {
 sorteia uma jogada
 enquanto a jogada nao for valida
  sorteia uma jogada
 efetua a jogada sorteada
}
se tipoJogador2 = humano então {
 espera usuário indicar a sua jogada
 enquanto a jogada nao for valida
  espera usuario indicar a sua jogada
 efetua a jogada indicada pelo usuário
}
senao, se tipoJogador2 = computador então {
 sorteia uma jogada
 enquanto a jogada nao for valida
  sorteia uma jogada
 efetua a jogada sorteada
}
se o jogo nao terminou entao
 salte para 'inicio'

vê? eu tenho que ficar vendo qual o tipo do jogador(humano, computador, …), e fazer um tratamento especifico para cada tipo.

eu fiz o jogo do jeito q eu indiquei, pois assim nao me interessa nem um pouco o tipo dos jogadores… desde que o jogador seja algo que implemente a interface Jogador, eu espero que o método efetuaJogada() vai se encarregar de criar uma jogada(seja a jogada q o usuario indicou, ou uma jogada sorteada), verificar se a jogada é legal, etc.
pra um simples jogo da velha, isso n vai fazer diferença… mas acho que é bom ir treinando essa abordagem, pois em sistemas mais complexos isso pode facilitar e mto a inclusão de coisas novas no sistema.

Criado 12 de janeiro de 2005
Ultima resposta 12 de jan. de 2005
Respostas 4
Participantes 3