2
\$\begingroup\$

This is my implementation of the classic "Hangman" word-guessing game.

Class LePendu :

public class LePendu {


    // Variable

    public static int NB_ERREURS_MAX=10;
    static ArrayList<Character> playerGuess = new ArrayList<Character>();
    static ArrayList <String> wrongGuess = new ArrayList<String>();
    static ArrayList <String> playerWord = new ArrayList<String>();
    static String penduDessin [][] = new String[10][10];

    // Le Main :

    public static void main(String args[]) throws FileNotFoundException {
        Scanner sc = new Scanner (new File("C:/Users/admin/pendu.txt"));
        Scanner charP = new Scanner (System.in);
        while(sc.hasNext()) {
            playerWord.add(sc.nextLine());
        }
        
        // Intitialisation Hangman :
        initialize2dArray();

        // Wordchoice :
        Random motAleatoire = new Random(); 
        String word = playerWord.get(motAleatoire.nextInt(playerWord.size()));

        // Loop for the game :
        int chance = 0;
        while(true) {              
            penduEntier();
            drawPendu(chance);
                    
            if (chance>word.length()) {
                System.out.println("Perdu!!!!");
                break;
            }
                            
            displayWord(word, playerGuess);
            if (!getPlayerChar(charP, word, playerGuess)) {
                chance ++;
            };
            if(displayWord(word, playerGuess)) {
                System.out.println("Victoire");
                break;
            } 
            System.out.println("Tentez votre chance pour le mot");
            if(charP.nextLine().equals(word)) {
                System.out.println("Victoire");
                break;
            } else {
                System.out.println("Mot incorrect, veuillez réessayer");
            }
        }        
    }


    // Méthode getPlayerChar :
    private static boolean getPlayerChar(Scanner charP, String word, ArrayList<Character> playerGuess) {
        System.out.println("Entrez une lettre svp");        
        String charPlayer = charP.nextLine();
        playerGuess.add(charPlayer.charAt(0));
        
        return word.contains(charPlayer);
    }

    // Méthode displayWord :
    private static boolean displayWord(String word, ArrayList<Character> playerGuess) {
        int count = 0;
        for (int i = 0;i<word.length();i++) {
            if(playerGuess.contains(word.charAt(i))) {
                System.out.print(word.charAt(i));
                count++;
            }
            else {
                System.out.print("-");
            }
        }
        System.out.println("");
        return (word.length() == count);
    }

    // Draw Hangman Methode :
    public static void penduEntier(){       
        // Loop through the entire 2D array to display Hangman image
        for (int row = 0; row < 10; row++) {
            for (int column = 0; column < 10; column++) {
                System.out.print(penduDessin[row][column]);
            }
            System.out.println();
        }
    }


    // Tableau 2D Hangman :
    public static void drawPendu(int chance) {      
        // The hangman will be erected from bottom to top, that is first gallos
        // base will be made and then step by step hangman will be generated.       
        switch(chance) {            
            // we do not need add break in the cases because when players misses
            // word after 8 chances then complete image of hangman is created.
            case 8:
                // Create legs of man
                penduDessin[6][6] = "/";
                penduDessin[7][5] = "/";
                penduDessin[6][8] = "\\";
                penduDessin[7][9] = "\\";
                
            case 6:
                // Create hands of man
                penduDessin[4][6] = "/";
                penduDessin[5][5] = "/";
                penduDessin[4][8] = "\\";
                penduDessin[5][9] = "\\";
                
            case 5:
                // Create tummy of man
                for(int i = 3; i <= 5; i++)             
                    penduDessin[i][7] = "|";
                
            case 4:
                // Create eyes and nose of man
                penduDessin[2][6] = "*";
                penduDessin[2][7] = "!";
                penduDessin[2][8] = "*";
                
            case 3:             
                // Create face of man
                penduDessin[2][5] = "(";
                penduDessin[2][9] = ")";                
                
            case 2:             
                // Create gallos
                for(int i = 3; i <= 7; i++)             
                    penduDessin[0][i] = "#";
                penduDessin[1][7] = "#";
                
            case 1:
                // Create gallos 
                for(int i = 0; i <= 9; i++)             
                    penduDessin[i][3] = "|";            
                                
            case 0:
                // Create base of gallos
                for(int i = 0; i <= 8; i++)             
                    penduDessin[8][i] = "_";            
            break;
            
            default:
                break;
                
        }
    }


    // Initialize the hangman with space :
    public static void initialize2dArray()
    {
        // Initialize the 2d array with blank spaces before printing the 
        // actual image of hangman.
        for (int row = 0; row < 10; row++)
        {
            for (int column = 0; column < 10; column++)
            {
                penduDessin[row][column] = " ";
            }           
        }
    }
    
}

Thx for your help

\$\endgroup\$
3
  • \$\begingroup\$ thanks for moving it over from stackoverflow! seems to be better place here \$\endgroup\$ Jun 25 at 13:14
  • \$\begingroup\$ An user say me to move CodeReview. ;) \$\endgroup\$
    – Cheg 62
    Jun 25 at 14:59
  • \$\begingroup\$ i read it - and upvoted that proposal =) \$\endgroup\$ Jun 25 at 15:03
2
\$\begingroup\$

minor issues: language

source code is written in english. I don't speak english and many other don't do as well. that might be one reason why this review has no answers yet.

  • NB_ERREURS_MAX
  • String penduDessin
  • Random motAleatoire
  • penduEntier()

minor issue: hard-coded strings

as said that the source code is in english same applies for texts written. to handle such that you should use constants that provide an english name (but havin foreign content)

instead of

System.out.println("Victoire");

you define a constant

static final String VICTORY_MESSAGE = "Victoire";
static final String FAIL_MESSAGE = "Perdu!!!!";

...

if (chance>word.length()) {
    System.out.println(FAIL_MESSAGE);
    break;
}

than everybody is able to understand the foreign text.

Another important point is that would be a more "maintainable" code since you would have all String on one place and could easily translate them. (open for enhancements thats one part of SOLID)

minor issue: c-style array initialization

in java we declare arrays directly on the array type, instead of String penduDessin [][] we use String[][] penduDessin

issue: single responsibility

your method displayWord() returns a boolean, because it does two things instead one. it

  • displays the word
  • checks if the word has been solved

seperate them!

the same applies for getPlayerChar() , this methods

  • handles user input
  • validates if it matches the secret word

major issue: objects and methods

you are using java but your code is not object orientated but procedural orientated. that leads to a lot of hard-to.read code.

use objects: that's what first got into my mind, but you can decide different:

  • HangmanGame (game logic)
  • HangmanWord
  • HangmanDisplay
  • Dictionary
  • Dictionary reader
  • InputReader

if you would split that code in such ways your code would be far more readable (maintainable)

public static void main(String args[]){
    Dictionary dic = new Dictionary(new FileDictReader().read(DICT_FILENAME));
    HangmanGame game = new HangmanGame(dict, new PlayerInputReader(), new HangmanDisplay());
    game.start();
}

doing so you could clearly address tasks to object, for example getting a word from a given List:

HangmanWord wordToGuess = new HangManWord(dictionary.getRandom());

so we have a single responsibility for the dictionary: provide words!

another example would be the dictionary reader:

reading the dictionary from one source (file) and it's exception handling would be done by the DictionaryReader. you could also add another reader that lets you read URLs or any other source. The benefit would be that you don't have to change the dictionary for new readers.

major: seperate data from display

you should provide a data object for the state of your game: HangmanWord. this state would change whenever you add a letter to the HangmanWord.

HangmanWord is a data object and could provide all relevant information needed to play the game

  • HangmanWord.isSolved()
  • HangmanWord.isFailed()
  • HangmanWord.getAmountFailures()
  • HangmanWord.addCharacter()
  • HangmanWord.getHiddenWord()
  • HangmanWord.getGuesses()

that would ease up the way your while-loop would look like

after-Thoughts

you should always try to avoid hard coupling, but hangman is a challenge. to avoid the direct dependency between HangmanWord and HangmanPrinter is not easily to achieve, since they are hardly connected by the amount of failures of the HangmanWord (and therefore the shape of the hangman). you already detected that dependency by using NB_ERREURS_MAX - i would really like to see a solution, where you (anyone) solved this dependency ^_^

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Thx a lot for your response \$\endgroup\$
    – Cheg 62
    Jul 1 at 6:46
  • \$\begingroup\$ you can accept the answer if you think it was helpful ;-) \$\endgroup\$ Jul 1 at 7:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.