Ybadoo - Soluções em Software Livre
Tutoriais
Programação Orientada a Objetos

O jogo da forca é um jogo popular que pode ser jogado simplesmente com um pedaço de papel e lápis. As origens deste jogo não são conhecidas com rigor, mas alguns autores defendem que o jogo surgiu na época Vitoriana, no Reino Unido, sendo possível encontrar referências a este jogo em diversas obras, embora com nomes diferentes.

No jogo da forca um jogador tem que descobrir uma palavra escondida, tendo como única informação prévia o número de letras que constituem a palavra. O jogador procede então, por tentativa e erro, sugerindo letras que podem pertencer a palavra.

Quando uma letra pertence a palavra, é indicada ao jogador a posição (ou posições, caso a letra apareça múltiplas vezes) em que a letra aparece na palavra. Quando a letra não pertence a palavra, é incrementado um contador de tentativas (normalmente representado através do desenho de um indivíduo sendo enforcado).

O jogo termina quando o jogador descobre todas as letras da palavra escondida (situação em que vence o jogo) ou quando esgota o número de tentativas possíveis (no máximo dez tentativas, situação em que perde o jogo).

Projete e implemente um programa que permita ao usuário jogar o jogo da forca no computador. O programa selecionará aleatoriamente uma palavra de seu dicionário para que o usuário a descubra.

Desenvolva a solução solicitada, apresentando a modelagem do projeto em Unified Modeling Language (UML) e a sua implementação.

 

Terminal

ybadoo@server:~$ ./application
Diagrama de Classes na Linguagem de Programação Java Dictionary.java DictionaryArray.java Hangman.java HangmanConsole.java Application.java
Diagrama de Classes
Diagrama de Classes na Linguagem de Programação Java

Arquivo Dictionary.java

/*************************************************************************
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)  *
 *                  Ybadoo - Solucoes em Software Livre (ybadoo.com.br)  *
 *                                                                       *
 * Permission is granted to copy, distribute and/or modify this document *
 * under the terms of the GNU Free Documentation License, Version 1.3 or *
 * any later version published by the  Free Software Foundation; with no *
 * Invariant Sections,  no Front-Cover Texts, and no Back-Cover Texts. A *
 * A copy of the  license is included in  the section entitled "GNU Free *
 * Documentation License".                                               *
 *                                                                       *
 * Ubuntu 16.10 (GNU/Linux 4.8.0-39-generic)                             *
 * OpenJDK Version "1.8.0_121"                                           *
 * OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)               *
 *************************************************************************/

package com.ybadoo.tutoriais.poo.tutorial07.exercicio05;

/**
 * Interface para o sorteio da palavra secreta do dicionario
 */
public interface Dictionary
{
  /**
   * Sortear uma palavra secreta do dicionario
   *
   * @return palavra secreta
   */
  public String raffle();
}

Arquivo DictionaryArray.java

/*************************************************************************
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)  *
 *                  Ybadoo - Solucoes em Software Livre (ybadoo.com.br)  *
 *                                                                       *
 * Permission is granted to copy, distribute and/or modify this document *
 * under the terms of the GNU Free Documentation License, Version 1.3 or *
 * any later version published by the  Free Software Foundation; with no *
 * Invariant Sections,  no Front-Cover Texts, and no Back-Cover Texts. A *
 * A copy of the  license is included in  the section entitled "GNU Free *
 * Documentation License".                                               *
 *                                                                       *
 * Ubuntu 16.10 (GNU/Linux 4.8.0-39-generic)                             *
 * OpenJDK Version "1.8.0_121"                                           *
 * OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)               *
 *************************************************************************/

package com.ybadoo.tutoriais.poo.tutorial07.exercicio05;

import java.util.Random;

/**
 * Dicionario de palavras secretas baseado num arranjo de strings
 */
public class DictionaryArray implements Dictionary
{
  /**
   * Lista de palavras secretas
   */
  private final String[] words = {"sufixo", "lexica", "teoria", "turing",
    "objeto", "string", "analise", "browser", "memoria", "palavra",
    "prefixo", "contexto", "alfabeto", "hardware", "software", "automato",
    "assembler", "conversao", "documento", "expressao", "linguagem",
    "gramatica", "paradigma", "semantica", "sintatica", "barramento",
    "compilador", "computacao", "computador", "dicionario", "ferramenta",
    "palindroma", "subpalavra", "tratamento", "delimitador", "informatica",
    "motherboard", "processador", "programacao", "significado",
    "registrador", "propriedade", "usabilidade", "concorrencia",
    "reconhecedor", "complementar", "universidade", "virtualmente",
    "enderecamento", "intermediario", "interpretador", "multiplicacao",
    "portabilidade", "processamento", "adaptabilidade", "arredondamento",
    "confiabilidade", "deterministico", "extraterrestre", "funcionalidade",
    "infraestrutura", "jurisprudencia", "tridimensional", "analisabilidade",
    "associatividade", "compatibilidade", "desenvolvimento", "cartografico",
    "conformidade", "semiconsciencia", "testabilidade", "simplificacao",
    "apreensibilidade", "autossustentavel", "inteligibilidade",
    "manutenibilidade", "microarquitetura", "modificabilidade",
    "operacionalidade", "pseudocientifico", "recuperabilidade"};

  /**
   * Construtor para inicializar o dicionario
   */
  public DictionaryArray()
  {

  }

  /* (non-Javadoc)
   * @see com.ybadoo.tutoriais.poo.tutorial07.exercicio05.Dicionary#raffle()
   */
  @Override
  public String raffle()
  {
    Random random = new Random();

    int index = random.nextInt(words.length);

    return words[index];
  }
}

Arquivo Hangman.java

/*************************************************************************
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)  *
 *                  Ybadoo - Solucoes em Software Livre (ybadoo.com.br)  *
 *                                                                       *
 * Permission is granted to copy, distribute and/or modify this document *
 * under the terms of the GNU Free Documentation License, Version 1.3 or *
 * any later version published by the  Free Software Foundation; with no *
 * Invariant Sections,  no Front-Cover Texts, and no Back-Cover Texts. A *
 * A copy of the  license is included in  the section entitled "GNU Free *
 * Documentation License".                                               *
 *                                                                       *
 * Ubuntu 16.10 (GNU/Linux 4.8.0-39-generic)                             *
 * OpenJDK Version "1.8.0_121"                                           *
 * OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)               *
 *************************************************************************/

package com.ybadoo.tutoriais.poo.tutorial07.exercicio05;

import java.util.ArrayList;
import java.util.List;

/**
 * Jogo da forca
 */
public abstract class Hangman
{
  /**
   * Numero maximo de tentativas permitidas
   */
  private final int MAX_ATTEMPT = 10;

  /**
   * Numero de tentativas
   */
  private int attempt;

  /**
   * Dicionario contendo as palavras secretas
   */
  private Dictionary dicionary;

  /**
   * Letras corretas
   */
  private List<Character> correctLetters;

  /**
   * Letras incorretas
   */
  private List<Character> incorrectLetters;

  /**
   * Palavra secreta
   */
  private String secretWord;

  /**
   * Construtor para inicializar o jogo da forca
   *
   * @param dicionary dicionario contendo as palavras secretas
   */
  public Hangman(Dictionary dicionary)
  {
    this.dicionary = dicionary;
  }

  /**
   * Executar o jogo da forca
   */
  public abstract void play();

  /**
   * Inicializar o jogo da forca para uma nova partida
   */
  protected void initialize()
  {
    secretWord = dicionary.raffle();

    correctLetters = new ArrayList<Character>();

    for(int i = 0; i < this.secretWord.length(); i++)
    {
      correctLetters.add('_');
    }

    incorrectLetters = new ArrayList<Character>();

    attempt = 1;
  }

  /**
   * Validar a tentativa do usuario
   *
   * @param letter letra proposta pelo usuario
   */
  protected void check(char letter)
  {
    boolean chInSecretWord = false;

    attempt = attempt + 1;

    for(int i = 0; i < secretWord.length(); i++)
    {
      if(secretWord.charAt(i) == letter)
      {
        chInSecretWord = true;

        correctLetters.set(i, letter);
      }
    }

    if(!chInSecretWord)
    {
      incorrectLetters.add(letter);
    }
  }

  /**
   * Verificar se a letra ja foi fornecida pelo usuario
   *
   * @param letter letra proposta pelo usuario
   * @return true se o usuario ja forneceu a letra,
   *         ou false caso contrario
   */
  protected boolean repeatedLetter(char letter)
  {
    return correctLetters.contains(letter) ||
           incorrectLetters.contains(letter);
  }

  /**
   * Verificar se o jogo da forca acabou
   *
   * @return true se o jogo da forca acabou,
   *         ou false caso contrario
   */
  protected boolean gameOver()
  {
    return gameWon() || gameLost();
  }

  /**
   * Verificar se o usuario perdeu o jogo da forca
   *
   * @return true se o usuario perdeu o jogo da forca,
   *         ou false caso contrario
   */
  protected boolean gameLost()
  {
    return incorrectLetters.size() == MAX_ATTEMPT;
  }

  /**
   * Verificar se o usuario ganhou o jogo da forca
   *
   * @return true se o usuario ganhou o jogo da forca,
   *         ou false caso contrario
   */
  protected boolean gameWon()
  {
    return !correctLetters.contains('_');
  }

  /**
   * Retornar o numero de tentativas realizadas pelo usuario
   *
   * @return numero de tentativas realizadas pelo usuario
   */
  protected int getAttempt()
  {
    return attempt;
  }

  /**
   * Retornar as letras corretas
   *
   * @return letras corretas
   */
  protected String getCorrectLetters()
  {
    StringBuilder out = new StringBuilder();

    for(int i = 0; i < correctLetters.size(); i++)
    {
      out.append(correctLetters.get(i));
      out.append(" ");
    }

    return out.toString();
  }

  /**
   * Retornar as letras incorretas
   *
   * @return letras incorretas
   */
  protected String getIncorrectLetters()
  {
    int i = 0;

    StringBuilder out = new StringBuilder();

    for(; i < incorrectLetters.size(); i++)
    {
      out.append(incorrectLetters.get(i));
      out.append(" ");
    }

    for(; i < MAX_ATTEMPT; i++)
    {
      out.append("_");
      out.append(" ");
    }

    return out.toString();
  }

  /**
   * Retornar a palavra secreta
   *
   * @return palavra secreta
   */
  protected String getSecretWord()
  {
    StringBuilder out = new StringBuilder();

    for(int i = 0; i < secretWord.length(); i++)
    {
      out.append(secretWord.charAt(i));
      out.append(" ");
    }

    return out.toString();
  }
}

Arquivo HangmanConsole.java

/*************************************************************************
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)  *
 *                  Ybadoo - Solucoes em Software Livre (ybadoo.com.br)  *
 *                                                                       *
 * Permission is granted to copy, distribute and/or modify this document *
 * under the terms of the GNU Free Documentation License, Version 1.3 or *
 * any later version published by the  Free Software Foundation; with no *
 * Invariant Sections,  no Front-Cover Texts, and no Back-Cover Texts. A *
 * A copy of the  license is included in  the section entitled "GNU Free *
 * Documentation License".                                               *
 *                                                                       *
 * Ubuntu 16.10 (GNU/Linux 4.8.0-39-generic)                             *
 * OpenJDK Version "1.8.0_121"                                           *
 * OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)               *
 *************************************************************************/

package com.ybadoo.tutoriais.poo.tutorial07.exercicio05;

import java.util.Scanner;

/**
 * Jogo da forca no console
 */
public class HangmanConsole extends Hangman
{
  /**
   * Construtor para inicializar o jogo da forca no console
   *
   * @param dicionary dicionario contendo as palavras secretas
   */
  public HangmanConsole(Dictionary dicionary)
  {
    super(dicionary);
  }

  /**
   * Executar o jogo da forca no console
   */
  public void play()
  {
    Scanner scanner = new Scanner(System.in);

    boolean readInput = true;

    String input = null;

    initialize();

    while(!gameOver())
    {
      System.out.println("Tentativa : " + getAttempt());

      System.out.println("Palavra   : " + getCorrectLetters());

      System.out.println("Forca     : " + getIncorrectLetters());

      readInput = true;

      input = null;

      while(readInput)
      {
        System.out.print("Letra     : ");

        input = scanner.nextLine();

        if((input == null) ||
           (input.length() == 0) ||
           (!Character.isAlphabetic(input.codePointAt(0))))
        {
          System.out.println("Erro      : forneça um letra válida!");
        }
        else if(repeatedLetter(input.charAt(0)))
        {
          System.out.println("Erro      : letra já fornecida!");
        }
        else
        {
          readInput = false;
        }
      }

      check(input.charAt(0));

      System.out.println();
    }

    scanner.close();

    System.out.println("Tentativa : " + getAttempt());

    System.out.println("Palavra   : " + getSecretWord());

    System.out.println("Forca     : " + getIncorrectLetters());

    if(gameWon())
    {
      System.out.println("Parabéns! Você descobriu!");
    }
    else
    {
      System.out.println("Desculpa, não foi dessa vez!");
    }
  }
}

Arquivo Application.java

/*************************************************************************
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)  *
 *                  Ybadoo - Solucoes em Software Livre (ybadoo.com.br)  *
 *                                                                       *
 * Permission is granted to copy, distribute and/or modify this document *
 * under the terms of the GNU Free Documentation License, Version 1.3 or *
 * any later version published by the  Free Software Foundation; with no *
 * Invariant Sections,  no Front-Cover Texts, and no Back-Cover Texts. A *
 * A copy of the  license is included in  the section entitled "GNU Free *
 * Documentation License".                                               *
 *                                                                       *
 * Ubuntu 16.10 (GNU/Linux 4.8.0-39-generic)                             *
 * OpenJDK Version "1.8.0_121"                                           *
 * OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)               *
 *************************************************************************/

package com.ybadoo.tutoriais.poo.tutorial07.exercicio05;

/**
 * Classe responsavel pela execucao da classe Hangman
 */
public class Application
{
  /**
   * Construtor para inicializar a execucao da classe Hangman
   */
  private Application()
  {

  }

  /**
   * Metodo principal da linguagem de programacao Java
   *
   * @param args argumentos da linha de comando (nao utilizado)
   */
  public static void main(String[] args)
  {
    Dictionary dictionary = new DictionaryArray();

    Hangman hangman = new HangmanConsole(dictionary);

    hangman.play();
  }
}