java -classpath "." p1.aplic.mancala.cui.JogoCUI ENIAC PDP11 ... java -classpath "." p1.aplic.mancala.cui.JogoCUI seunome PDP11
package p1.aplic.mancala.cui; import p1.aplic.mancala.jogo.*; import java.util.*; /** * O controlador de jogo Mancala quando a interface é a caractere. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class JogoCUI { public static void main(String[] args) { Jogador j1 = null; Jogador j2 = null; switch(args.length) { case 0: j1 = criaJogador("ENIAC", Tabuleiro.EM_BAIXO); j2 = criaJogador("PDP11", Tabuleiro.EM_CIMA); break; case 1: j1 = criaJogador(args[0], Tabuleiro.EM_BAIXO); j2 = criaJogador("PDP11", Tabuleiro.EM_CIMA); break; case 2: j1 = criaJogador(args[0], Tabuleiro.EM_BAIXO); j2 = criaJogador(args[1], Tabuleiro.EM_CIMA); break; default: sintaxe(); } // cria um Model JogoMancala jogo = new UmJogo(j1, j2); // cria uma View e cadastre-se junto ao Model jogo.addMancalaListener(new OutputMancalaCUI()); try { joga(jogo); } catch(MancalaException e) { System.err.println(e.getMessage()); System.exit(1); } } /** * Joga um jogo de Mancala com interface a caractere. * * @param jogo O objeto para controlar o jogo. * @throws MancalaException em caso de erro de jogo. */ private static void joga(JogoMancala jogo) throws MancalaException { jogo.iniciaJogo(); Jogador jogadorAtual = jogo.getJogadorAtual(); while(!jogo.fimDeJogo()) { jogadorAtual = jogo.umaJogada(jogadorAtual.escolheJogada(jogo), JogoMancala.COM_EVENTO); } } /** * Cria um jogador de acordo com nomes especiais conhecidos. * * @param nome O nome do jogador. * "ENIAC" é o nome de um computador com algoritmo burro. * "PDP11" é o nome de um computador com algoritmo melhorzinho. * Qualquer outro nome indica um jogador humano. * @return O jogador correspondente. */ private static Jogador criaJogador(String nome, int posição) { if(nome.equals("ENIAC")) { return new JogadorComputador1(nome, posição); } else if(nome.equals("PDP11")) { return new JogadorComputador2(nome, posição); } else { return new JogadorHumanoCUI(nome, posição); } } /** * Dá mensagem de erro de sintaxe e cai fora. * */ private static void sintaxe() { System.err.println("Sintaxe: JogoCUI [primeiro_nome] [segundo_nome]"); System.err.println(" O nome ENIAC é um computador burro"); System.err.println(" O nome PDP11 é um computador melhorzinho"); System.exit(1); } }
while(!jogo.fimDeJogo()) { jogadorAtual = jogo.umaJogada(jogadorAtual.escolheJogada(jogo), JogoMancala.COM_EVENTO); }
package p1.aplic.mancala.jogo; import java.util.*; /** * A parte comum de qualquer jogador: manter nome e posição (EM_BAIXO ou EM_CIMA). * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public abstract class JogadorAbstrato implements Jogador { private String nome; private int posição; /** * Construtor genérico de um jogador. * * @param nome O nome do jogador. * @param posição A posição do jogador (EM_BAIXO ou EM_CIMA). */ public JogadorAbstrato(String nome, int posição) { this.nome = nome; this.posição = posição; } /** * Obtém o nome do jogador. * * @return O nome do jogador */ public String getNome() { return nome; } /** * Informa a posição do jogador. * * @return A posição do jogador (EM_BAIXO ou EM_CIMA) */ public int getPosição() { return posição; } /** * Pede ao jogador para escolher um buraco para jogar. * * @param jogo O jogo do qual o jogador está participando. * @return O número do buraco (entre 0 e 5) * @throws MancalaException se o buraco escolhido não for possível. */ public abstract int escolheJogada(JogoMancala jogo) throws MancalaException; }
package p1.aplic.mancala.cui; import p1.aplic.mancala.jogo.*; import p1.io.*; /** * Interface a caractere para jogar Mancala. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class JogadorHumanoCUI extends JogadorAbstrato { /** * Construtor de um jogador humano com interface a caractere. * * @param nome O nome do jogador. * @param posição A posição do jogador (EM_BAIXO ou EM_CIMA). */ public JogadorHumanoCUI(String nome, int posição) { super(nome, posição); } /** * Pede ao jogador, na entrada padrão, para escolher um buraco para jogar. * * @param jogo O jogo do qual o jogador está participando. * @return O número do buraco (entre 0 e 5) * @throws MancalaException se o buraco escolhido não for possível. */ public int escolheJogada(JogoMancala jogo) throws MancalaException { String resp; boolean ok = false; int numBuraco = 0; while(!ok) { resp = Entrada.in.lerLinha("Jogador " + getNome() + ": informe o numero do buraco: "); if(resp.startsWith("q")) { throw new MancalaException("Jogador " + getNome() + " abandonou o jogo. Tchau."); } try { numBuraco = jogo.getTabuleiro().numAIndex(Integer.parseInt(resp)-1, this.getPosição()); ok = true; } catch(NumberFormatException e) { System.out.println("Tente algo numerico, ta?"); } catch(MancalaException e) { System.out.println(e.getMessage()); } } return numBuraco; } }
package p1.aplic.mancala.jogo; import java.util.*; /** * * Regras deste jogo de Mancala (também chamado Kalaha). * Mancala é jogado com sete buracos -- seis buracos de jogo * e um buraco de pontuação, a <I>Kalaha</I> -- por jogador. * No início do jogo, cada um dos 12 buracos de jogo contém * 3 sementes (ou contas, ou pedras, ou bolas, ...). * Para jogar, o jogador escolhe um buraco a partir do qual ele * vai "semear" as sementes. Cada semente do buraco é colocada, * uma de cada vez, em buracos sucessivos, movendo-se em sentido * anti-horário. Sementes colocadas numa Kalaha são pontos para * o dono da Kalaha. Sementes não são colocadas na Kalaha do oponente. * Se a última semente cair na Kalaha do jogador, ele pode jogar novamente * Se a última semente cair num buraco vazio do próprio jogador, * ele captura as sementes do buraco oposto e as transfere para sua Kalaha * Todas as sementes capturadas, além da semente que fez a captura, * são colocadas na Kalaha do jogador. * O jogo termina quando todos os buracos em algum lado do tabuleiro estejam vazios. * O jogador com sementes em jogo os recolhe para sua Kalaha. * O ganhador é o jogador com mais sementes na sua Kalaha. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class UmJogo implements JogoMancala { private final static int SEMENTES_INICIAIS = 3; private Jogador[] jogadores; private Jogador jogadorAtual; private Tabuleiro tabuleiro; private Collection mancalaListeners = new LinkedList(); /** * Construtor de um jogo de Mancala com dois jogadores. * * @param jogador1 O primeiro jogador. * @param jogador2 O segundo jogador. */ public UmJogo(Jogador jogador1, Jogador jogador2) { jogadores = new Jogador[2]; jogadores[0] = jogador1; jogadores[1] = jogador2; inicializaTabuleiro(); } /** * Inicializa a configuração do tabuleiro. * Neste jogo, temos 3 sementes em cada buraco (que não seja Kalaha). * */ private void inicializaTabuleiro() { tabuleiro = new Tabuleiro(); for(int i = 0; i < Tabuleiro.NUM_BURACOS; i++) { Buraco buraco = tabuleiro.getBuraco(Tabuleiro.EM_BAIXO, i); buraco.adicionaSementes(SEMENTES_INICIAIS); buraco = tabuleiro.getBuraco(Tabuleiro.EM_CIMA, i); buraco.adicionaSementes(SEMENTES_INICIAIS); } } /** * Obtém o tabuleiro sendo usado para o jogo. * * @return O tabuleiro sendo usado para o jogo. */ public Tabuleiro getTabuleiro() { return tabuleiro; } /** * Altera o tabuleiro sendo usado para o jogo. * * @param tabuleiro O tabuleiro a usar. */ public void setTabuleiro(Tabuleiro tabuleiro) { this.tabuleiro = tabuleiro; } /** * Obtem o jogador cuja vez é de jogar. * * @return O jogador cuja vez é de jogar. */ public Jogador getJogadorAtual() { return jogadorAtual; } /** * Obtém um jogador através do seu número. O jogador de baixo é 0, o de cima é 1. * * @param númeroDoJogador o número do jogador (0 = em baixo, 1 = em cima). * @return O jogador indicado. */ public Jogador getJogador(int númeroDoJogador) { return jogadores[númeroDoJogador]; } /** * Obtém o jogador que ganhou a partida. * * @return O jogador que ganhou a partida, ou null se tiver sido empate. */ public Jogador getGanhador() { int diferença = getKalaha(jogadores[0]).getNúmeroDeSementes() - getKalaha(jogadores[1]).getNúmeroDeSementes(); if(diferença > 0) { return jogadores[0]; } else if(diferença < 0) { return jogadores[1]; } else { return null; //empate } } /** * Obtem a Kalaha do jogador indicado. * * @param jogador O jogador cuja Kalaha se deseja. * @return Uma referência ao buraco representando a Kalaha do jogador. */ public Buraco getKalaha(Jogador jogador) { return tabuleiro.getKalaha(jogador.getPosição()); } /** * Avisa ao jogo que queremos iniciar. * */ public void iniciaJogo() { jogadorAtual = jogadores[0]; disparaMancalaEvent(MancalaEvent.INICIO_DE_JOGO, null, jogadorAtual, null); } /** * Faz uma jogada para o jogadorAtual do jogo no buraco indicado por indexBuraco. * * @param indexBuraco O índice (de 0 a 5) do buraco escolhido. * @param querEvento igual a SEM_EVENTO, para uma jogada que não aparecer na interface com o usuário. * Seria o caso para estratégias de jogadores automatizados que querem tentar várias jogadas. * Uma jogada normal (com efeito total) usa COM_EVENTO. * @return O próximo jogador a jogar. * @throws MancalaException se um buraco ilegal for escolhido. */ public Jogador umaJogada(int indexBuraco, int querEvento) throws MancalaException { Buraco buracoEscolhido = tabuleiro.getBuraco(jogadorAtual.getPosição(), indexBuraco); Buraco últimoBuraco = semeia(buracoEscolhido); Jogador quemJogou = jogadorAtual; Jogador próximoJogador = jogadorAtual; // vê quem é o próximo jogador if(!jogaNovamente(últimoBuraco)) { próximoJogador = jogadorAtual.equals(jogadores[0]) ? jogadores[1] : jogadores[0]; } if(querEvento == COM_EVENTO) { jogadorAtual = próximoJogador; // gera evento de mudança de tabuleiro disparaMancalaEvent(MancalaEvent.JOGADOR_JOGOU, buracoEscolhido, jogadorAtual, quemJogou); } return próximoJogador; } /** * Informa se o jogador corrente pode jogar novamente * * @param últimoBuraco O último buraco em que uma semente caiu. * @return true, se o jogador pode jogar novamente. */ private boolean jogaNovamente(Buraco últimoBuraco) { return últimoBuraco.equals(getKalaha(jogadorAtual)); } /** * Informa quem é o jogador oposto de um certo jogador. * * @param jogador O jogador cujo oponente procuramos. * @return O oponente do jogador */ private Jogador jogadorOposto(Jogador jogador) { return jogador.equals(jogadores[0]) ? jogadores[1] : jogadores[0]; } /** * Espalha as sementes de um buraco como resultado de uma jogada e * aplica a regra de roubar as sementes opostas quando o último * buraco está vazio e é do próprio jogador. * * @param buracoEscolhido O buraco escolhido para jogar. * @return O último buraco onde uma semente foi depositada. */ private Buraco semeia(Buraco buracoEscolhido) { int numSementes = buracoEscolhido.getNúmeroDeSementes(); buracoEscolhido.removeSementes(numSementes); Buraco buracoCorrente = buracoEscolhido; while(numSementes > 0) { buracoCorrente = tabuleiro.próximoBuraco(buracoCorrente); if(buracoCorrente.equals(getKalaha(jogadorOposto(jogadorAtual)))) { continue; // não põe semente na Kalaha do oponente } numSementes--; buracoCorrente.adicionaSementes(1); } // se o último buraco é meu estava vazio, rouba sementes do buraco oposto if(tabuleiro.getPosição(buracoCorrente) == jogadorAtual.getPosição() && buracoCorrente.getNúmeroDeSementes() == 1) { // rouba Buraco buracoOposto = tabuleiro.buracoOposto(buracoCorrente); numSementes = buracoOposto.getNúmeroDeSementes(); buracoOposto.removeSementes(numSementes); getKalaha(jogadorAtual).adicionaSementes(numSementes); } return buracoCorrente; } /** * Verifica se o jogo acabou. * * @return true, se o jogo acabou; false, caso contrário. */ public boolean fimDeJogo() { if(tabuleiro.ladoEstáVazio(Tabuleiro.EM_BAIXO) || tabuleiro.ladoEstáVazio(Tabuleiro.EM_CIMA)) { recolheSementes(jogadores[0]); recolheSementes(jogadores[1]); disparaMancalaEvent(MancalaEvent.FIM_DE_JOGO, null, null, null); return true; } else { return false; } } /** * No fim do jogo, recolhe as sementes de um jogador para a Kalaha dele. * * @param jogador O jogador cujas sementes devem ser recolhidas à Kalaha. */ private void recolheSementes(Jogador jogador) { for(int i = 0; i < Tabuleiro.NUM_BURACOS; i++) { Buraco buraco = tabuleiro.getBuraco(jogador.getPosição(), i); int numSementes = buraco.getNúmeroDeSementes(); buraco.removeSementes(numSementes); getKalaha(jogador).adicionaSementes(numSementes); } } /** * Adiciona um listener interessado em receber eventos do jogo. * Normalmente usado para conectar o jogo a uma interface com o usuário. * * @param listener O objeto que deseja receber os eventos do jogo. */ public synchronized void addMancalaListener(MancalaListener l) { if(mancalaListeners.contains(l)) { return; } mancalaListeners.add(l); } /** * Remove um listener não mais interessado em receber eventos do jogo. * * @param listener O listener a ser descadastrado. */ public synchronized void removeMancalaListener(MancalaListener l) { mancalaListeners.remove(l); } /** * Envia um evento de jogo para todos os listeners cadastrados. * Os eventos podem indicar: * 1) o início do jogo (INICIO_DE_JOGO); * 2) Uma jogada de algum jogador (JOGADOR_JOGOU); * 3) o fim do jogo (FIM_DE_JOGO). * * @param oQueOcorreu Indica um dos tr~es eventos acima. * @param buraco o buraco que foi jogado. * @param jogadorAtual O jogador que passa a ser o jogador atual. * @param jogadorQueJogou o jogador que acabou de jogar. */ void disparaMancalaEvent(int oQueOcorreu, Buraco buraco, Jogador jogadorAtual, Jogador jogadorQueJogou) { Collection ml; MancalaEvent evento = new MancalaEvent(this, buraco, jogadorAtual, jogadorQueJogou); synchronized (this) { // A interface Collection não tem clone() // mas a classe LinkedList tem. // Clonar para evitar problemas de sincronização // durante a propagação ml = (Collection)((LinkedList)mancalaListeners).clone(); } Iterator it = ml.iterator(); while(it.hasNext()) { MancalaListener umListener = (MancalaListener)(it.next()); switch(oQueOcorreu) { case MancalaEvent.INICIO_DE_JOGO: umListener.inicioDeJogo(evento); break; case MancalaEvent.JOGADOR_JOGOU: umListener.jogadorJogou(evento); break; case MancalaEvent.FIM_DE_JOGO: umListener.fimDeJogo(evento); break; } } } }
package p1.aplic.mancala.jogo; import java.util.*; /** * * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class Tabuleiro { /** * Posição "em baixo" do tabuleiro, com buracos 1 a 6 e Kalaha à direita. */ public final static int EM_BAIXO = 0; /** * Posição "em cima" do tabuleiro, com buracos 8 a 13 e Kalaha à esquerda. */ public final static int EM_CIMA = 1; /** * Posição de um buraco indicando uma Kalaha. */ public final static int KALAHA = 2; /** * Número de buracos por jogador (sem incluir Kalahas) */ public final static int NUM_BURACOS = 6; private final static int TOTAL_BURACOS = 2*(NUM_BURACOS+1); private final static int PRIMEIRO_BURACO_EM_BAIXO = 0; private final static int ÚLTIMO_BURACO_EM_BAIXO = NUM_BURACOS-1; private final static int KALAHA_DIREITA = NUM_BURACOS; private final static int PRIMEIRO_BURACO_EM_CIMA = NUM_BURACOS+1; private final static int ÚLTIMO_BURACO_EM_CIMA = TOTAL_BURACOS-2; private final static int KALAHA_ESQUERDA = TOTAL_BURACOS-1; private Buraco[] buracos; /** * Construtor de um tabuleiro padrão vazio para jogar Mancala. */ Tabuleiro() { buracos = new Buraco[TOTAL_BURACOS]; for(int i = 0; i < TOTAL_BURACOS; i++) { buracos[i] = new Buraco(i, 0); } } /** * Informa a Kalaha correspondendo a uma posição (EM_BAIXO ou EM_CIMA) * A Kalaha do jogador "em baixo" está à direita. * A Kalaha do jogador "em cima" está à esquerda. * * @param posição A posição de interesse (EM_BAIXO ou EM_CIMA). * @return O buraco correpondendo à Kalaha da posição de interesse. */ Buraco getKalaha(int posição) { return posição == EM_BAIXO ? buracos[KALAHA_DIREITA] : buracos[KALAHA_ESQUERDA]; } /** * Informa o buraco correspondendo a um número de buraco * de uma certa posição (EM_BAIXO ou EM_CIMA). * * @param posição A posição de interesse (EM_BAIXO ou EM_CIMA). * @param númeroDoBuraco O número do buraco (0 a 5) de interesse. * @return O buraco de interesse. */ public Buraco getBuraco(int posição, int númeroDoBuraco) { return posição == EM_CIMA ? buracos[PRIMEIRO_BURACO_EM_CIMA + númeroDoBuraco] : buracos[PRIMEIRO_BURACO_EM_BAIXO + númeroDoBuraco]; } /** * Verifica se um lado do tabuleiro está vazio. * * @param posição A posição de interesse (EM_BAIXO ou EM_CIMA). * @return true se o lado do tabuleiro indicado pela posição está vazio, * isto é, com os 6 buracos vazios. */ boolean ladoEstáVazio(int posição) { for(int i = 0; i < Tabuleiro.NUM_BURACOS; i++) { Buraco buraco = getBuraco(posição, i); if(buraco.getNúmeroDeSementes() > 0) { return false; } } return true; } /** * Informa o próximo buraco depois de um certo buraco, incluindo Kalahas, * no sentido do jogo (anti-horário). * * @param buraco O buraco de referência. * @return O buraco depois do buraco de referência. */ public Buraco próximoBuraco(Buraco buraco) { return buracos[(buraco.getNúmero()+1)%TOTAL_BURACOS]; } /** * Dado um buraco de referência, informa o buraco do lado oposto do tabuleiro. * * @param buraco O buraco de referência. * @return O buraco do lado oposto do tabuleiro */ Buraco buracoOposto(Buraco buraco) { int index = getPosição(buraco) == EM_BAIXO ? KALAHA_DIREITA + (KALAHA_DIREITA - buraco.getNúmero()): KALAHA_ESQUERDA + (KALAHA_ESQUERDA - buraco.getNúmero()); return buracos[index % TOTAL_BURACOS]; } /** * Informa se um buraco está EM_CIMA, EM_BAIXO, ou é KALAHA. * * @param buraco O buraco de interesse. * @return EM_BAIXO, para buracos de cima * EM_CIMA, para buracos de baixo * KALAHA para as duas Kalahas. */ int getPosição(Buraco buraco) { int num = buraco.getNúmero(); if(PRIMEIRO_BURACO_EM_BAIXO <= num && num <= ÚLTIMO_BURACO_EM_BAIXO) { return EM_BAIXO; } else if(PRIMEIRO_BURACO_EM_CIMA <= num && num <= ÚLTIMO_BURACO_EM_CIMA) { return EM_CIMA; } else { return KALAHA; } } /** * Converte um número absoluto (de 0 a 13) para um índice de buraco (0 a 5) * Se o buraco não corresponder à posição desejada, lança exceção. * (Isso fede e precisa de refatoramento) * * @param numAbsoluto Um número de buraco do tabuleiro, de 0 a 13. * @param posição A posição (EM_BAIXO, EM_CIMA) na qual este buraco deve estar. * @return O índice do buraco correspondente (de 0 a 5). * @throws MancalaException se O buraco não se localiza na posição indicada. */ public int numAIndex(int numAbsoluto, int posição) throws MancalaException { if(posição == EM_CIMA) { if(PRIMEIRO_BURACO_EM_CIMA <= numAbsoluto && numAbsoluto <= ÚLTIMO_BURACO_EM_CIMA) { return numAbsoluto - PRIMEIRO_BURACO_EM_CIMA; } } else { if(PRIMEIRO_BURACO_EM_BAIXO <= numAbsoluto && numAbsoluto <= ÚLTIMO_BURACO_EM_BAIXO) { return numAbsoluto - PRIMEIRO_BURACO_EM_BAIXO; } } throw new MancalaException("Esse buraco nao eh seu!"); } /** * Duplica o tabuleiro. É um Deep Copy. * * @return O clone do objeto. */ public Object clone() { Tabuleiro novo = new Tabuleiro(); for(int i = 0; i < TOTAL_BURACOS; i++) { novo.buracos[i].adicionaSementes(this.buracos[i].getNúmeroDeSementes()); } return novo; } }
package p1.aplic.mancala.jogo; /** * Este classe representa um buraco do tabuleiro do jogo de mancala. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class Buraco { /** * O número que identifica do buraco (de 0 a 13) */ private int número; /** * O número de sementes no buraco */ private int numSementes; /** * Construtor de um buraco com dada identificação * * @param número A identificação do buraco (de 0 a 13). */ Buraco(int número) { this(número, 0); } /** * Construtor de um buraco com dada identificação e com sementes iniciais. * * @param número A identificação do buraco (de 0 a 13). * @param numSementes O número de sementes a colocar inicialmente no buraco. */ Buraco(int número, int numSementes) { this.número = número; this.numSementes = numSementes; } /** * Informa quantas sementes estão no buraco. * * @return O número de sementes no buraco. */ public int getNúmeroDeSementes() { return numSementes; } /** * Informa a identificação do buraco. * * @return A identificação do buraco (de 0 a 13) */ public int getNúmero() { return número; } /** * Adiciona sementes ao buraco. * * @param numSementes O número de sementes a adicionar ao buraco. */ void adicionaSementes(int numSementes) { this.numSementes += numSementes; } /** * Remove sementes do buraco. * * @param numSementes O número de sementes a remover do buraco. */ void removeSementes(int numSementes) { this.numSementes -= numSementes; } /** * Representa o buraco como string * * @return Um string representando o buraco. */ public String toString() { return "Buraco " + número + ", " + getNúmeroDeSementes() + " sementes"; } }
package p1.aplic.mancala.jogo; /** * Representação de um evento "interessante" de um jogo de Mancala. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class MancalaEvent extends java.util.EventObject { /** * Um possível evento de jogo: o jogo acabou de iniciar mas ninguém jogou ainda. */ public final static int INICIO_DE_JOGO = 0; /** * Um possível evento de jogo: um jogador acabou de jogar. */ public final static int JOGADOR_JOGOU = 1; /** * Um possível evento de jogo: o jogo acabou. */ public final static int FIM_DE_JOGO = 2; private Buraco buraco; private Jogador jogadorAtual; private Jogador jogadorQueJogou; /** * Construtor de um evento de jogo. * * @param source O jogo que é a fonte do evento. * @param buraco O buraco que acabou de ser jogado. * @param jogadorAtual O próximo jogador a jogar. * @param jogadorQueJogou Quem acabou de jogar. */ public MancalaEvent(JogoMancala source, Buraco buraco, Jogador jogadorAtual, Jogador jogadorQueJogou) { super(source); this.buraco = buraco; this.jogadorAtual = jogadorAtual; this.jogadorQueJogou = jogadorQueJogou; } /** * Accessor para o buraco jogado. * * @return O buraco que foi jogado. */ public Buraco getBuraco() { return buraco; } /** * Accessor para o jogador que acabou de jogar. * * @return O jogador que acabou de jogar. */ public Jogador getJogadorQueJogou() { return jogadorQueJogou; } /** * Accessor para o próximo jogador a jogar. * * @return O próximo jogador a jogar. */ public Jogador getJogadorAtual() { return jogadorAtual; } }
package p1.aplic.mancala.jogo; /** * Listeners de um jogo de Mancala são normalmente objetos que implementam * interfaces com o usuário para o jogo. Tais objetos * devem implementar essa interface. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public interface MancalaListener extends java.util.EventListener { /** * Este método do listener é chamado para indicar que o jogo iniciou. * * @param evento O objeto que descreve o inicio do jogo. */ void inicioDeJogo(MancalaEvent evento); /** * Este método do listener é chamado para indicar que um jogador jogou. * * @param evento O objeto que descreve a jogada feita. */ void jogadorJogou(MancalaEvent evento); /** * Este método do listener é chamado para indicar que o jogo terminou. * * @param evento O objeto que descreve o resultado do jogo. */ void fimDeJogo(MancalaEvent evento); }
package p1.aplic.mancala.cui; import p1.aplic.mancala.jogo.*; import java.util.*; /** * Classe que recebe os eventos de jogo e fornece a saída * com interface a caractere. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class OutputMancalaCUI implements MancalaListener { /** * Recebe o evento de início de jogo. * * @param evento O evento INICIO_DE_JOGO. * O evento contém o jogo fonte e o primeiro jogador. */ public void inicioDeJogo(MancalaEvent evento) { JogoMancala jogo = (JogoMancala)evento.getSource(); mostraTabuleiro(jogo, evento.getJogadorAtual()); } /** * Recebe o evento de jogada feita. * * @param evento O evento JOGADOR_JOGOU. * O evento contém o jogo fonte, * o buraco jogado, quem jogou, * e o próximo jogador. */ public void jogadorJogou(MancalaEvent evento) { JogoMancala jogo = (JogoMancala)evento.getSource(); System.out.println("Jogador " + evento.getJogadorQueJogou().getNome() + " jogou buraco " + (evento.getBuraco().getNúmero()+1)); mostraTabuleiro(jogo, evento.getJogadorAtual()); } /** * Recebe o evento de fim de jogo. * * @param evento O evento FIM_DE_JOGO. * O evento contém o jogo fonte, * e quem jogou. */ public void fimDeJogo(MancalaEvent evento) { JogoMancala jogo = (JogoMancala)evento.getSource(); System.out.println(); System.out.println("Fim do jogo"); mostraTabuleiro(jogo, evento.getJogadorAtual()); System.out.println(); if(jogo.getGanhador() == null) { System.out.println("Empate!"); } else { System.out.println("Jogador " + jogo.getGanhador().getNome() + " ganhou!"); } } /** * Desenha o tabuleiro na saída. * * @param jogo O jogo sendo jogado. * @param jogadorAtual O próximo jogadora jogar. */ private void mostraTabuleiro(JogoMancala jogo, Jogador jogadorAtual) { final String SEPARADOR = "-----------------------"; String espacoLinhaMancala = ""; // Usado para colocar espacos na linha // da mancala System.out.println(" 13 12 11 10 9 8"); System.out.println(SEPARADOR); // linha de buracos do jogador de cima System.out.print( " " ); for(int i = Tabuleiro.NUM_BURACOS-1; i >= 0; i--) { Buraco buraco = jogo.getTabuleiro().getBuraco(Tabuleiro.EM_CIMA, i); System.out.print( buraco.getNúmeroDeSementes() + " " ); espacoLinhaMancala += " "; } mostraJogador(jogo.getJogador(1), jogadorAtual, jogo); // linha das mancalas System.out.print(jogo.getKalaha(jogo.getJogador(1)).getNúmeroDeSementes() + " " ); System.out.print( espacoLinhaMancala ); System.out.println(jogo.getKalaha(jogo.getJogador(0)).getNúmeroDeSementes()); // linha de buracos do jogador de baixo System.out.print( " " ); for(int i = 0; i < Tabuleiro.NUM_BURACOS; i++) { Buraco buraco = jogo.getTabuleiro().getBuraco(Tabuleiro.EM_BAIXO, i); System.out.print( buraco.getNúmeroDeSementes() + " " ); espacoLinhaMancala += " "; } mostraJogador(jogo.getJogador(0), jogadorAtual, jogo); System.out.println(SEPARADOR); System.out.println(" 1 2 3 4 5 6"); p1.io.Entrada.in.lerLinha(); } /** * Imprima a informação de um jogador na saída. * * @param jogador O jogador sendo impresso. * @param jogadorAtual Quem é o próximo jogador a jogar no jogo. * @param jogo O jogo sendo jogado. */ private void mostraJogador(Jogador jogador, Jogador jogadorAtual, JogoMancala jogo) { // indicador da vez if(jogador == jogadorAtual) { System.out.print( " -->" ); } else { System.out.print( " "); } // informacao sobre o jogador System.out.println("Jogador " + jogador.getNome()); } }
package p1.aplic.mancala.jogo; import java.util.*; /** * Um jogador automático bastante burrinho. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class JogadorComputador1 extends JogadorAbstrato { /** * Construtor de um jogador automático (computador) * com algoritmo bem burrinho para jogar. * * @param nome O nome do jogador. * @param posição A posição do jogador (EM_BAIXO ou EM_CIMA). */ public JogadorComputador1(String nome, int posição) { super(nome, posição); } /** * Pede ao jogador para escolher um buraco para jogar. * A estratégia é burra: o primeiro buraco que contém sementes * * @param jogo O jogo do qual o jogador está participando. * @return O número do buraco (entre 0 e 5) * @throws MancalaException se o buraco escolhido não for possível. */ public int escolheJogada(JogoMancala jogo) throws MancalaException { for(int i = 0; i < Tabuleiro.NUM_BURACOS; i++) { Buraco buraco = jogo.getTabuleiro().getBuraco(getPosição(), i); if(buraco.getNúmeroDeSementes() > 0) { return i; } } throw new MancalaException("A partida nao terminou mas nao tenho sementes!"); } }
package p1.aplic.mancala.jogo; import java.util.*; /** * Um jogador automático mais-ou-menos razoável para jogar Mancala. * * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br * @version 1.0 * <br> * Copyright (C) 2001 Universidade Federal da Paraíba. */ public class JogadorComputador2 extends JogadorAbstrato { /** * Construtor de um jogador automático (computador) * com algoritmo razoável para jogar. * * @param nome O nome do jogador. * @param posição A posição do jogador (EM_BAIXO ou EM_CIMA). */ public JogadorComputador2(String nome, int posição) { super(nome, posição); } /** * Pede ao jogador para escolher um buraco para jogar. * A estratégia é razoável: tenta todos os buracos e escolhe o que * dá "melhor" resultado, numa avaliação simples. * * @param jogo O jogo do qual o jogador está participando. * @return O número do buraco (entre 0 e 5) * @throws MancalaException se o buraco escolhido não for possível. */ public int escolheJogada(JogoMancala jogo) throws MancalaException { // Jogador eh computador: devemos determinar a melhor jogada int melhorJogada = -1; int jogadaComRepetição = -1; int maxPedrasAdicionais = -1; // tente as possiveis jogadas Tabuleiro tabuleiroOriginal = jogo.getTabuleiro(); int sementesOriginais = jogo.getKalaha(this).getNúmeroDeSementes(); for(int i = 0; i < Tabuleiro.NUM_BURACOS; i++) { if(tabuleiroOriginal.getBuraco(getPosição(), i).getNúmeroDeSementes() > 0) { Tabuleiro tabuleiroDeTeste = (Tabuleiro)tabuleiroOriginal.clone(); jogo.setTabuleiro(tabuleiroDeTeste); if(jogo.umaJogada(i, JogoMancala.SEM_EVENTO) == this) { jogadaComRepetição = i; } int pedrasAdicionais = jogo.getKalaha(this).getNúmeroDeSementes() - sementesOriginais; if( pedrasAdicionais > maxPedrasAdicionais ) { maxPedrasAdicionais = pedrasAdicionais; melhorJogada = i; } } } jogo.setTabuleiro(tabuleiroOriginal); // tentamos todas as possibilidades: escolhe a melhor if(maxPedrasAdicionais > 1) { return melhorJogada; } else if(jogadaComRepetição >= 0) { return jogadaComRepetição; } else { return melhorJogada; } } }
exemplo-1 programa