improper output while printing coloured letter of a word in a wordle game in python

Question:

import random
import sys   
from termcolor import colored

def print_menu():
    print("welcome to wordle !")
    print("type a 5 letter word and hit entern")

def read_random_word():
    with open('E:kartikeypythonprogramswordlewords.txt') as word_database:
        #splitline so every line in the text file gets stored as a diferent array
        #block and since here every line is basically a word so every word gets stored as an individual array.
        words=word_database.read().splitlines()
        return random.choice(words).lower()
print_menu()
play_again=""

while play_again !="quit":  
    word=read_random_word()
    for attempt in range(1,7):
        guess=input().lower()
        for i in range(min(len(guess),5)):
            if guess[i]==word[i]:
                #end="" is used so it doesnt go to a new line after printing the coloured letter
                print(colored(guess[i],'green'), end="")  
            elif guess[i] in word:
                print(colored(guess[i],'yellow'), end="")
            else:
                print(guess[i] , end="")  
        if guess==word:
                print((f"nyou got the word in {attempt} try"))
                break
        elif attempt==6:
            print(f"sorry the wordle was {word}")
play_again=input("type quit to exit otherwise click enter")

the error im getting is:

welcome to wordle !
type a 5 letter word and hit enter

poise
?[32mp?[0m?[32mo?[0m?[32mi?[0m?[32ms?[0m?[32me?[0m
you got the word in 1 try

When I don’t use the colored() function this error is not appearing but gives this issue when using it.

Asked By: horsei_

||

Answers:

When i don’t use the colored() function this error is not appearing but gives this issue when using it.

The issue is that what you see are escape sequences used to set the color of a single letter in the terminal output.

Apparently you use a console/terminal which doesn’t support escape sequences or run your code in some other environment which output does not support coloring.

Your code runs perfectly and colors the hit letters in the output. Well done! Just run it in a console supporting escape sequences and enjoy!

Happy coding 🙂

CodeIsRunningOK

Below a version of your code with following changes:

  • Reading from text file with words to guess is done only once and not each time next word has to be chosen
  • Integer constants are moved out of the inner part of the code and given values at the beginning of script
  • There is a class for automated user input, so while playing around with colors it’s not necessary to provide any input to see how the user interface looks like
  • colored() function is used with explicit parameter names to make it simple to see what goes where
  • The script doesn’t need to access a file to be run and runs as it is utilizing implemented automated user input

# wordle.py 
# https://stackoverflow.com/questions/73555383/improper-output-while-printing-coloured-letter-of-a-word-in-a-wordle-game-in-pyt
# requires module 'termcolor' : 
import random
import sys   
from termcolor import colored

# --- wordle game parameter:
WORD_LENGTH      = 5
NO_OF_ATTEMPTS   = 7
#                  ^-- to avoid constants spread within the code 
# --- v-- input/output automation constants
AUTOMATED_INPUT  = True  # False
MAX_NO_OF_ROUNDS = 3 # set to negative value for an unlimited number
WORDS_FROM_FILE  = False # True # False
REVEAL_THE_WORD_TO_GUESS = True
# ---
# v-- automated input text
mlnTextIO_mlnText = """
green
blues
mouse
quit
quit"""
# v-- words to guess
words = """
mouse
mouse
mouse""".splitlines()
# --- 
class mlnTextIO():
    def __init__(self, mlnText):
        self.lst_mlnText = mlnText.split('n')
        self.lineNo = 0
        self.lenText=len(self.lst_mlnText)
    def input(self, promptText='without promptText'):
        # print('n','input() called:', promptText)
        if promptText == 'without promptText':
            pass
        else:
           print(promptText)
        lineNo = self.lineNo
        self.lineNo += 1
        if promptText == "type quit to exit otherwise click enter":
            if lineNo < self.lenText: 
                if self.lst_mlnText[lineNo] != "quit": 
                    self.lineNo -= 1
                    return 'n'
                else: 
                    return 'quit'
            else: 
                return 'quit'                
            #:if/else
        #:if
        if  lineNo < self.lenText:
            print(  self.lst_mlnText[lineNo])            
            return  self.lst_mlnText[lineNo]        
        else:
            return 'No further automated user input available.'
#:def
if AUTOMATED_INPUT: 
    input = mlnTextIO(mlnTextIO_mlnText).input

def print_menu():
    print(f"  Welcome to wordle !")
    print(f"  Type a {WORD_LENGTH} letter word and hit entern")

def get_random_word():
    global WORDS_FROM_FILE, words
    if WORDS_FROM_FILE: 
        with open('words.txt') as word_database:
            # splitline so every line in the text file gets stored as a diferent array
            # block and since here every line is basically a word so every word gets stored as an individual array.
            words=word_database.read().splitlines()
        WORDS_FROM_FILE = False
        # ^-- prevents file operation each time a word is requested
    return random.choice(words).lower()

print_menu()
play_again=""

maxNoOfRounds = MAX_NO_OF_ROUNDS
while play_again !="quit" and maxNoOfRounds > 0:

    if maxNoOfRounds == 0:
        print(colored(text="  Restart the program to play again", color='green', on_color='on_white', attrs=['bold']))
    maxNoOfRounds -= 1    
    
    word=get_random_word()
    if REVEAL_THE_WORD_TO_GUESS: 
        print(f'  Wordle word to guess is: "{word}"') # reveals the word to guess

    for attempt in range( 1, NO_OF_ATTEMPTS):
        guess=input().lower()
        for i in range( min(len(guess), WORD_LENGTH) ):
            if guess[i]==word[i]:
                #end="" is used so it doesnt go to a new line after printing the coloured letter
                print(colored(text=guess[i], color='white' , on_color='on_grey', attrs=['bold']),  end="")  
            elif guess[i] in word:
                print(colored(text=guess[i], color='white' , on_color='on_grey'),                  end="")
            else:
                print(colored(text=guess[i], color='red'   , on_color='on_grey', attrs=['bold']) , end="")  
        print()        
        if guess==word:
            print(f"  You got the word using {colored(text=str(attempt), color='white',on_color='on_grey', attrs=['bold'])} attempts")  
            break
        elif attempt==6:
            print(f"  Sorry, but the wordle was {colored(text=word, color='white',on_color='on_grey', attrs=['bold'])}")
        #if/elif
    #:for attempt
    play_again=input("  Type quit to exit otherwise click enter")
#: while play_again

The wordle when run in a console/terminal supporting escape sequences for colors and text layout looks now as follows:

enter image description here

The meaning of colors in the wordle output is as follows:

  • bold highlighted white letters are in the proper position.
  • white, not bold highlighted letters mean the letter is in the word to guess
  • red bold letters are not in the word to guess

And … if you want to play it instead of playing around with its code just

  • put the words to guess into words
  • change REVEAL_THE_WORD_TO_GUESS = True to False
  • and AUTOMATED_INPUT = True to False
Answered By: Claudio

finally sorted the code out ,added sys to clear up the output screen after each input guess and replace it with the coloured output for a cleaner interface.

import random
import sys
# to clear the terminal and make the game user friendly
import termcolor
from colorama import Fore, Back, Style, init
from termcolor import colored
init(convert=True)


def print_menu():
    print("welcome to wordle !")
    print("type a 5 letter word and hit entern")


def read_random_word():
    with open('E:kartikeypythonprogramswordlewords.txt') as word_database:

        # splitline so every line in the text file gets stored as a diferent array
        # block and since here every line is basically a word so every word gets stored as an individual array.

        words = word_database.read().splitlines()
        return random.choice(words).lower()


print_menu()
play_again = ""

while play_again != "quit":

    word = read_random_word()

    for attempt in range(1, 7):

        guess = input().lower()

        sys.stdout.write('x1b[1A')
        sys.stdout.write('x1b[2K')

        for i in range(min(len(guess), 5)):
            if guess[i] == word[i]:

                # end="" is used so it doesnt go to a new line after printing the coloured letter

                print(colored(guess[i], 'green'), end="")
            elif guess[i] in word:
                print(colored(guess[i], 'yellow'), end="")

            else:
                print(guess[i], end="")

        print()

        if guess == word:
            print((f"nyou got the word in {attempt} tries !"))
            break
        elif attempt == 6:
            print(f"sorry the wordle was {word} :(")
    play_again = input("ntype quit to exit otherwise click enter")

Output:
colouredoutput

Answered By: horsei_
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.