[Tutor] Improving My Simple Game Code for Speed, Memory and Learning

WolfRage wolfrage8765 at gmail.com
Mon Jan 12 21:28:33 CET 2015


I fixed the other functions to again work as expected. But the 
procedural access of the self.grid and self.transposed_grid also 
function correctly. That is good because now I can again do lookups if I 
need to. Although I do not have a need to at this time.

Can anyone see anything wrong with the logic as it is at this time? If 
anyone has any improvements or things to think about, I would love to 
hear it. I am going to work on some tests that will specifically involve 
the procedural code to verify that the id's are arranged in the grid as 
I expect them to be.

I would also appreciate an explanation of why my by_id functions use the 
opposite grid to get the correct output?

#Output Below
python3 test1.py
| 19 | 11 |  5 | 19 |
| 11 | 19 | 19 |  5 |
| 20 | 19 | 20 |  6 |
| 11 | 19 | 11 |  5 |
| 11 |  6 |  5 | 20 |
|  6 |  5 | 19 | 19 |
| 20 | 19 | 20 | 20 |
|  6 | 20 | 19 | 20 |
After Eliminations
| 19 |  0 |  5 | 19 |
|  0 |  0 |  0 |  5 |
|  0 |  0 | 20 |  6 |
|  0 | 19 | 11 |  5 |
|  0 |  6 |  5 | 20 |
|  0 |  5 | 19 | 19 |
| 20 | 19 | 20 | 20 |
|  6 | 20 | 19 | 20 |

After Drops
|  0 |  0 |  0 | 19 |
|  0 |  0 |  5 |  5 |
|  0 |  0 | 20 |  6 |
|  0 | 19 | 11 |  5 |
|  0 |  6 |  5 | 20 |
| 19 |  5 | 19 | 19 |
| 20 | 19 | 20 | 20 |
|  6 | 20 | 19 | 20 |
By ID
| 0,0 | 1,0 | 2,0 | 3,0 |
| 0,1 | 1,1 | 2,1 | 3,1 |
| 0,2 | 1,2 | 2,2 | 3,2 |
| 0,3 | 1,3 | 2,3 | 3,3 |
| 0,4 | 1,4 | 2,4 | 3,4 |
| 0,5 | 1,5 | 2,5 | 3,5 |
| 0,6 | 1,6 | 2,6 | 3,6 |
| 0,7 | 1,7 | 2,7 | 3,7 |
Procedurally
| 0,0 (0,0) | 1,0 (1,0) | 2,0 (2,0) | 3,0 (3,0) |
| 0,1 (0,1) | 1,1 (1,1) | 2,1 (2,1) | 3,1 (3,1) |
| 0,2 (0,2) | 1,2 (1,2) | 2,2 (2,2) | 3,2 (3,2) |
| 0,3 (0,3) | 1,3 (1,3) | 2,3 (2,3) | 3,3 (3,3) |
| 0,4 (0,4) | 1,4 (1,4) | 2,4 (2,4) | 3,4 (3,4) |
| 0,5 (0,5) | 1,5 (1,5) | 2,5 (2,5) | 3,5 (3,5) |
| 0,6 (0,6) | 1,6 (1,6) | 2,6 (2,6) | 3,6 (3,6) |
| 0,7 (0,7) | 1,7 (1,7) | 2,7 (2,7) | 3,7 (3,7) |
Tansposed
| 0,0 | 0,1 | 0,2 | 0,3 | 0,4 | 0,5 | 0,6 | 0,7 |
| 1,0 | 1,1 | 1,2 | 1,3 | 1,4 | 1,5 | 1,6 | 1,7 |
| 2,0 | 2,1 | 2,2 | 2,3 | 2,4 | 2,5 | 2,6 | 2,7 |
| 3,0 | 3,1 | 3,2 | 3,3 | 3,4 | 3,5 | 3,6 | 3,7 |
Transposed & Procedurally
| 0,0 (0,0) | 0,1 (0,1) | 0,2 (0,2) | 0,3 (0,3) | 0,4 (0,4) | 0,5 (0,5) 
| 0,6 (0,6) | 0,7 (0,7) |
| 1,0 (1,0) | 1,1 (1,1) | 1,2 (1,2) | 1,3 (1,3) | 1,4 (1,4) | 1,5 (1,5) 
| 1,6 (1,6) | 1,7 (1,7) |
| 2,0 (2,0) | 2,1 (2,1) | 2,2 (2,2) | 2,3 (2,3) | 2,4 (2,4) | 2,5 (2,5) 
| 2,6 (2,6) | 2,7 (2,7) |
| 3,0 (3,0) | 3,1 (3,1) | 3,2 (3,2) | 3,3 (3,3) | 3,4 (3,4) | 3,5 (3,5) 
| 3,6 (3,6) | 3,7 (3,7) |

# Code Below
import random


class GameTile():
     def __init__(self, col, row, values=None, value=None, **kwargs):
         # values is not required because the value can be directly set.
         # This is to support a future feature that will allow me to build a
         # board off of a list.
         # id is grid (X,Y) which is equal to grid (col,row)
         self.id = str(col) + ',' + str(row)
         self.col = col
         self.row = row
         if value is None:
             value = random.choice(values)
         self.value = value
         self.eliminated = False
         # hide_anim = hidden for animation purposes
         self.hide_anim = False
         # drop_value = value to be dropped during animation
         self.drop_value = None
         # drop_to could have inversely been a drop_from
         # drop_to = the id of where the value should be dropped too.
         self.drop_to = None

     def __str__(self):
         return "%2d" % self.value


class GameGrid():
     def __init__(self, cols=8, rows=7, **kwargs):
         if cols < 3 or rows < 3:
             raise ValueError("Minimum board size is 3x3! %sx%s is too 
small."
                  % (cols, rows))
         self.cols = cols
         self.rows = rows
         self.values = [5, 6, 11, 19, 20]
         self.make_grid()

     def make_grid(self):
         # grid is 2d array as x, y ie [x][y].
         self.transposed_grid = []
         for row_num in range(self.rows):
             # Do you still think this needs to be broken into a smaller 
method?
             row = [GameTile(col_num, row_num, self.values)
                    for col_num in range(self.cols)]
             self.transposed_grid.append(row)
         self.grid = list(zip(*self.transposed_grid))

     def draw(self):
         for row in self.transposed_grid:
             print(end='| ')
             for node in row:
                 print(node, end=' | ')
             print()

     def draw_by_id(self):
         # Why does this one use self.transposed_grid instead of self.grid ?
         for row in self.transposed_grid:
             print(end='| ')
             for node in row:
                 print(node.id, end=' | ')
             print()

     def draw_by_id_proc(self):
         # Draw Procedurally
         for row_num in range(self.rows):
             print(end='| ')
             for col_num in range(self.cols):
                 print(self.grid[col_num][row_num].id, '(' + 
str(col_num) + ',' + str(row_num) + ')', end=' | ')
             print()

     def draw_by_id_trans(self):
         # Why does this one use self.grid instead of self.transposed_grid ?
         for col in self.grid:
             print(end='| ')
             for node in col:
                 print(node.id, end=' | ')
             print()

     def draw_by_id_proc_trans(self):
         # Draw Procedurally & Transposed
         for col_num in range(self.cols):
             print(end='| ')
             for row_num in range(self.rows):
                 print(self.transposed_grid[row_num][col_num].id, '(' + 
str(col_num) + ',' + str(row_num) + ')', end=' | ')
             print()

     def find_eliminations(self):
         #First Down the columns.
         i = 0
         for col_list in self.grid:
             while True:
                 try:
                     if self.check_total(col_list[i: i + 3]):
                         self.eliminate(col_list[i: i + 3])
                     i += 1
                 except ValueError:
                     i = 0
                     break
         # Now across the rows.
         for row_list in self.transposed_grid:
             while True:
                 try:
                     if self.check_total(row_list[i: i + 3]):
                         self.eliminate(row_list[i: i + 3])
                     i += 1
                 except ValueError:
                     i = 0
                     break
         # Set all eliminated nodes to a value of 0.
         for col in self.transposed_grid:
             for node in col:
                 if node.eliminated is True:
                     node.eliminated = False
                     node.value = 0

     def check_total(self, slices):
         first, second, third = slices
         if first.value == second.value or second.value == third.value:
             total = first.value + second.value + third.value
             return total in (17, 21, 28, 29, 31, 42, 45, 46, 49, 58)

     def eliminate(self, slices):
         first, second, third = slices
         first.eliminated = True
         second.eliminated = True
         third.eliminated = True

     def drop_floating_nodes0(self):
         i = self.rows
         # first_zero_row serves as memory for how far to drop non-zero 
values
         first_zero_row = None
         for col_list in self.grid:
             while True:
                 # Low is on Top, High is on Bottom
                 low, high = col_list[i - 2: i]  # Goes Up the Rows
                 if high.value == 0:
                     if low.value != 0:
                         if first_zero_row is None:
                             high.value = low.value
                             low.value = 0
                             first_zero_row = low
                         else:
                             first_zero_row.value = low.value
                             low.value = 0
                             try:
                                 row = first_zero_row.row - 1
                                 col = first_zero_row.col
                                 first_zero_row = self.grid[col][row]
                             except:
                                 i = self.rows
                                 print('broke', col, row)
                                 print(first_zero_row.col, 
first_zero_row.row)
                                 first_zero_row = None
                                 break
                     else:
                         if first_zero_row is None:
                             first_zero_row = high
                 i -= 1
                 if i == 1:
                     i = self.rows
                     first_zero_row = None
                     break

     def drop_floating_nodes1(self):
         i = 0
         for col_list in self.transposed_grid:
             while True:
                 try:
                     low, high = col_list[i: i + 2]  # Goes Down the Rows
                     if high.value == 0 and low.value != 0:
                         high.value = low.value
                         low.value = 0
                     i += 1
                 except ValueError:
                     i = 0
                     break




grid = GameGrid(4, 8)
grid.draw()
grid.find_eliminations()
print('After Eliminations')
grid.draw()
print()
grid.drop_floating_nodes0()
print('After Drops')
grid.draw()
print('By ID')
grid.draw_by_id()
print('Procedurally')
grid.draw_by_id_proc()
print('Tansposed')
grid.draw_by_id_trans()
print('Transposed & Procedurally')
grid.draw_by_id_proc_trans()


More information about the Tutor mailing list