开发者

How to draw a line of characters in a grid (nested lists)

开发者 https://www.devze.com 2023-02-08 20:05 出处:网络
Given a w x h sized grid, produc开发者_Go百科ed in the following way self.grid = [ [\'-\'] * self.w ] * self.h

Given a w x h sized grid, produc开发者_Go百科ed in the following way

self.grid = [ ['-'] * self.w ] * self.h

I wish to "draw" a "line" of characters between two points in said grid. The following code is what I've come up with

def line( self, char, (x1, y1), (x2, y2) ):
    self.point( char, (x1, y1) )

    x = x1 + cmp( x2, x1 )
    y = y1 + cmp( y2, y1 )
    while x != x2 or y != y2:
        self.point( char, (x, y) )
        x = x + cmp( x2, x )
        y = y + cmp( y2, y )

    self.point( char, (x2, y2) )

Where the point() function simply fills in a single point in the grid with char.

This works like a charm for straight lines and perfect diagonals. It works for "crooked" lines too, in the sense that it doesn't throw errors, but it doesn't exactly look like a line between two points, more like... I don't know, a hockey stick.

For example, given a 10x7 grid and the call

line( 'X', (1,1), (5,9) )

I get

----------
-X--------
--X-------
---X------
----X-----
-----XXXXX
----------

What I'd like is probably something more like

----------
-X--------
---X------
-----X----
-------X--
---------X
----------

How would I do this, while not breaking it for straight lines and perfect diagonals in the process? Do I need two distinct pieces of code to handle the two cases, or can one algorithm do both?


You should be using Bresenham's line algorithm, if you insist on programming this yourself at all. Furthermore, be careful about initialising the grid like this:

grid = [ ['-'] * self.w ] * self.h

because of edning up with self.h copies of the same list:

grid = [ ['-'] * 3 ] * 3 
grid[0][0] = 'X'
print grid
# [['X', '-', '-'], ['X', '-', '-'], ['X', '-', '-']]

Use

grid = [['-'] * self.w for ignored in xrange(self.h)]

or Numpy arrays instead.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号