On 01/02/2015 02:21 AM, Steven D'Aprano wrote:
Fixing the mangled formatting, as best as I am able (and can be
bothered).

On Thu, Jan 01, 2015 at 11:48:18PM -0500, WolfRage wrote:

class GameTile():
     def __init__(self, id, **kwargs):
         # id is (X,Y)
         self.id = id

What is the purpose of the **kwargs? It doesn't get used, it just
silently ignores them.
These are Kivy Buttons, when GameTile is written as a whole. But I broke it out in order to solve this specific problem.

Actually, what is the purpose of this GameTile class? It has no methods
apart from the constructor. That is a sign of a class that isn't pulling
its weight, its not doing anything. All the other code in your program
looks inside the GameTile and accesses self.id directly. This is a sure
sign of a class that doesn't need to exist.
It manages the on_press, on_release, and the image currently being displayed on the displayed tiles. But that is all that it does. But I still think I have to have it, since it is a button which inherits from Kivy's Button class.

It may be better to give this at least a __str__ method, so if
nothing else you can print it without looking inside:
Excellent idea, I will add this __str__ method so that I can print it directly.


class GameTile():
     def __init__(self, x, y):
         self.x = x
         self.y = y
     def __str__(self):
         return "%d, %d" % (self.x, self.y)



class GameGrid():
     def __init__(self, **kwargs):
         self.cols = 7
         self.rows = 8
         # grid is 2d array as y, x ie [y][x].
         self.grid = [[None] * self.rows for i in range(self.cols)]

Why do you have GameTiles use X,Y but the grid uses the opposite order,
Y,X? This is going to cause confusion. I'm already confused!
Well my lack of understanding as to how to implement the 2d list resulted in the row and col count being opposite, but I see now simply re-arranging those would fix this problem and the resulting hacks in the rest of the code, as it goes back and forth.


     def make_grid(self):
         for row in range(0, self.rows):
             for col in range(0, self.cols):
                 self.grid[col][row] = GameTile(id=str(row) + ',' + str(col))

No need to write range(0, Whatever), since range defaults to 0. Better
to write range(Whatever).
Good point.

Why does the GameTile record the coordinates as strings?

I would prefer something like this:

     def make_grid(self):
         for row in range(self.rows):
             for col in range(self.cols):
                 self.grid[col][row] = GameTile(row, col)
I did this when I was writing the previous Kivy code, the coordinates actually serve as the id which is a Kivy variable that I am able to quickly lookup via there method, but I have mostly replaced this lookup with the new 2d list lookup now and so it is no longer necessary (At least I think, I will have to see how much of my previous code relied on this functionality and then weed it out).
http://kivy.org/docs/api-kivy.uix.widget.html#kivy.uix.widget.Widget.id


although it looks strange due to the backwards ordering of col/row.


Your __init__ method should automatically call make_grid. That is:

     def __init__(self, **kwargs):
         self.cols = 7
         self.rows = 8
         # grid is 2d array as y, x ie [y][x].
         self.grid = [[None] * self.rows for i in range(self.cols)]
         self.make_grid()


Actually, even better will be to move the self.grid = ... line out of
the __init__ method, and make it part of make_grid. Since it is part of
making the grid.
The making of the grid was put in the update because of Kivy, literally. I did not want to delay the display of the next screen while I was building my linked list. The previous linked list code was even bigger than what I posted initially and the execution of this code took around 1-2 seconds which caused the previous screen to hang. To prevent that I called update as a task to happen after the screens had flipped. But now that the grid creation is so fast, I can do this and no delay will be experienced.


     def print_by_row(self):
         for col in range(0, self.cols):
             for row in range(0, self.rows):
                 print(self.grid[col][row].id)

This now becomes:

     def print_by_row(self):
         for col in range(0, self.cols):
             for row in range(0, self.rows):
                 print(self.grid[col][row])
That is a cool feature with the __str__ method. haven't really learned to use the "Magic" or "special" methods yet. But will definitely start too now.


since GameTiles now know how to print themselves. Likewise for this:

     def print_by_col(self):
         for row in range(0, self.rows):
             for col in range(0, self.cols):
                 print(self.grid[col][row])


Another simplification here:


     def check_bounds(self, x, y):
         return (0 <= x < self.rows) and (0 <= y < self.cols)



Your lookup_node method returns a GameTile or False on failure:

     def lookup_node(self, x, y, ):
         if not self.check_bounds(x, y):
             return False
         return self.grid[y][x]

I'm not sure about that design. I wonder whether it would be better to
return None, or raise an exception.

You have a lookup_node method that checks the bounds, but you don't seem
to use it anywhere. Why does it exist?
Both are very good questions. What is the best speed wise way to handle error returns consistently, but I can return an exception or else I would have to catch it, because I do not want the game crashing on the player. This lookup method is used when finding nodes to the North, South, East, and West of a selected tile. However searching the entire grid for matches is so fast now, that I don't need to isolate my search area, so this functionality is likely to be removed like you say.



     def draw_grid(self):
         for col in range(0, self.cols):
             print(end='| ')
             for row in range(0, self.rows):
                 print(self.grid[col][row].id, end=' | ')
         print()


I'm not sure if I have reconstructed the indentation correctly here. A
few changes: no need to call range(0, ...). GameTile instances now know
how to print themselves, so you can call:

                 print(self.grid[col][row], end=' | ')



This could be improved:

temp = GameGrid()
temp.make_grid()
temp.draw_grid()


Creating a GameGrid should automatically create the game grid, hence
what I said above about having __init__ call make_grid. Then use a more
meaningful name, and we have:


grid = GameGrid()
grid.draw_grid()  # Maybe this could be just called "draw"?
Thank you! Sorry about the indentation. I am checking the web version of the tutor archives now to see if my code reposted correctly.




_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to