1

I am trying to write some code which will overwrite its previous output e.g. the original output is "1" but the "1" is replaced with a "2". This makes it look as though the "1" had never been outputted in the first place. I have a list of lists called board, I convert this list into a multi-line string using this code:

rendered_board = ""
for y in range(board_height):
    for x in range(board_width):
        rendered_board += board[y][x]

    rendered_board += "\n"

I get the string I want, However, I want to be able to update this string with a new one and have it replace the old.

Example output :

+-------+                      +-------+
|       |  *gets replaced by*  |       |
|       | -------------------> |   *   |
|       |                      |       |
+-------+                      +-------+

Currently I have been trying to do this by using end="\r" e.g.

print(rendered_board, end="\r")
update_board()
print(rendered_board, end="\r")

This has resulted in this output:

+-------+
|       |
|       |
|       |
+-------+
+-------+
|       |
|   *   |
|       |
+-------+
1
  • Can you add boardlegth, board and boardheight values? Commented Jun 9, 2017 at 21:46

4 Answers 4

5

That's not as trivial as you might think. You can use \r (carriage return) to return back to the current line, or \b to move a character back - both reminiscent from the early electronic typewriter days - but to go around a screen you need more control over the terminal. Sure, you can call os.system('clear') on *nix / os.system('cls') on Windows to clear the whole screen and draw it again, but that's just not elegant.

Instead, Python provides the curses module designed just for that purpose. Here's a simple demonstration on how to use it:

import curses
import time

console = curses.initscr()  # initialize is our playground

# this can be more streamlined but it's enough for demonstration purposes...
def draw_board(width, height, charset="+-| "):
    h_line = charset[0] + charset[1] * (width - 2) + charset[0]
    v_line = charset[2] + charset[3] * (width - 2) + charset[2]
    console.clear()
    console.addstr(0, 0, h_line)
    for line in range(1, height):
        console.addstr(line, 0, v_line)
    console.addstr(height-1, 0, h_line)
    console.refresh()

def draw_star(x, y, char="*"):
    console.addstr(x, y, char)
    console.refresh()

draw_board(10, 10)  # draw a board
time.sleep(1)  # wait a second
draw_star(6, 6)  # draw our star
time.sleep(1)  # wait a second
draw_star(6, 6, " ")  # clear the star
draw_star(3, 3)  # place the star on another position
time.sleep(3)  # wait a few seconds

curses.endwin()  # return control back to the console

Of course, you can get far fancier than this, but it should give you the idea on how to utilize it.

Sign up to request clarification or add additional context in comments.

1 Comment

I dont need anything particularly fancy os.system("cls") may not be the update a single char and leave the rest that i would've originally wanted but it does the job and that's the most important thing.
1

You haven't specified if you need solution working on Linux or Windows.

For Linux you can use zwer answer. However curses module is not available on Windows.

Windows cmd is very simple and doesn't understand advanced formatting. You have clear and redraw the whole window to get animation.

Here is an example of a star moving randomly on board for 20 frames of animation:

import os
import time
import random
import copy


board = [['+', '-', '-', '-', '-', '-', '-', '-', '-', '+'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
 ['+', '-', '-', '-', '-', '-', '-', '-', '-', '+']]


for i in range(20):
    os.system('cls')
    frame = copy.deepcopy(board)
    frame[random.randint(1, 8)][random.randint(1, 8)] = '*'
    print('\n'.join([''.join(i) for i in frame]))
    time.sleep(1)

1 Comment

There's UniCurses as a drop-in replacement for using on Windows.
0

I'd suggest you using something like

print(PrintBoard, end='')
for x in len(PrintBoard):
    print("\b")
UpdateBoard()
print(PrintBoard, end='')

This solution uses ASCII backspace escape character \b. Also, I didn't see a point in using end="\r", so I replaced it with end="".

1 Comment

\b and \r will not work for overwriting/rescanning a multi-line output.
-1

I would split each board it's own list like this:

a = ["+-------+", 
     "|       |",
     "|       |",
     "|       |",
     "+-------+"]

b = ["+-------+",
     "|       |",
     "|   *   |",
     "|       |",
     "+-------+"]

div = ["            ",
       "  rep with  ",
       " -------->  ",
       "            ",
       "            "]

Then to print you can just zip them together and print..

for a, div, b in zip(a, div, a):
    print(a, div, b)

+-------+            +-------+
|       |  to this   |       |
|       | -------->  |   *   |
|       |            |       |
+-------+            +-------+

1 Comment

This does not answer the question. OP wants to print one square and then print another square, which replaces the old

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.