Home > database >  Print an item in a list in a color based on the item
Print an item in a list in a color based on the item

Time:08-24

I've written a script for a very clunky version of minesweeper.

The player selects the square they want to reveal based on co-ordinates (like in chess) and the board is updated with the values showing how many mines are in the squares around the chosen co-ordinates. The player can also flag where they think a mine is, which shows up as an "f".

How the player board looks after the player has selected a few squares

Unfortunately this is unreadable which makes it very slow going. So I was hoping to update the code with some colour, where all "2"s are printed in blue, all "3"s in red etc. I have all the components; I've downloaded colorama but I can't get it to work. I'm stuck with the rest.

Code that prints the initial empty grid:

difficulty_dictionaries = {
    1 : {
        "difficulty": "Beginner",
        "x_axis": 8, 
        "y_axis": 8, 
        "mine_no": 10
    },
    2 : {
        "difficulty": "Intermediate",
        "x_axis": 16, 
        "y_axis": 16, 
        "mine_no": 40
    },
    3 : {
        "difficulty": "Expert",
        "x_axis": 26, 
        "y_axis": 16, 
        "mine_no": 98
    }
}   

ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

def set_difficulty():
    print ("Please select difficulty level by entering either 1, 2 or 3 based on the corresponding difficulty")
    diff_input = input ("1. Beginner: \n2. Intermediate: \n3. Expert: ") 
    
    return difficulty_dictionaries[int(diff_input)]

def set_user_board():
    grid = []
    grid.append("  ")
    for set_x in range(diff_dict["x_axis"]):
        grid.append(ALPHABET[set_x])
    grid[0] = (" ".join(grid))

    del grid[1:]
    grid.append("  "   " "   ("- ")*(diff_dict["x_axis"]))
    for set_y in range(diff_dict["y_axis"]):
        grid.append(str(set_y   1)   " |"   (" "   "|")*diff_dict["x_axis"]) if set_y < 9 else grid.append(str(set_y   1)   "|"   (" "   "|")*diff_dict["x_axis"])
        grid.append("   "   ("- ")*diff_dict["x_axis"])
    return(grid)

def print_grid():
    print('\n'.join(' '.join(map(str, b)) for b in grid))
    return

diff_dict = set_difficulty()
grid = set_user_board()
print_grid()

Output:

Empty player grid

As squares are selected, the values are taken from another reference list of lists and inserted into grid at the relevant point.

I stole the part of the code that prints the grid from another answer on SO but I don't know how it works. I have also tried this:

def print_grid():
    for x in grid:
        print(*x)
    return

which is far more understandable. But when I try to apply the colour to the items in the list I'm encountering some problems - mostly with the *.

def print_grid():
    for x in grid:
        print(f"{Fore.RED}"   x)

    return

That prints an all red grid - but it's squished: Squished, red grid

CodePudding user response:

First explanations:

You have 2D grid and x can means row with many values -

When you use print(*x) then it runs it as print(x[0], x[1], ...) so it prints many separated elements and print() automatically add space between elements. You could say that every comma , adds space in output.

Try print("A", "B") and you get "A B" instead of "AB"

When you print(f"{Fore.RED}" x) then you print one string (probably row converted to string) and print() doesn't know that it needs spaces between elements. You have to format this string with spaces before using print()


It would be simpler to keep grid as 2D grid (without converting rows to string) and use nested for-loops `(with better names for variables)

for row in grid:
    for item in row:
        print(item, end=' ')
    print() # go to next line

And now you can use if/else to print it in different colors

for row in grid:
    for item in row:
        if item in (' ', '-', '|'):  # or `if item in " -|"`
            color = Fore.RED
        elif item in ('1', '2', '3', '4', '5'): # or `if item in "12345"`
            color = Fore.GREEN
        else: 
            color = Fore.WHITE
        print(f"{color}{item}", end=' ')   # I add `space` instead of `\n` as `end` 
    print() # go to next line

Minimal working example:

from colorama import Fore, Back, Style

grid = [
    [' ', '-', ' ', '-', ' ', '-', ' '],
    ['|', '1', '|', ' ', '|', ' ', '|'],
    [' ', '-', ' ', '-', ' ', '-', ' '],
    ['|', 'X', '|', '2', '|', ' ', '|'],
    [' ', '-', ' ', '-', ' ', '-', ' '],
    ['|', ' ', '|', 'O', '|', '3', '|'],
    [' ', '-', ' ', '-', ' ', '-', ' '],
]

# ---

# letters

print(end='   ')
for item in 'ABC':
    print(f" {Fore.WHITE   Style.BRIGHT}{item} ", end=' ')
print()

# rows 

for number, row in enumerate(grid, 1):
    
    # row's number
    
    if number % 2 == 1:
        print("  ", end='')
    else:
        print(f"{Fore.WHITE   Style.BRIGHT}{number//2} ", end='')

    # row's grid
    for item in row:
        if item in (' ', '-', '|'):  # or `if item in " -|"`
            color = Fore.RED   Style.BRIGHT
        elif item in ('1', '2', '3', '4', '5'): # or `if item in "12345"`
            color = Fore.GREEN   Style.BRIGHT
        elif item in ('X', 'O'): # or `if item in "12345"`
            color = Fore.BLUE   Style.BRIGHT
        else: 
            color = Fore.WHITE   Style.BRIGHT
        print(f"{color}{item}", end=' ')   # I add space at the end of `f-string`
    print() # go to next line

Result (with colors) in console:

enter image description here


EDIT:

I made more universal version which use grid without lines -

from colorama import Fore, Back, Style
import string

grid = [
    ['1', 'D', ' ', 'A', '4'],
    ['E', '2', '5', ' ', 'B'],
    ['6', 'F', '3', 'C', ' '],
]

# ---

HEIGTH = len(grid) 
WIDTH  = len(grid[0])

LETTERS = string.ascii_uppercase[:WIDTH]

# --- columns letters ---

print(end='   ')
for item in LETTERS:
    print(f' {Fore.WHITE   Style.BRIGHT}{item}  ', end='')
print()  

# --- rows ---

for number, row in enumerate(grid, 1):
    
    # top line
    
    print(f'{Fore.RED   Style.BRIGHT}   '   ' -  '*WIDTH)

    # row with data
    
    # number
    print(f'{Fore.WHITE   Style.BRIGHT}{number} ', end='')
    
    # first left line
    print(f'{Fore.RED   Style.BRIGHT}| ', end='')

    # data with right line
    for item in row:
        if item in '123':
            color = Fore.GREEN   Style.BRIGHT
        elif item in '456':
            color = Fore.YELLOW   Style.BRIGHT
        elif item in 'ABCDEF': # or `if item in "12345"`
            color = Fore.BLUE   Style.BRIGHT
        else: 
            color = Fore.WHITE   Style.BRIGHT
            
        print(f"{color}{item} {Fore.RED   Style.BRIGHT}| ", end='')   # I add space at the end of `f-string`
        
    print() # go to next line

# --- last (bottom) line ---

print(f'{Fore.RED   Style.BRIGHT}   '   ' -  '*WIDTH)

Result (with colors) in console:

enter image description here

  • Related