Q:

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

Given a w x h sized grid, produced 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?

A:

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.

