Anterior Próximo

Coding Dojo Partida de Tenispublicado em 12/02/2010

Recentemente postei aqui no site a resolução do problema FizzBuzz usando TDD sugerido no Dojo do .Net Architects.

Caso você tenha assistido ao vídeo até o final, pôde perceber que por falta de tempo, o problema do Jogo de Tênis não foi resolvido. Por este motivo estou postando aqui a minha solução.

O Objetivo do problema é simular uma partida de tênis simples com apenas um game, onde os jogadores podem pontuar e trocar vantagens até o fim do jogo. Segue as regras:

  • Todos os jogadores podem pontuar, a ordem de pontuação é 0,15,30,40 pontos.
  • Um jogador com 40 pontos, ganha o jogo sem precisar de vantagem caso marque mais um ponto e seu oponente tenha menos de 40 pontos.
  • Um jogador ganha a vantagem caso marque ponto e seu oponente possua 40 pontos.
  • Um jogador perde a vantagem caso seu oponente pontue.
  • Se um jogador com vantagem pontuar, ganha o jogo.

Comecei com testes básicos e fui avançando ponto a ponto, ao fim do problema eles ficaram assim:

[TestClass]
public class Dada_Uma_Partida_De_Tenis
{
    [TestMethod]
    public void Ao_Iniciar_Partida_A_Pontuacao_Esta_Zerada()
    {   
        PartidaDeTenis partida = new PartidaDeTenis();
        Assert.AreEqual(Pontos.Zero, partida.Jogador1.Pontuacao);
        Assert.AreEqual(Pontos.Zero, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void P1_Pontua_1x_E_Sua_Pontuacao_Fica_15()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador1();
        Assert.AreEqual(Pontos.Quinze, partida.Jogador1.Pontuacao);
    }

    [TestMethod]
    public void P1_Pontua_2x_E_Sua_Pontuacao_Fica_30()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        Assert.AreEqual(Pontos.Trinta, partida.Jogador1.Pontuacao);
    }

    [TestMethod]
    public void P2_Pontua_1x_E_Sua_Pontuacao_Fica_15()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Quinze, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void P2_Pontua_2x_E_Sua_Pontuacao_Fica_30()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Trinta, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void P2_Pontua_3x_E_Sua_Pontuacao_Fica_40()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Quarenta, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void P1_Pontua_4x_P2_Nao_Pontua_P1_Ganha_O_Jogo()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        Assert.AreEqual(Pontos.Ganhou, partida.Jogador1.Pontuacao);
    }

    [TestMethod]
    public void P2_Pontua_4x_P1_Nao_Pontua_P2_Ganha()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Ganhou, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void P1_Possui_40_Pontos_P2_Possui_40_Pontos_Entao_P1_Ao_Pontuar_Ganha_Vantagem()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        Assert.AreEqual(Pontos.Vantagem, partida.Jogador1.Pontuacao);
    }

    [TestMethod]
    public void P1_Possui_Vantagem_Entao_P1_Ao_Pontuar_Ganha_O_Jogo()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        Assert.AreEqual(Pontos.Ganhou, partida.Jogador1.Pontuacao);
    }

    [TestMethod]
    public void P1_Possui_Vantagem_P2_Pontua_Entao_P1_Perde_Vantagem()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Quarenta, partida.Jogador1.Pontuacao);
    }

    [TestMethod]
    public void P2_Possui_40_Pontos_P1_Possui_40_Pontos_Entao_P2_Ao_Pontuar_Ganha_Vantagem()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Vantagem, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void P2_Possui_Vantagem_P2_Ao_Pontuar_Ganha_O_Jogo()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Ganhou, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void P2_Possui_Vantagem_P1_Pontua_Entao_P2_Perde_Vantagem()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        Assert.AreEqual(Pontos.Quarenta, partida.Jogador2.Pontuacao);
    }

    [TestMethod]
    public void Partida_Completa_Com_Troca_De_Vantagens_Onde_P2_Ganha()
    {
        PartidaDeTenis partida = new PartidaDeTenis();
        partida.PontuarJogador1();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador1();
        partida.PontuarJogador2();
        partida.PontuarJogador2();
        Assert.AreEqual(Pontos.Ganhou, partida.Jogador2.Pontuacao);
    }
}

Depois de muitos testes e refatorações cheguei ao código abaixo, acho que ainda poderia melhorar o método Pontuar() diminuindo o número de Ifs, mas como o tempo estava curto deixei para uma outra oportunidade:

public class PartidaDeTenis
{
    public Jogador Jogador1 { get; private set; }
    public Jogador Jogador2 { get; private set; }

    public PartidaDeTenis()
    {
        // Iniciando jogadores da partida
        this.Jogador1 = new Jogador();
        this.Jogador2 = new Jogador();
    }

    public void PontuarJogador1()
    {
       this.Pontuar(Jogador1, Jogador2);            
    }

    public void PontuarJogador2()
    {
        this.Pontuar(Jogador2, Jogador1);
    }

    private void Pontuar(Jogador jogadorPontuador, Jogador jogadorPontuado)
    {
        if (jogadorPontuador.TemVantagem)
            jogadorPontuador.Pontuacao = Pontos.Ganhou;
        else
        {
            if (jogadorPontuado.TemVantagem)
                jogadorPontuado.Pontuacao = Pontos.Quarenta;
            else
            {
                // verifica se é necessário dar vantagem
                if (jogadorPontuador.Pontuacao.Equals(Pontos.Quarenta) && jogadorPontuado.Pontuacao.Equals(Pontos.Quarenta))
                    jogadorPontuador.Pontuacao = Pontos.Vantagem;
                else
                {
                    switch (jogadorPontuador.Pontuacao)
                    {
                        case Pontos.Zero:
                            jogadorPontuador.Pontuacao = Pontos.Quinze;
                            break;
                        case Pontos.Quinze:
                            jogadorPontuador.Pontuacao = Pontos.Trinta;
                            break;
                        case Pontos.Trinta:
                            jogadorPontuador.Pontuacao = Pontos.Quarenta;
                            break;
                        case Pontos.Quarenta:
                            jogadorPontuador.Pontuacao = Pontos.Ganhou;
                            break;
                    }
                }
            }
        }
    }

}

public enum Pontos
{
    Zero = 0,
    Quinze = 15,
    Trinta = 30,
    Quarenta = 40,
    Vantagem = 45,
    Ganhou = 50
}  

public class Jogador
{
    public Pontos Pontuacao { get; set; }
    public bool TemVantagem
    {
        get { return this.Pontuacao.Equals(Pontos.Vantagem);  }
    }
}    

E você ? Fez o Dojo também ? Comente a minha solução e sugira novos problemas para que eu possa postar as soluções por aqui!

Faça o download da Solution com tudo funcionando:

Referencias úteis:


Tags:

retweet

BBCode permitido - [code], [pre], [b], [i], [u], [del], [url], [left], [right], [center]


Ir direto para o topo