SlideShare uma empresa Scribd logo
1 de 19
Jogos de tabuleiro
Multiplayer
Marco Antonio
Apresentação
• Jogos multiplayer fazem uso de threads para
gerenciar múltiplas tarefas, além de sockets
para envio de pacotes entre computadores.
• Na aplicação a seguir temos vários exemplos
de como isso pode ser implementado.
DadosDeConexao
package com.javagames.tabuleiro;
/**
* Armazena os dados de conexao da aplicacao
*
* Porta local - utilizada para o ServerSocket
* Porta remota - utilizada para o socket cliente
* Servidor - nome/ip da maquina remota
* O servidor + porta remota sao utilizados para enviar os dados a cada jogada
* Nao e necessario indicar o nome/ip da maquina local
* Nome do usuario - utilizado para personalizar sua partida
*
* @author marcoreis
*
*/
public class DadosDeConexao {
private int portaLocal;
private int portaRemota;
private String servidor;
private String nomeDoUsuario;
{...Metodos de acesso...}
}
UtilComunicacao
package com.javagames.tabuleiro;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Transporta os dados entre duas maquinas utilizando socket
* Deve ser atualizada para suportar diferentes tipos de dados
* Os metodos tem suporte apenas a Map
*
* @author marcoreis
*
*/
public class UtilComunicacao {
/**
* Abre um socket entre o cliente e o servidor
* O servidor deve estar esperando (accept) esta requisicao
*
* @param dadosDeConexao Nome do servidor remoto e porta
* @param mapa - dados que serao enviados
*/
public void enviaDadosParaComputadorRemoto(DadosDeConexao dadosDeConexao,
Map mapa) {
try {
Socket socket = new Socket(dadosDeConexao.getServidor(), dadosDeConexao
.getPortaRemota());
OutputStream outSocket = socket.getOutputStream();
ObjectOutputStream saida = new ObjectOutputStream(outSocket);
saida.writeObject(mapa);
saida.close();
outSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
UtilComunicacao
/**
* Sincroniza dois mapas
* Por definicao, um mapa nao tem repeticao de chaves (keys)
* Isso garante que nao havera posicoes repetidas
*
* @param mapaRecuperado
* @return Mapa sincronizado
*/
public Map sincronizaMapas(Map<String, String> mapaRecuperado) {
Map mapa = new HashMap();
for (Object o : mapaRecuperado.keySet()) {
mapa.put(o.toString(), mapaRecuperado.get(o));
}
return mapa;
}
UtilComunicacao
/**
*
* E o outro lado do metodo enviaDadosParaComputadorRemoto
* Enquanto o primeiro esta no cliente, este esta no servidor
* Converte os dadso em Map, ou seja, nao suporta outros tipos de dados
*
* @param socket Conexao aberta entre cliente e servidor
* @return Mapa enviado
*/
public Map extrairMapa(Socket socket) {
try {
InputStream dados = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(dados);
Object o = ois.readObject();
Map<String, String> mapaRecuperado = (Map<String, String>) o;
return mapaRecuperado;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
JogoDaVelha
package com.javagames.tabuleiro;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import com.javagames.util.*;
/**
* Jogo da velha multiplayer
* Utiliza sockets para comunicar as jogadas entre jogadores
*
* @author marcoreis
*
*/
@SuppressWarnings("serial")
public class JogoDaVelha extends JFrame {
private static final int QUANTIDADE_DE_CASAS = 3;
private int ALTURA = 350;
private int LARGURA = 300;
private Map<String, String> mapaDeCasas;
private String jogadorAtual;
private Point pontoClicado;
private DadosDeConexao dadosDeConexao;
private UtilComunicacao utilComunicacao;
JogoDaVelha
/**
* MŽtodo construtor
* Inicializacao dos parametros obrigatorios
*/
public JogoDaVelha() {
setSize(LARGURA, ALTURA);
setBackground(Color.BLUE);
adicionaEventoCliqueDoMouse();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
/**
* Chama o construtor padrao
* @param dados - Dados de conexao informado pelo usuario
*/
public JogoDaVelha(DadosDeConexao dados) {
this();
this.dadosDeConexao = dados;
setTitle("Bem-vindo, " + dados.getNomeDoUsuario());
}
/**
* Adicionar listener para cliques do mouse
*/
private void adicionaEventoCliqueDoMouse() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
eventoCliqueDoMouse(e);
}
});
}
JogoDaVelha
/**
* Algoritmo a ser implementado
* @return Se o jogador atual ganhou ou nao
*/
private boolean ganhou() {
try {
int contador = 0;
//Verifica se ganhou na vertical
for (int i = 0; i < 3; i++) {
//Verifica se as posicoes estao ocupadas pelo jogador atual
for (int j = 0; j < 3; j++) {
if (getMapaDeCasas().get(i + "," + j) != null && getMapaDeCasas().get(i + "," + j).equals(jogadorAtual)) {
contador++;
}
//Caso tenha as tres posicoes ocupadas, retorna true, jogador atual ganhou
if (contador == 3) {
return true;
}
}
//Quando muda de coluna, zera o contador
contador = 0;
}
} catch (Exception e) {
}
return false;
}
JogoDaVelha
/**
* Calcula a celular que deve ser utilizada a partir do ponto clicado na tela
* @param pontoClicado
*/
private void marcaPosicao(Point pontoClicado) {
int indiceX = pontoClicado.x / (getTamanhoDaCasaX());
int indiceY = pontoClicado.y / (getTamanhoDaCasaY());
String posicao = indiceX + "," + indiceY;
getMapaDeCasas().put(posicao, jogadorAtual);
//Envia os dados para a thread do oponente, que esta esperando
getUtilComunicacao().enviaDadosParaComputadorRemoto(dadosDeConexao, getMapaDeCasas());
setTitle(dadosDeConexao.getNomeDoUsuario() + ", voce jogou. Aguarde.");
}
/**
*
* @return {@link}
*/
private UtilComunicacao getUtilComunicacao() {
if (utilComunicacao == null) {
utilComunicacao = new UtilComunicacao();
}
return utilComunicacao;
}
JogoDaVelha
/**
*
* @param pontoClicado Coordenadas do clique do usuario
* @return Se o quadrante clicado est‡ ou nao ocupado
*/
private boolean posicaoJahMarcada(Point pontoClicado) {
int indiceX = pontoClicado.x / (getTamanhoDaCasaX());
int indiceY = pontoClicado.y / (getTamanhoDaCasaY());
String posicao = indiceX + "," + indiceY;
if (getMapaDeCasas().get(posicao) != null) {
return true;
}
return false;
}
/**
* Calculo para definir o tamanho das celulas utilizadas.
* Jamais utilize valores fixos, pois isso impede a evolucao do sistema
* @return Tamanhos
*/
private int getTamanhoDaCasaY() {
return ALTURA / QUANTIDADE_DE_CASAS;
}
private int getTamanhoDaCasaX() {
return LARGURA / QUANTIDADE_DE_CASAS;
}
/**
* Desenha/redesenha a tela a cada clique
* Ou, na versao multiplayer, a cada jogada
*/
public void paint(Graphics g) {
super.paint(g);
//Vertical
g.drawLine((LARGURA / 3), 30, (LARGURA / 3), ALTURA - 10);
g.drawLine((LARGURA / 3) * 2, 30, (LARGURA / 3) * 2, ALTURA - 10);
//Horizontal
g.drawLine(10, ALTURA / 3, LARGURA - 10, ALTURA / 3);
g.drawLine(10, (ALTURA / 3) * 2, LARGURA - 10, (ALTURA / 3) * 2);
imprimeMapaNoTabuleiro();
//
}

JogoDaVelha

/**
* Imprime o mapa no tabuleiro
* A chave (key) do mapa esta no formato 'x,y'
* Por isso temos o stringtokenizer que recupera cada valor separado pela ','
* Em seguida le cada posicao marcada do mapa, recuperando o jogador marcado
* Por fim, desenha na celula x,y a imagem respectiva
* O loop le todos os elementos que compoe o mapa naquele momento
*
*/
public void imprimeMapaNoTabuleiro() {
for (Object o : getMapaDeCasas().keySet()) {
//o (formato x,y)
try {
StringTokenizer s = new StringTokenizer(o.toString(), ",");
int posicaoX = new Integer(s.nextToken()) * getTamanhoDaCasaX() + 30;
int posicaoY = new Integer(s.nextToken()) * getTamanhoDaCasaY() + 50;
//
String jogador = getMapaDeCasas().get(o);
desenhaIcone(posicaoX, posicaoY, jogador);
//
} catch (Exception e) {
System.out.println(e);
}
}
}
JogoDaVelha
/**
* Desenha a respectiva imagem dada uma posicao e um jogador
* @param posicaoX
* @param posicaoY
* @param jogador
*/
private void desenhaIcone(int posicaoX, int posicaoY, String jogador) {
Graphics g = getGraphics();
if (jogador.equals("X")) {
g.drawImage(UtilImagem.getImagem("xis.png"), posicaoX, posicaoY, this);
} else {
g.drawImage(UtilImagem.getImagem("zero.png"), posicaoX, posicaoY, this);
}
}
/**
* Armazena todas as jogadas ate o presente instante
* @return Mapa atual
*/
public Map<String, String> getMapaDeCasas() {
if (mapaDeCasas == null) {
mapaDeCasas = new HashMap<String, String>();
}
return mapaDeCasas;
}
public void setMapaDeCasas(Map<String, String> mapaDeCasas) {
this.mapaDeCasas = mapaDeCasas;
}
JogoDaVelha
/**
* Efetua todas as operacoes referentes ao evento clique do mouse
* A cada jogada do usuario, o jogo deve aplicar todas as regras definidas
* Alem de informar se algo nao esta correto
* @param e Ponto clicado na tela
*/
private void eventoCliqueDoMouse(MouseEvent e) {
pontoClicado = e.getPoint();
defineJogador();
if (posicaoJahMarcada(pontoClicado)) {
JOptionPane.showMessageDialog(null, "Posicao ja ocupada.", "Atencao",
JOptionPane.WARNING_MESSAGE);
} else {
repaint();
marcaPosicao(pontoClicado);
}
if (ganhou()) {
JOptionPane.showMessageDialog(null, "Ganhou");
}
}
/**
* Nas duas primeiras jogadas da partida verifica quem e quem
* O primeiro jogador sera '0'
* O segundo sera 'X'
*/
private void defineJogador() {
if (getMapaDeCasas().keySet().size() == 0 && jogadorAtual == null) {
jogadorAtual = "0";
} else if (getMapaDeCasas().keySet().size() == 1 && jogadorAtual == null) {
jogadorAtual = "X";
}
}
}
ThreadJogoDaVelha
package com.javagames.tabuleiro;
import java.net.*;
import java.util.*;
public class ThreadJogoDaVelha extends Thread {
private DadosDeConexao dadosDeConexao;
private JogoDaVelha jogo;
private UtilComunicacao utilComunicacao;
/**
* Metodo construtor que exige os dados de conexao e o seu tabuleiro
*
* Esta classe gerencia as jogadas do oponente atraves do socket
* Observacao: Nao ha controle para bloquear o jogador depois do clique
* Isso permite que alguem jogue duas vezes
*
* @param jogo Tabuleiro do seu jogo
* @param dados Informacoes necessarias para conectar os tabuleiros
*/
public ThreadJogoDaVelha(JogoDaVelha jogo, DadosDeConexao dados) {
this.dadosDeConexao = dados;
this.jogo = jogo;
}
ThreadJogoDaVelha

/**
* A thread fica aguardando ate a jogada do oponente
* Apos a jogada, bloqueia a thread (accept)
* Assim que o oponente jogar, sincroniza os mapas
*
*/
@SuppressWarnings("unchecked")
public void run() {
//
while (true) {
try {
jogo.repaint();
Thread.sleep(1000);
//Aguarda jogada do oponente
//Bloqueia a thread
ServerSocket server = new ServerSocket(dadosDeConexao.getPortaLocal());
Socket socket = server.accept();
//O oponente jogou
jogo.setTitle(dadosDeConexao.getNomeDoUsuario() + ", agora Ž sua vez.");
//Processa jogada
//Recupera o mapa de jogadas do oponente
Map<String, String> mapaRecuperado = getUtilComunicacao().extrairMapa(
socket);
//Sincroniza o seu tabuleiro
Map mapaDeCasas = getUtilComunicacao().sincronizaMapas(mapaRecuperado);
jogo.setMapaDeCasas(mapaDeCasas);
jogo.imprimeMapaNoTabuleiro();
//Desbloquear os recursos apos sua utilizacao
socket.close();
server.close();
//
} catch (Exception e) {
System.out.print("...");
}
}
}
ThreadJogoDaVelha
private UtilComunicacao getUtilComunicacao() {
if (utilComunicacao == null) {
utilComunicacao = new UtilComunicacao();
}
return utilComunicacao;
}
}
Splash Screen
•

No Netbeans, crie uma tela com
os componentes indicados.

•

Inicie seu jogo e informe os
dados do oponente.

•

O botão de conectar deve iniciar
uma thread do JogoDaVelha
passando todos os dados
necessários (veja o próximo
slide).
Conexão
private void btnConectarActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_btnConectarActionPerformed
DadosDeConexao dados = new DadosDeConexao();
dados.setPortaLocal(new Integer(txtPortaLocal.getText()));
dados.setPortaRemota(new Integer(txtPortaServidor.getText()));
dados.setServidor(txtServidor.getText());
dados.setNomeDoUsuario(txtNome.getText());
JogoDaVelha jogo = new JogoDaVelha(dados);
new ThreadJogoDaVelha(jogo, dados).start();
setVisible(false);
}//GEN-LAST:event_btnConectarActionPerformed

Mais conteúdo relacionado

Destaque

Guia de lógica recreativa
Guia de  lógica recreativaGuia de  lógica recreativa
Guia de lógica recreativaXKARIN
 
Jogo da velha tabuada
Jogo da velha tabuadaJogo da velha tabuada
Jogo da velha tabuadaLucianalorab
 
CCNA 1 Routing and Switching v5.0 Chapter 10
CCNA 1 Routing and Switching v5.0 Chapter 10CCNA 1 Routing and Switching v5.0 Chapter 10
CCNA 1 Routing and Switching v5.0 Chapter 10Nil Menon
 
Apost atividades-multiplicação-e_divisão simone helen drumond
Apost  atividades-multiplicação-e_divisão simone helen drumondApost  atividades-multiplicação-e_divisão simone helen drumond
Apost atividades-multiplicação-e_divisão simone helen drumondSimoneHelenDrumond
 
JOGO DA VELHA COM FIGURAS GEOMÉTRICAS
JOGO DA VELHA COM FIGURAS GEOMÉTRICASJOGO DA VELHA COM FIGURAS GEOMÉTRICAS
JOGO DA VELHA COM FIGURAS GEOMÉTRICASMasclleide Paula
 
Portfolio PROETI CARLOS CHAGAS
Portfolio PROETI CARLOS CHAGASPortfolio PROETI CARLOS CHAGAS
Portfolio PROETI CARLOS CHAGASequipente
 
Projeto Educação em Tempo Integral na Escola
Projeto Educação em Tempo Integral na EscolaProjeto Educação em Tempo Integral na Escola
Projeto Educação em Tempo Integral na Escolaanjalylopes
 
Caderno de boas práticas tempo integral
Caderno de boas práticas tempo integralCaderno de boas práticas tempo integral
Caderno de boas práticas tempo integralPaula Pereira
 
Projeto tempo integral 2015
Projeto tempo integral 2015Projeto tempo integral 2015
Projeto tempo integral 2015Muni2015
 

Destaque (12)

Threads e sockets java
Threads e sockets javaThreads e sockets java
Threads e sockets java
 
Projeto jogo da-velha
Projeto jogo da-velhaProjeto jogo da-velha
Projeto jogo da-velha
 
Guia de lógica recreativa
Guia de  lógica recreativaGuia de  lógica recreativa
Guia de lógica recreativa
 
Jogo da velha tabuada
Jogo da velha tabuadaJogo da velha tabuada
Jogo da velha tabuada
 
CCNA 1 Routing and Switching v5.0 Chapter 10
CCNA 1 Routing and Switching v5.0 Chapter 10CCNA 1 Routing and Switching v5.0 Chapter 10
CCNA 1 Routing and Switching v5.0 Chapter 10
 
Velha da multiplicação
Velha da multiplicaçãoVelha da multiplicação
Velha da multiplicação
 
Apost atividades-multiplicação-e_divisão simone helen drumond
Apost  atividades-multiplicação-e_divisão simone helen drumondApost  atividades-multiplicação-e_divisão simone helen drumond
Apost atividades-multiplicação-e_divisão simone helen drumond
 
JOGO DA VELHA COM FIGURAS GEOMÉTRICAS
JOGO DA VELHA COM FIGURAS GEOMÉTRICASJOGO DA VELHA COM FIGURAS GEOMÉTRICAS
JOGO DA VELHA COM FIGURAS GEOMÉTRICAS
 
Portfolio PROETI CARLOS CHAGAS
Portfolio PROETI CARLOS CHAGASPortfolio PROETI CARLOS CHAGAS
Portfolio PROETI CARLOS CHAGAS
 
Projeto Educação em Tempo Integral na Escola
Projeto Educação em Tempo Integral na EscolaProjeto Educação em Tempo Integral na Escola
Projeto Educação em Tempo Integral na Escola
 
Caderno de boas práticas tempo integral
Caderno de boas práticas tempo integralCaderno de boas práticas tempo integral
Caderno de boas práticas tempo integral
 
Projeto tempo integral 2015
Projeto tempo integral 2015Projeto tempo integral 2015
Projeto tempo integral 2015
 

Semelhante a Jogo tabuleiro multiplayer

Spock Framework 2
Spock Framework 2Spock Framework 2
Spock Framework 2Ismael
 
Exercícios java 20 02
Exercícios java 20   02Exercícios java 20   02
Exercícios java 20 02julyesersantos
 
Geolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesGeolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesLuis Gustavo Almeida
 
Ubiquitous Language - Portugues
Ubiquitous Language - PortuguesUbiquitous Language - Portugues
Ubiquitous Language - PortuguesAlline Oliveira
 
JS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript FuncionalJS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript FuncionaliMasters
 
Gabarito funcoes
Gabarito funcoesGabarito funcoes
Gabarito funcoesbferes
 
Programação funcional em JavaScript: como e por quê?
Programação funcional em JavaScript: como e por quê?Programação funcional em JavaScript: como e por quê?
Programação funcional em JavaScript: como e por quê?Arthur Xavier
 
INdT Mobile Labs - Sparta
INdT Mobile Labs - SpartaINdT Mobile Labs - Sparta
INdT Mobile Labs - SpartaHeitor Carlos
 
Programação Estruturada 2 - Aula 02 - Código Fonte
Programação Estruturada 2 - Aula 02 - Código FonteProgramação Estruturada 2 - Aula 02 - Código Fonte
Programação Estruturada 2 - Aula 02 - Código Fontethomasdacosta
 
Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...
Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...
Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...INdT
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaEduardo Bregaida
 
Conexão Java 2012 - Orientação a Objetos das Galáxias
Conexão Java 2012 - Orientação a Objetos das GaláxiasConexão Java 2012 - Orientação a Objetos das Galáxias
Conexão Java 2012 - Orientação a Objetos das GaláxiasMaurício Aniche
 
Aprendendo objective c - parte 1
Aprendendo objective c - parte 1Aprendendo objective c - parte 1
Aprendendo objective c - parte 1Alamo Saravali
 
Data mapping com Groovy - Part 2
Data mapping com Groovy - Part 2Data mapping com Groovy - Part 2
Data mapping com Groovy - Part 2Jeison Barros
 
Ferramentas para desenvolvimento no blockchain Ethereum
Ferramentas para desenvolvimento no blockchain EthereumFerramentas para desenvolvimento no blockchain Ethereum
Ferramentas para desenvolvimento no blockchain EthereumOriginalMy.com
 
Como criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.jsComo criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.jsHelder da Rocha
 
Palestra Mocks - AgileBrazil 2010
Palestra Mocks - AgileBrazil 2010Palestra Mocks - AgileBrazil 2010
Palestra Mocks - AgileBrazil 2010rafaelferreira
 

Semelhante a Jogo tabuleiro multiplayer (20)

Clean code
Clean codeClean code
Clean code
 
Spock Framework 2
Spock Framework 2Spock Framework 2
Spock Framework 2
 
Sobrecarga operadores
Sobrecarga operadoresSobrecarga operadores
Sobrecarga operadores
 
Exercícios java 20 02
Exercícios java 20   02Exercícios java 20   02
Exercícios java 20 02
 
Geolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesGeolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e Routes
 
Ubiquitous Language - Portugues
Ubiquitous Language - PortuguesUbiquitous Language - Portugues
Ubiquitous Language - Portugues
 
JS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript FuncionalJS Experience 2017 - Javascript Funcional
JS Experience 2017 - Javascript Funcional
 
Gabarito funcoes
Gabarito funcoesGabarito funcoes
Gabarito funcoes
 
Programação funcional em JavaScript: como e por quê?
Programação funcional em JavaScript: como e por quê?Programação funcional em JavaScript: como e por quê?
Programação funcional em JavaScript: como e por quê?
 
apostila C++
apostila C++apostila C++
apostila C++
 
INdT Mobile Labs - Sparta
INdT Mobile Labs - SpartaINdT Mobile Labs - Sparta
INdT Mobile Labs - Sparta
 
Programação Estruturada 2 - Aula 02 - Código Fonte
Programação Estruturada 2 - Aula 02 - Código FonteProgramação Estruturada 2 - Aula 02 - Código Fonte
Programação Estruturada 2 - Aula 02 - Código Fonte
 
Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...
Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...
Thiago Valle e Heitor Repolho - Utilizando sparta para para desenvolvimento d...
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completa
 
Conexão Java 2012 - Orientação a Objetos das Galáxias
Conexão Java 2012 - Orientação a Objetos das GaláxiasConexão Java 2012 - Orientação a Objetos das Galáxias
Conexão Java 2012 - Orientação a Objetos das Galáxias
 
Aprendendo objective c - parte 1
Aprendendo objective c - parte 1Aprendendo objective c - parte 1
Aprendendo objective c - parte 1
 
Data mapping com Groovy - Part 2
Data mapping com Groovy - Part 2Data mapping com Groovy - Part 2
Data mapping com Groovy - Part 2
 
Ferramentas para desenvolvimento no blockchain Ethereum
Ferramentas para desenvolvimento no blockchain EthereumFerramentas para desenvolvimento no blockchain Ethereum
Ferramentas para desenvolvimento no blockchain Ethereum
 
Como criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.jsComo criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.js
 
Palestra Mocks - AgileBrazil 2010
Palestra Mocks - AgileBrazil 2010Palestra Mocks - AgileBrazil 2010
Palestra Mocks - AgileBrazil 2010
 

Jogo tabuleiro multiplayer

  • 2. Apresentação • Jogos multiplayer fazem uso de threads para gerenciar múltiplas tarefas, além de sockets para envio de pacotes entre computadores. • Na aplicação a seguir temos vários exemplos de como isso pode ser implementado.
  • 3. DadosDeConexao package com.javagames.tabuleiro; /** * Armazena os dados de conexao da aplicacao * * Porta local - utilizada para o ServerSocket * Porta remota - utilizada para o socket cliente * Servidor - nome/ip da maquina remota * O servidor + porta remota sao utilizados para enviar os dados a cada jogada * Nao e necessario indicar o nome/ip da maquina local * Nome do usuario - utilizado para personalizar sua partida * * @author marcoreis * */ public class DadosDeConexao { private int portaLocal; private int portaRemota; private String servidor; private String nomeDoUsuario; {...Metodos de acesso...} }
  • 4. UtilComunicacao package com.javagames.tabuleiro; import java.io.*; import java.net.*; import java.util.*; /** * Transporta os dados entre duas maquinas utilizando socket * Deve ser atualizada para suportar diferentes tipos de dados * Os metodos tem suporte apenas a Map * * @author marcoreis * */ public class UtilComunicacao { /** * Abre um socket entre o cliente e o servidor * O servidor deve estar esperando (accept) esta requisicao * * @param dadosDeConexao Nome do servidor remoto e porta * @param mapa - dados que serao enviados */ public void enviaDadosParaComputadorRemoto(DadosDeConexao dadosDeConexao, Map mapa) { try { Socket socket = new Socket(dadosDeConexao.getServidor(), dadosDeConexao .getPortaRemota()); OutputStream outSocket = socket.getOutputStream(); ObjectOutputStream saida = new ObjectOutputStream(outSocket); saida.writeObject(mapa); saida.close(); outSocket.close(); } catch (Exception e) { e.printStackTrace(); } }
  • 5. UtilComunicacao /** * Sincroniza dois mapas * Por definicao, um mapa nao tem repeticao de chaves (keys) * Isso garante que nao havera posicoes repetidas * * @param mapaRecuperado * @return Mapa sincronizado */ public Map sincronizaMapas(Map<String, String> mapaRecuperado) { Map mapa = new HashMap(); for (Object o : mapaRecuperado.keySet()) { mapa.put(o.toString(), mapaRecuperado.get(o)); } return mapa; }
  • 6. UtilComunicacao /** * * E o outro lado do metodo enviaDadosParaComputadorRemoto * Enquanto o primeiro esta no cliente, este esta no servidor * Converte os dadso em Map, ou seja, nao suporta outros tipos de dados * * @param socket Conexao aberta entre cliente e servidor * @return Mapa enviado */ public Map extrairMapa(Socket socket) { try { InputStream dados = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(dados); Object o = ois.readObject(); Map<String, String> mapaRecuperado = (Map<String, String>) o; return mapaRecuperado; } catch (Exception e) { e.printStackTrace(); return null; } } }
  • 7. JogoDaVelha package com.javagames.tabuleiro; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import com.javagames.util.*; /** * Jogo da velha multiplayer * Utiliza sockets para comunicar as jogadas entre jogadores * * @author marcoreis * */ @SuppressWarnings("serial") public class JogoDaVelha extends JFrame { private static final int QUANTIDADE_DE_CASAS = 3; private int ALTURA = 350; private int LARGURA = 300; private Map<String, String> mapaDeCasas; private String jogadorAtual; private Point pontoClicado; private DadosDeConexao dadosDeConexao; private UtilComunicacao utilComunicacao;
  • 8. JogoDaVelha /** * MŽtodo construtor * Inicializacao dos parametros obrigatorios */ public JogoDaVelha() { setSize(LARGURA, ALTURA); setBackground(Color.BLUE); adicionaEventoCliqueDoMouse(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } /** * Chama o construtor padrao * @param dados - Dados de conexao informado pelo usuario */ public JogoDaVelha(DadosDeConexao dados) { this(); this.dadosDeConexao = dados; setTitle("Bem-vindo, " + dados.getNomeDoUsuario()); } /** * Adicionar listener para cliques do mouse */ private void adicionaEventoCliqueDoMouse() { addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { eventoCliqueDoMouse(e); } }); }
  • 9. JogoDaVelha /** * Algoritmo a ser implementado * @return Se o jogador atual ganhou ou nao */ private boolean ganhou() { try { int contador = 0; //Verifica se ganhou na vertical for (int i = 0; i < 3; i++) { //Verifica se as posicoes estao ocupadas pelo jogador atual for (int j = 0; j < 3; j++) { if (getMapaDeCasas().get(i + "," + j) != null && getMapaDeCasas().get(i + "," + j).equals(jogadorAtual)) { contador++; } //Caso tenha as tres posicoes ocupadas, retorna true, jogador atual ganhou if (contador == 3) { return true; } } //Quando muda de coluna, zera o contador contador = 0; } } catch (Exception e) { } return false; }
  • 10. JogoDaVelha /** * Calcula a celular que deve ser utilizada a partir do ponto clicado na tela * @param pontoClicado */ private void marcaPosicao(Point pontoClicado) { int indiceX = pontoClicado.x / (getTamanhoDaCasaX()); int indiceY = pontoClicado.y / (getTamanhoDaCasaY()); String posicao = indiceX + "," + indiceY; getMapaDeCasas().put(posicao, jogadorAtual); //Envia os dados para a thread do oponente, que esta esperando getUtilComunicacao().enviaDadosParaComputadorRemoto(dadosDeConexao, getMapaDeCasas()); setTitle(dadosDeConexao.getNomeDoUsuario() + ", voce jogou. Aguarde."); } /** * * @return {@link} */ private UtilComunicacao getUtilComunicacao() { if (utilComunicacao == null) { utilComunicacao = new UtilComunicacao(); } return utilComunicacao; }
  • 11. JogoDaVelha /** * * @param pontoClicado Coordenadas do clique do usuario * @return Se o quadrante clicado est‡ ou nao ocupado */ private boolean posicaoJahMarcada(Point pontoClicado) { int indiceX = pontoClicado.x / (getTamanhoDaCasaX()); int indiceY = pontoClicado.y / (getTamanhoDaCasaY()); String posicao = indiceX + "," + indiceY; if (getMapaDeCasas().get(posicao) != null) { return true; } return false; } /** * Calculo para definir o tamanho das celulas utilizadas. * Jamais utilize valores fixos, pois isso impede a evolucao do sistema * @return Tamanhos */ private int getTamanhoDaCasaY() { return ALTURA / QUANTIDADE_DE_CASAS; } private int getTamanhoDaCasaX() { return LARGURA / QUANTIDADE_DE_CASAS; }
  • 12. /** * Desenha/redesenha a tela a cada clique * Ou, na versao multiplayer, a cada jogada */ public void paint(Graphics g) { super.paint(g); //Vertical g.drawLine((LARGURA / 3), 30, (LARGURA / 3), ALTURA - 10); g.drawLine((LARGURA / 3) * 2, 30, (LARGURA / 3) * 2, ALTURA - 10); //Horizontal g.drawLine(10, ALTURA / 3, LARGURA - 10, ALTURA / 3); g.drawLine(10, (ALTURA / 3) * 2, LARGURA - 10, (ALTURA / 3) * 2); imprimeMapaNoTabuleiro(); // } JogoDaVelha /** * Imprime o mapa no tabuleiro * A chave (key) do mapa esta no formato 'x,y' * Por isso temos o stringtokenizer que recupera cada valor separado pela ',' * Em seguida le cada posicao marcada do mapa, recuperando o jogador marcado * Por fim, desenha na celula x,y a imagem respectiva * O loop le todos os elementos que compoe o mapa naquele momento * */ public void imprimeMapaNoTabuleiro() { for (Object o : getMapaDeCasas().keySet()) { //o (formato x,y) try { StringTokenizer s = new StringTokenizer(o.toString(), ","); int posicaoX = new Integer(s.nextToken()) * getTamanhoDaCasaX() + 30; int posicaoY = new Integer(s.nextToken()) * getTamanhoDaCasaY() + 50; // String jogador = getMapaDeCasas().get(o); desenhaIcone(posicaoX, posicaoY, jogador); // } catch (Exception e) { System.out.println(e); } } }
  • 13. JogoDaVelha /** * Desenha a respectiva imagem dada uma posicao e um jogador * @param posicaoX * @param posicaoY * @param jogador */ private void desenhaIcone(int posicaoX, int posicaoY, String jogador) { Graphics g = getGraphics(); if (jogador.equals("X")) { g.drawImage(UtilImagem.getImagem("xis.png"), posicaoX, posicaoY, this); } else { g.drawImage(UtilImagem.getImagem("zero.png"), posicaoX, posicaoY, this); } } /** * Armazena todas as jogadas ate o presente instante * @return Mapa atual */ public Map<String, String> getMapaDeCasas() { if (mapaDeCasas == null) { mapaDeCasas = new HashMap<String, String>(); } return mapaDeCasas; } public void setMapaDeCasas(Map<String, String> mapaDeCasas) { this.mapaDeCasas = mapaDeCasas; }
  • 14. JogoDaVelha /** * Efetua todas as operacoes referentes ao evento clique do mouse * A cada jogada do usuario, o jogo deve aplicar todas as regras definidas * Alem de informar se algo nao esta correto * @param e Ponto clicado na tela */ private void eventoCliqueDoMouse(MouseEvent e) { pontoClicado = e.getPoint(); defineJogador(); if (posicaoJahMarcada(pontoClicado)) { JOptionPane.showMessageDialog(null, "Posicao ja ocupada.", "Atencao", JOptionPane.WARNING_MESSAGE); } else { repaint(); marcaPosicao(pontoClicado); } if (ganhou()) { JOptionPane.showMessageDialog(null, "Ganhou"); } } /** * Nas duas primeiras jogadas da partida verifica quem e quem * O primeiro jogador sera '0' * O segundo sera 'X' */ private void defineJogador() { if (getMapaDeCasas().keySet().size() == 0 && jogadorAtual == null) { jogadorAtual = "0"; } else if (getMapaDeCasas().keySet().size() == 1 && jogadorAtual == null) { jogadorAtual = "X"; } } }
  • 15. ThreadJogoDaVelha package com.javagames.tabuleiro; import java.net.*; import java.util.*; public class ThreadJogoDaVelha extends Thread { private DadosDeConexao dadosDeConexao; private JogoDaVelha jogo; private UtilComunicacao utilComunicacao; /** * Metodo construtor que exige os dados de conexao e o seu tabuleiro * * Esta classe gerencia as jogadas do oponente atraves do socket * Observacao: Nao ha controle para bloquear o jogador depois do clique * Isso permite que alguem jogue duas vezes * * @param jogo Tabuleiro do seu jogo * @param dados Informacoes necessarias para conectar os tabuleiros */ public ThreadJogoDaVelha(JogoDaVelha jogo, DadosDeConexao dados) { this.dadosDeConexao = dados; this.jogo = jogo; }
  • 16. ThreadJogoDaVelha /** * A thread fica aguardando ate a jogada do oponente * Apos a jogada, bloqueia a thread (accept) * Assim que o oponente jogar, sincroniza os mapas * */ @SuppressWarnings("unchecked") public void run() { // while (true) { try { jogo.repaint(); Thread.sleep(1000); //Aguarda jogada do oponente //Bloqueia a thread ServerSocket server = new ServerSocket(dadosDeConexao.getPortaLocal()); Socket socket = server.accept(); //O oponente jogou jogo.setTitle(dadosDeConexao.getNomeDoUsuario() + ", agora Ž sua vez."); //Processa jogada //Recupera o mapa de jogadas do oponente Map<String, String> mapaRecuperado = getUtilComunicacao().extrairMapa( socket); //Sincroniza o seu tabuleiro Map mapaDeCasas = getUtilComunicacao().sincronizaMapas(mapaRecuperado); jogo.setMapaDeCasas(mapaDeCasas); jogo.imprimeMapaNoTabuleiro(); //Desbloquear os recursos apos sua utilizacao socket.close(); server.close(); // } catch (Exception e) { System.out.print("..."); } } }
  • 17. ThreadJogoDaVelha private UtilComunicacao getUtilComunicacao() { if (utilComunicacao == null) { utilComunicacao = new UtilComunicacao(); } return utilComunicacao; } }
  • 18. Splash Screen • No Netbeans, crie uma tela com os componentes indicados. • Inicie seu jogo e informe os dados do oponente. • O botão de conectar deve iniciar uma thread do JogoDaVelha passando todos os dados necessários (veja o próximo slide).
  • 19. Conexão private void btnConectarActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_btnConectarActionPerformed DadosDeConexao dados = new DadosDeConexao(); dados.setPortaLocal(new Integer(txtPortaLocal.getText())); dados.setPortaRemota(new Integer(txtPortaServidor.getText())); dados.setServidor(txtServidor.getText()); dados.setNomeDoUsuario(txtNome.getText()); JogoDaVelha jogo = new JogoDaVelha(dados); new ThreadJogoDaVelha(jogo, dados).start(); setVisible(false); }//GEN-LAST:event_btnConectarActionPerformed