A function that returns a string which resemples a playing board in python

Question:

I want to write a function that returns a square playing board containing '*' and ' ' based on the input number.

The intended output should be like this:

board_of_5 = (
    ' * * n'
    '* * *n'
    ' * * n'
    '* * *n'
    ' * * n'
)
    
board_of_10 = (
    ' * * * * *n'
    '* * * * * n'
    ' * * * * *n'
    '* * * * * n'
    ' * * * * *n'
    '* * * * * n'
    ' * * * * *n'
    '* * * * * n'
    ' * * * * *n'
    '* * * * * n'
)

Here is my current code, which produces an output on a single line, and with no offset on alternating lines:

def get_playing_board(num):
    string = ''
    for i in range(num):
        for j in range(num):
            if j % 2 == 0:
                string += ' '
            elif j % 2 != 0:
                string += '*'
        print(string)
    return string

get_playing_board(5)

How do I introduce an offset and newlines?
How do I loop over the rows?

My idea is to add '*' or blank space based on even or odd numbers and loop for each row and col.

However, I cannot get the intended chart board.

Asked By: mmmmmm

||

Answers:

You can use:

def get_playing_board(num):
    import math
    n = math.ceil(num/2)
    s = '* '*n
    return 'n'.join(([" "+s[:num-1], s[:num]]*n)[:num])
    
print(get_playing_board(5))

print(get_playing_board(10))

Output:

# print(get_playing_board(5))
 * * 
* * *
 * * 
* * *
 * * 

# print(get_playing_board(10))
 * * * * *
* * * * * 
 * * * * *
* * * * * 
 * * * * *
* * * * * 
 * * * * *
* * * * * 
 * * * * *
* * * * * 
Answered By: mozway

The thing that goes into a given row, column depends on the relationship of the row and column index. Specifically, if both are even or odd (have the same parity), the element will be ' '. If they are not the same parity, the element will be a '*'.

The simplest way to check parity is with

if (i % 2) == (j % 2):

The parity of a number is encoded in the last bit: 1 for even, 0 for odd. You can therefore check for sameness using the XOR operator:

if (i ^ j) & 1:

In this case & 1 removes the last bit using bitwise AND.

To insert a newline at the end of each row, you just need to add that at the end of the outer loop:

def get_playing_board(num):
    board = ''
    for i in range(num):
        for j in range(num):
            board += ' *'[(i ^ j) & 1] # The index expression is 0 or 1
        board += 'n'
    return board

get_playing_board(5)

There is a clever alternative to manually generating each row. Instead, you can generate a string that is one element longer than num and grab a subset for each row:

def get_playing_board(num):
    row = ' *' * ((num + 2) // 2)
    board = ''
    for i in range(num):
        board += row[i % 2:num + i % 2] + 'n'
    return board

You can write either approach as a one-liner:

'n'.join(''.join(' *'[(i ^ j) & 1] for j in range(num)) for i in range(num))
'n'.join((' *' * ((num + 2) // 2))[i % 2:num + i % 2] for i in range(num))

I don’t particularly recommend the bottom two approaches.

Answered By: Mad Physicist
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.