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.
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 🙂
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:
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
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
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.
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 🙂
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:
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
toFalse
- and
AUTOMATED_INPUT = True
toFalse
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