2
\$\begingroup\$

This is a game in which a sequence of 4 characters is displayed to the player, one at a time with a delay between them. Then the player must input that sequence as it was displayed.

Sequences are displayed until input is incorrect.

The characters composing the sequences are chosen at random and they are all lines.

__all__ = []

import random
import time

from colorama import deinit, init

MSG_ASK = 'What was the sequence? '
MSG_CORRECT = '\033[32mCorrect!\033[0m'
MSG_INCORRECT = '\033[31mIncorrect\033[0m'


def main():
    k = 4

    lines = r'|\-/'

    seconds = 1

    init()

    while True:
        s = ''

        sequence = random.choices(lines, k=k)
        sequence = ''.join(sequence)

        for i in range(k):
            if not i:
                s = ''
            elif i == 1:
                s = ' '
            else:
                s = i * ' '

            print(s, sequence[i], end='\r')
            time.sleep(seconds)

        print(f'{s}  ')

        if input(MSG_ASK) == sequence:
            print(MSG_CORRECT)
        else:
            print(MSG_INCORRECT)
            break

    deinit()


if __name__ == '__main__':
    main()
\$\endgroup\$
3
\$\begingroup\$

Using __all__ = [] is mostly useless in the main program, and should probably be removed.


This is hard to read:

MSG_CORRECT = '\033[32mCorrect!\033[0m'
MSG_INCORRECT = '\033[31mIncorrect\033[0m'

This is much easier:

from colorama import Fore

MSG_CORRECT = Fore.GREEN + 'Correct!' + Fore.RESET
MSG_INCORRECT = Fore.RED + 'Incorrect' + Fore.RESET

Note: Style.RESET_ALL would be an exact translation of \033[0m. Adjust as desired.


You could pull your loop body out into separate functions:

def generate_random_sequence(length: int, characters: str) -> str:
    """
    Generate a random sequence of characters.
    """

    return ''.join(random.choices(characters, k=length))

def show_sequence(sequence: str, seconds_per_character: float) -> None:
    """
    Display a sequence to the user, one character at a time, on one line,
    using the given delay between characters.

    After the last character has been shown, clear the line.
    """

    for i, ch in enumerate(sequence):
        print(' ' * i, ch, end='\r')
        time.sleep(seconds_per_character)

    print(' ' * len(sequence), ' ')

I've done several things here:

  • type-hints and a """docstring""" have been added
  • sequence is computed in one step
  • removed the s variable, since it can be directly computed as ' ' * i
  • looped directly over the sequence, using enumerate to keep track of the index.
  • speed, length and characters are all arguments to the functions, so the challenge could become programmatically harder (ie, faster or longer)

With the above function, the main loop becomes simpler:

def main():
    k = 4
    lines = r'|\-/'
    seconds = 1

    init()

    while True:
        sequence = generate_random_sequence(k, lines)
        show_sequence(sequence, seconds)

        guess = input(MSG_ASK)
        if guess == sequence:
            print(MSG_CORRECT)
        else:
            print(MSG_INCORRECT)
            break

    deinit()
\$\endgroup\$

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.