How to append strings from a loop to a single output line?

Viewed 84

So I am trying to make a text-based game of connect-4 for the purposes of better understanding Python and how it actually works.

Short version

  • How can I append printed text from every run-through of a while loop to a print output that exists just before the while loop
  • Out of the two methods seen below (The work in progress and the current successfully working one) which is a better practice of executing the desired output?

Long version

I am trying to use a looping system to print out an array in an evenly spaced and aesthetically pleasing format after every turn is taken, so users have clear feedback of what the current board looks like before the next turn is taken. To do this I want to be able to have lines of code that are as small as possible for making it easier to read the code itself. Although this might not be the best practice for executing this scenario I want to understand this way of coding better so I could apply it to future projects if need be.

In terms of the actual execution, I am trying to use a while loop to append 7 positions of an array one after another in the same output line for array positions that are in the same row. after this, I want to print the next row on the line below the previous one as seen in the code below "Desired output".

Thank you in advance for your answers, suggestions and comments.

Work in progress

import numpy as np
ARRAY = np.zeros(shape=(6, 7), dtype = 'int8')
# In reality I will be using an empty array that gradually gets populated
# Zeros are used for ease of asking the question

def Display_board():
    i = 0
    while i < 7:
        j = 0
        print("  ", end = " ")
        while j < 8:
            print(str(ARRAY[i][j]))
            j += 1
        i += 1

work in progress output

 0
   0
0
0
0
0
0
0
   0
0
0
0
0
0
0
# It goes on but didn't include as it would take up unnessary space in the question

If I change the line that prints the array to as follows I get another undesired output

print(str(ARRAY[i][j]), end = " ")

#output
  0 0 0 0 0 0 0    0 0 0 0 0 0 0    0 0 0 0 0 0 0    0 0 0 0 0 0 0    0 0 0 0 0 0 0    0 0 0 0 0 0 0

Current working method - Gives desired output

def Display_board():
   for i in range(6):
       print("   " + str(ARRAY[i][0]) + "  " + str(ARRAY[i][1]) + "  " + str(ARRAY[i][2]) \
       + "  " + str(ARRAY[i][3]) + "  " + str(ARRAY[i][4]) + "  " + str(ARRAY[i][5])\
       + "  " + str(ARRAY[i][6]))

Desired output

  0  0  0  0  0  0  0
  0  0  0  0  0  0  0
  0  0  0  0  0  0  0
  0  0  0  0  0  0  0
  0  0  0  0  0  0  0
  0  0  0  0  0  0  0
3 Answers

The simple fix is to use end=' ' on the print inside the while loop on j and then add a print() after it:

def Display_board():
    i = 0
    while i < 6:
        j = 0
        print("  ", end = " ")
        while j < 7:
            print(str(ARRAY[i][j]), end=" ")
            j += 1
        print()
        i += 1

Output:

   0 0 0 0 0 0 0 
   0 0 0 0 0 0 0 
   0 0 0 0 0 0 0 
   0 0 0 0 0 0 0 
   0 0 0 0 0 0 0 
   0 0 0 0 0 0 0 

You can also use a nested list comprehension with join to achieve the output in one line:

def Display_board():
    print('\n'.join(' '.join(['  '] + [str(ARRAY[i][j]) for j in range(7)]) for i in range(6)))

FINAL FINAL EDIT: Fixed the code to ACTUALLY use the width setting!

FINAL EDIT :)

If the numbers can be greater than 9 you can use the wonderful python f-string formatting option:

ARRAY = [
    [1, 2, 3, 4, 5],
    [10, 20, 3, 4, 5],
    [1, 2, 30, 4, 5],
    [1, 2, 3, 4, 500],
]

width = 3
for row in ARRAY:
    print(" ".join(f'{x:>{width}}' for x in row))

which produces:

  1   2   3   4   5
 10  20   3   4   5
  1   2  30   4   5
  1   2   3   4 500

EDIT:

This, while less intuitive is shorter and arguably more pythonic:

for row in ARRAY:
    print(" ".join(map(str, row)))

This will work for any ARRAY:

ARRAY = [
    [1, 2, 3, 4, 5],
    [1, 2, 3, 4, 5],
    [1, 2, 3, 4, 5],
    [1, 2, 3, 4, 5],
]

for row in ARRAY:
    for n in row:
        print(n, end = " ")
    print()

poduces:

1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5

Edited to remove "" in print("")

came up with two functions

first one:

def display_board1(board):

    m, n = board.shape

    for i in range(m):
        for j in range(n):
            print(board[i][j], end= ' ')
        print()

    return 1

second one:

def display_board2(board):

    s = board.__str__()
    s = s.replace('[', ']')
    s = s.replace(']', '')
    s = ' ' + s

    print(s)

    return 1

the return 1 statements are just for plotting, delete them if you dont want them

here's their performance with respect to input size display_board2() is faster and more stable

import perfplot

bench = perfplot.bench(
    setup= np.zeros,
    kernels= [
        display_board1,
        display_board2
    ],
    n_range= [(i, i) for i in range(10)],
)

bench.show()

enter image description here

Related