'How to replace the underscores with chosen letters in hangman

In my piece of code, I am having trouble replacing the underscores displayed by the length of the word with the correct letters. How do I solve this?.

Below is a example of my code being run.

print("Welcome to Python Hangman")
print()

import random # Needed to make a random choice
from turtle import * #Needed to draw line

WORDS= ("variable", "python", "turtle", "string", "loop")

word= random.choice(WORDS)#chooses randomly from the choice of words
print  ("The word is", len(word), "letters long.")# used to show how many letters are in the random word

space = len(word)
underscore = ("_ " * space)
print(underscore)

for i in range(1, 9):#gives the amount of guesses allocated
    letter = input("Guess a letter ")
    if letter in word:
        print ("Correct", letter)#if guesses letter is correct print correct
    else:
        print ("Incorrect", " ",letter)
        #if its wrong print incorecct 
​


Solution 1:[1]

I would use a dict to keep track of the letter guessed correctly and print based on that, you also need to catch when the user wins:

WORDS= ("variable", "python", "turtle", "string", "loop")

word = random.choice(WORDS)#chooses randomly from the choice of words
print  ("The word is", len(word), "letters long.")# used to show how many letters are in the random word

ln = len(word)
guessed = dict.fromkeys(word, 0)
print("_ "*ln)
correct = 0
for i in range(1, 9):#gives the amount of guesses allocated
    letter = input("Guess a letter ")

    if letter in word:
        print ("Correct! {} is in the word".format(letter))#if guesses letter is correct print correct
        guessed[letter] = 1
        correct += 1
        if correct == ln:
            print("Congratulations! you win.\n The word was {}".format(word))
            break
    else:
        print ("Incorrect! {} is not in the word".format(letter))
        #if its wrong print incorecct
    print(" ".join([ch if guessed[ch] else "_" for ch in word]))
else:
    print("You lose!\nThe word was {}".format(word))

Solution 2:[2]

Sadly, it's not possible to replace the underscores after you printed them to a console window. Your options are:

  1. to implement a GUI, which allows you to change the text after it is displayed
  2. to print a lot of empty lines to make the old version of your output text disappear (which gives the impression that the output has changed)
  3. to print an updated version each time your output text needs to be changed (which is what I would recommend). See my description of this option below.

For option 3 your output may look like this:

Welcome to Python Hangman

The word is 6 letters long.

_ _ _ _ _ _ 
Guess a letter t
Correct t

t _ _ t _ _ 
Guess a letter u
Correct u

t u _ t _ _ 
Guess a letter e
Correct e

t u _ t _ e 
Guess a letter 

To achieve this, you should have a list like this:

output = ['_'] * len(word)

Now you can replace the spaces in this list each time a user finds a correct letter by doing:

for i,x in enumerate(word):
    if x is letter:
        output[i] = letter

and print the updated list using a function:

def print_output():
    print ''.join([str(x)+" " for x in output])

Which gives you the desired output.

Complete solution:

print "Welcome to Python Hangman"
print
import random # Needed to make a random choice

WORDS = ("variable", "python", "turtle", "string", "loop")

word = random.choice(WORDS)#chooses randomly from the choice of words
print "The word is", len(word), "letters long." # used to show how many letters are in the random word

output = ['_'] * len(word)

# function to print the output list
def print_output():
    print
    print ''.join([x+" " for x in output])

for i in range(1, 9):#gives the amount of guesses allocated
    print_output()
    letter = raw_input("Guess a letter ")
    if letter in word:
        print "Correct", letter #if guesses letter is correct print correct

        # now replace the underscores in the output-list with the correctly
        # guessed letters - on the same position the letter is in the 
        # secret word of course
        for i,x in enumerate(word):
            if x is letter:
                output[i] = letter

    else:
        print "Incorrect", " ", letter
        #if its wrong print incorecct 

Solution 3:[3]

Here is a Python 3 version that also checks for a win:

print('Welcome to Python Hangman')
import random 

WORDS = ("variable", "python", "turtle", "string", "loop")

word = random.choice(WORDS)#chooses randomly from the choice of words
print('The word is", len(word), "letters long.')
    output = ['_'] * len(word)


def print_output():
    print()
    print(''.join([x+' ' for x in output]))


for w in range(1, 9):
    print_output()
    letter = input('Guess a letter \n')
    if letter == word:
        print('You win!')
        break
    elif letter in word:
        print('Correct', letter)
        for i, x in enumerate(word):
            if x is letter:
                output[i] = letter
    if '_' not in output:
        print('You win!')
        break
    else:
        print('Incorrect', ' ', letter)

And here is a multiplayer version that allows the first person to choose their own word:

print('Welcome to Python Hangman')

word = input('Your word. DON\'T TELL THIS TO ANYONE!\n')
print('\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
      '\n\n\n\n\nThe word is', len(word), 'letters long.')
output = ['_'] * len(word)


def print_output():
    print()
    print(''.join([x+' ' for x in output]))


for w in range(1, 9):
    print_output()
    letter = input('Guess a letter \n')
    if letter == word:
        print('You win!')
        break
    elif letter in word:
        print('Correct', letter)
        for i, x in enumerate(word):
            if x is letter:
                output[i] = letter
    if '_' not in output:
        print('You win!')
        break
    else:
        print('Incorrect', ' ', letter)

Solution 4:[4]

Use a list and replace anything you want inside like:

ml = ["tom","tim"]
fw = (ml[0])
fwl = list(fw)
no = 0
for i in range(0,len(fwl)):
    a = (fwl[no])
    if a == "o":
        fwl[0] = "i"
    no = no+1
o = ""
p = o.join(fwl)
print(p)

In short use:

your list[index for replacement to be done] = replacement  


    

Solution 5:[5]

The use of printing empty lines before the actual print would give the illusion that you are over writing the underscores. I used os to find the tty/terminal height and print that many empty lines.

"\b" cannot be used in this instance as a newline required for input is used.

import os
import random # Needed to make a random choice


WORDS= ("variable", "python", "turtle", "string", "loop")

word= random.choice(WORDS)#chooses randomly from the choice of words
print  ("The word is", len(word), "letters long.")# used to show how many letters are in the random word


def guess_word(word, max_attempt, attempt, guessed_chars=[]):
    prompt_string="Guess a letter "
    rows, columns = os.popen('stty size', 'r').read().split()
    print "\n"*int(columns)
    print("Welcome to Python Hangman")
    complete = 1
    for char in word:
        if char in guessed_chars:
            print char,
        else:
            print '_',
        complete = 0
    if complete == 1:
        print "\nYou won!"
        return
    print "Attempts left = "+ str(max_attempt - attempt + 1)
    letter = raw_input(prompt_string)
    if letter in word:
        guessed_chars.append(letter)
    else:
        print ' '

    if (attempt<max_attempt and len(guessed_chars) <= len(word)):
        guess_word(word, max_attempt, attempt+1, guessed_chars)
    else:
           print "You lose :(. Word is "+word

guess_word(word, len(word), 0)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Padraic Cunningham
Solution 2
Solution 3 CodedCuber
Solution 4 William Baker Morrison
Solution 5 Anshu Prateek