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

WolfRage wolfrage8765 at gmail.com
Tue Jan 13 04:29:46 CET 2015


Updated the code to now allow for a fill_rows optional argument for 
Grid, that determines how many rows are filled with values.
I have also added some experimental code to invert the dropping, as in 
all of the values can float to the top. Other code is even more 
experimental and not yet working right that pulls the nodes to the right 
or left, with hope of being able to apply gravity in all 4 directions. 
But I still need to work out the bugs. Any help is greatly appreciated. 
Thanks for all of the contributions so far.

#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, fill_rows=None, **kwargs):
         if cols < 3 or rows < 3:
             raise ValueError('Minimum board size is 3x3! %sx%s is too 
small.'
                  % (cols, rows))
         if fill_rows > rows:
             string = 'Can not fill more rows than actual rows ' + \
                 'exist. fill_rows=%s rows=%s'
             raise ValueError(string % (fill_rows, rows))
         self.cols = cols
         self.rows = rows
         self.values = [5, 6, 11, 19, 20]
         self.make_grid(fill_rows)

     def __str__(self):
         output = []
         for row in self.transposed_grid:
             s = '| '
             for node in row:
                 s += str(node) + ' | '
             output.append(s)
         return '\n'.join(output)

     def make_grid(self, fill_rows=None):
         # grid is 2d array as x, y ie [x][y].
         # transposed_grid is 2d array as y, x ie [y][x]
         self.transposed_grid = []
         for row_num in range(self.rows):
             if fill_rows is None:
                 values = self.values
             elif row_num < self.rows - fill_rows:
                 values = [0, ]
             else:
                 values = self.values
             row = [GameTile(col_num, row_num, values)
                 for col_num in range(self.cols)]
             self.transposed_grid.append(row)
         self.grid = list(zip(*self.transposed_grid))

     def draw(self):
         print(self)

     def draw_by_id(self):
         # Why does this one use self.transposed_grid instead of self.grid ?
         output = []
         for row in self.transposed_grid:
             s = '| '
             for node in row:
                 s += str(node.id) + ' | '
             output.append(s)
         return '\n'.join(output)

     def draw_by_id_proc(self):
         # Draw Procedurally
         output = []
         for row_num in range(self.rows):
             s = '| '
             for col_num in range(self.cols):
                 s += (str(self.grid[col_num][row_num].id) + '(' + 
str(col_num) +
                     ',' + str(row_num) + ')' + ' | ')
             output.append(s)
         return '\n'.join(output)

     def draw_by_id_trans(self):
         # Why does this one use self.grid instead of self.transposed_grid ?
         output = []
         for col in self.grid:
             s = '| '
             for node in col:
                 s += str(node.id) + ' | '
             output.append(s)
         return '\n'.join(output)

     def draw_by_id_trans_proc (self):
         # Draw Transposed & Procedurally
         output = []
         for col_num in range(self.cols):
             s = '| '
             for row_num in range(self.rows):
                 s += (str(self.transposed_grid[row_num][col_num].id) + 
'(' +
                     str(col_num) + ',' + str(row_num) + ')' + ' | ')
             output.append(s)
         return '\n'.join(output)

     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_nodes(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 it is low because it is the lower 
numbered row
                 # High is on Bottom it is high because it is the higher 
numbered
                 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
                             row = first_zero_row.row - 1
                             col = first_zero_row.col
                             first_zero_row = self.grid[col][row]
                     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 invert_drop_nodes(self):
         i = 0
         # 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 it is low because it is the lower 
numbered row
                 # High is on Bottom it is high because it is the higher 
numbered
                 low, high = col_list[i: i + 2]  # Goes Down the Rows
                 if low.value == 0:
                     if high.value != 0:
                         if first_zero_row is None:
                             low.value = high.value
                             high.value = 0
                             first_zero_row = high
                         else:
                             first_zero_row.value = high.value
                             high.value = 0
                             row = first_zero_row.row + 1
                             col = first_zero_row.col
                             first_zero_row = self.grid[col][row]
                     else:
                         if first_zero_row is None:
                             first_zero_row = low
                 i += 1
                 if i == self.rows - 1:
                     i = 0
                     first_zero_row = None
                     break

     def pull_nodes(self):
         i = self.cols
         # first_zero_row serves as memory for how far to drop non-zero 
values
         first_zero_row = None
         for row_list in self.transposed_grid:
             while True:
                 # Low is on Top it is low because it is the lower 
numbered row
                 # High is on Bottom it is high because it is the higher 
numbered
                 low, high = row_list[i - 2: i]  # Goes Up the Columns
                 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  # Testing 
Here
                                 col = first_zero_row.col  # Or Here?
                                 first_zero_row = 
self.transposed_grid[col][row]
                             except:
                                 i = self.cols
                                 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.cols
                     first_zero_row = None
                     break

     def invert_pull_nodes(self):
         i = 0
         # first_zero_row serves as memory for how far to drop non-zero 
values
         first_zero_row = None
         for row_list in self.transposed_grid:
             while True:
                 # Low is on Top it is low because it is the lower 
numbered row
                 # High is on Bottom it is high because it is the higher 
numbered
                 low, high = row_list[i: i + 2]  # Goes Down the Columns
                 if low.value == 0:
                     if high.value != 0:
                         if first_zero_row is None:
                             low.value = high.value
                             high.value = 0
                             first_zero_row = high
                         else:
                             first_zero_row.value = high.value
                             high.value = 0
                             try:
                                 row = first_zero_row.row  # Testing Here
                                 col = first_zero_row.col + 1  # Or Here?
                                 first_zero_row = 
self.transposed_grid[col][row]
                             except:
                                 i = 0
                                 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 = low
                 i += 1
                 if i == self.cols - 1:
                     i = 0
                     first_zero_row = None
                     break


grid = GameGrid(4, 8, 6)
print(grid)
grid.find_eliminations()
print('After Eliminations')
print(grid)
grid.drop_nodes()
print('After Drops')
print(grid)
grid.invert_drop_nodes()
print('Reverse Gravity aka Inverted')
print(grid)
#grid.pull_nodes()
#print('Pull Nodes')
#print(grid)
#grid.invert_pull_nodes()
#print('Invert Pull Nodes')
#print(grid)
print(grid.draw_by_id())



More information about the Tutor mailing list