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

WolfRage wolfrage8765 at gmail.com
Fri Jan 2 23:35:23 CET 2015


First an explanation of how the game works: The game is a simple 
matching game but with a twist. Instead of matching a straight 3 in a 
row, we have some rules that only certain combinations will result in an 
elimination. In general 2 of the same value in a row with with 1 of 2 
other possible values will eliminate all three nodes. Eliminations can 
occur either horizontally or vertically but not diagonally. Each tile 
has a value now, that value is used when evaluating the rules. Currently 
there are only 5 allowed values of 0-4 although more could be added 
later, so any solution needs to be expandable.
These are the basic rules that allow for an elimination to occur(values 
are put in quotes to distinguish values):
2 "5"s followed or proceeded by a "19" will eliminate all 3 nodes.
2 "5"s followed or proceeded by an "11" will eliminate all 3 nodes.
2 "6"s followed or proceeded by a "5" will eliminate all 3 nodes.
2 "6"s followed or proceeded by a "19" will eliminate all 3 nodes.
2 "11"s followed or proceeded by a "6" will eliminate all 3 nodes.
2 "11"s followed or proceeded by a "20" will eliminate all 3 nodes.
2 "19"s followed or proceeded by a "20" will eliminate all 3 nodes.
2 "19"s followed or proceeded by an "11" will eliminate all 3 nodes.
2 "20"s followed or proceeded by a "6" will eliminate all 3 nodes.
2 "20"s followed or proceeded by a "5" will eliminate all 3 nodes.

The main focus of the code is the find_eliminations method. I think its 
implementation is smart since it uses a math trick, but then again I 
wrote it.
My math trick works by first finding 2 matching nodes next to each other 
out of every 3 nodes, then adding the values of all 3 nodes together and 
checking for specific totals. None of the possible totals overlap.

Here is the code:

import random


class GameTile():
     def __init__(self, value, col, row, **kwargs):
         # id is grid (X,Y) which is equal to grid (col,row)
         self.id = str(col) + ',' + str(row)
         self.col = col
         self.row = row
         self.value = value
         self.eliminated = False

     def __str__(self):
         #return '%d, %d' % (self.col, self.row)
         if len(str(self.value)) == 1:
             return ' ' + str(self.value)
         return str(self.value)


class GameGrid():
     def __init__(self, cols=8, rows=7, **kwargs):
         self.cols = cols
         self.rows = rows
         self.make_grid()

     def make_grid(self):
         # grid is 2d array as x, y ie [x][y].
         self.grid = []
         for row_num in range(self.rows):
             self.grid.append([GameTile(value=random.choice([5, 6, 11, 
19, 20]), col=col_num,
                 row=row_num) for col_num in range(self.cols)])

     def print_by_col(self):
         # As in going down the column assuming we started at the top.
         for col_num in range(self.cols):
             for row_list in self.grid:
                 print(row_list[col_num])

     def print_by_row(self):
         # As in going right across the row assuming we started at the left.
         for row in self.grid:
             for node in row:
                 print(node)

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

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

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

     def find_eliminations(self):
         # I define 3 variables for holding the 3 nodes/tiles that I am
         # currently checking to see if an elimination possibility exists.
         # It uses a math trick to check for elimination by adding the 
values
         # and checking for specific totals. None of the possible totals 
overlap.
         #First Down the columns.
         for col_num in range(self.cols):
             first = None
             second = None
             third = None
             for row_list in self.grid:
                 if row_list[col_num].row == 0:
                     first = row_list[col_num]
                 elif row_list[col_num].row == 1:
                     second = row_list[col_num]
                 elif row_list[col_num].row == 2:
                     third = row_list[col_num]
                 else:
                     first = second
                     second = third
                     third = row_list[col_num]
                 if third is not None:
                     self.check_total_and_eliminate(first, second, third)
         # Now across the rows.
         for row in self.grid:
             first = None
             second = None
             third = None
             for node in row:
                 if node.col == 0:
                     first = node
                 elif node.col == 1:
                     second = node
                 elif node.col == 2:
                     third = node
                 else:
                     first = second
                     second = third
                     third = node
                 if third is not None:
                     self.check_total_and_eliminate(first, second, third)
         # Set all eliminated nodes to a value of 0.
         for col in self.grid:
             for node in col:
                 if node.eliminated is True:
                     node.eliminated = False
                     node.value = 0

     def check_total_and_eliminate(self, first, second, third):
         total = None
         if first.value == second.value:
             total = first.value + second.value + third.value
         elif second.value == third.value:
             total = first.value + second.value + third.value
         if total == 17 or total == 21 or total == 28 or total == 29 or \
             total == 31 or total == 42 or total == 45 or total == 46 \
             or total == 49 or total == 58:
             first.eliminated = True
             second.eliminated = True
             third.eliminated = True



grid = GameGrid(4, 8)
grid.draw()
grid.find_eliminations()
print('After Eliminations')
grid.draw()


# END CODE

After this part has been improved, I then need to search the columns 
backwards to be able to drop any floating values. Any none zero values 
should not have a zero value below it. That is what I mean by drop 
floating values. I think this will be simple by just using range method 
to count backwards. I will be working on coding that in the meantime.


More information about the Tutor mailing list