Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- #Jack Granite and Emily Coghlan
- # -*- coding: utf-8 -*-
- from cisc106 import assertEqual
- import time
- from tkinter import *
- DEBUG = True
- # A grid is a 2D list containing ones or zeros. A "shape" is an
- # object containing a nested tuple, where the real world shape is
- # represented as True values. For example, an "L" shape could be
- # represented as
- #
- # ((False, False, True),(True, True, True))
- #
- # Read a sequence of letters from a string (later from a text
- # file). Each letter represents a shape: T, L, or Z (all 2x3), or I
- # (1x4). Use functions to find a place on the grid where
- # the next shape in the sequence doesn't overlap any ones. Rotate the
- # shape to find the "best" fit. Then modify the grid to show the
- # shape in place, and repeat with the next shape in the sequence.
- # We will add the graphics and high level functions in the next part.
- class Grid:
- """
- Has attributes numRows, numCols, and squares (a 2D list containing True/False).
- """
- def __init__(self,rows,cols,squares):
- self.numRows = rows
- self.numCols = cols
- self.squares = squares if squares else [cols * [0] for r in range(rows)]
- def updateGrid(self, shape):
- """
- Top-level def for placing a single shape on grid. Finds best
- position and rotation for shape, update grid squares (mutates).
- Calls: find_max_score_location
- Returns boolean: fits or not
- """
- def print(self):
- """
- Print the grid, using an asterisk for each true square, underscore for false.
- Use a newline after each row, and no spaces in rows.
- """
- for rowi in range(self.numRows):
- print("\t")
- for coli in range(self.numCols):
- if self.squares[rowi][coli]:
- print('*', end = '')
- else:
- print('_', end = '')
- class Shape:
- """
- A "shape" is a nested tuple, where the real world shape is
- represented as ones. For example, an "L" shape could be
- represented as
- ((False, False, True),(True, True, True))
- Has attributes x, y, letter, squares (a nested list of type boolean),
- color, num_rotations
- """
- def __init__(self, letter, squares, color):
- self.x = 0 # will be modified later to indicate position
- self.y = 0 # will be modified later to indicate position
- self.letter = letter
- self.squares = squares
- self.color = color
- self.num_rotations = 0
- def rotate90(self):
- """
- Rotates this shape 90 degrees clockwise (direction
- matters). Mutates squares and num_rotations
- Returns None
- """
- self.squares = self.squares[::-1]
- a = len(self.squares[0])
- b = len(self.squares)
- new_shape_grid = [[0]*b for num in range(a)]
- for row in range(len(self.squares)):
- for col in range(len(self.squares[0])):
- new_shape_grid[col][row] = self.squares[row][col]
- self.squares = new_shape_grid
- self.num_rotations = self.num_rotations + 1
- def get_shape(letter):
- if letter == 'L':
- return Shape('L', [[False, False, True], [True, True, True]], 'blue')
- if letter == 'I':
- return Shape('I', [[True, True, True, True]], 'pink')
- if letter == 'T':
- return Shape('T', [[True, True, True], [False, True, False]], 'green')
- if letter == 'Z':
- return Shape('Z', [[True, True, False], [False, True, True]], 'purple')
- """
- Returns the Shape corresponding to the letter parameter: I
- for a line; T for a T; L for an L on its back, foot to right; Z
- for a Z. More may be added.
- """
- def fits(location, grid, shape):
- row,col = location
- test_matrix = []
- for x in range(len(shape.squares)):
- test_matrix = test_matrix + [grid.squares[row+x][col:(len(shape.squares[0]) + col)]]
- for i in range(len(test_matrix)):
- for j in range(len(test_matrix[i])):
- if test_matrix[i][j] == True:
- if shape.squares[i][j] == True:
- return False
- return True
- def generate_all_locations(grid, shape):
- """
- Takes a single shape in one position and finds all the places it could fit on the
- grid, given its dimensions.
- Returns: a list of row,col tuples
- """
- l = []
- for row in range(len(grid.squares)-len(shape.squares)+1):
- grid_column = grid.squares[row]
- shape_column = shape.squares[0]
- for column in range(len(grid_column)-len(shape_column)+1):
- l = l + [(row,column)]
- return l
- grid1 = Grid(3,5,[[0,0,1,0,0],[0,1,0,0,0],[0,1,1,0,1]])
- assertEqual(generate_all_locations(grid1, get_shape('T')), [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)])
- assertEqual(generate_all_locations(grid1, get_shape('I')), [(0,0),(0,1),(1,0),(1,1),(2,0), (2,1)])
- def get_valid_locations(location_list, grid, shape):
- """
- Returns list of locations where shape does not overlap shapes
- already on grid. Assumes that all locations in parameter list are
- potential fits for this shape.
- Calls: fits
- """
- valid_locations_list = []
- for location in location_list:
- if fits(location, grid, shape):
- valid_locations_list += [location]
- return valid_locations_list
- grid2 = Grid(4,4,[[0,0,0,0],[0,0,1,1],[1,0,0,1],[0,0,0,1]])
- assertEqual(get_valid_locations([(0,0),(1,0)], grid2, get_shape('Z')), [(1,0)])
- assertEqual(get_valid_locations([(1,0),(2,0)], grid2, get_shape('L')), [(2,0)])
- assertEqual(get_valid_locations([(0,0),(0,1),(2,0)], grid2, get_shape('T')), [(0,0)])
- '''assertEqual(get_valid_locations([(0,0), (0,1), (1,0)], grid2, get_shape('I')), [(0,0)])'''
- def get_score(location, grid, shape):
- """
- Computes the score for a shape placed at a single location on grid.
- Scores are positive, higher is better. For now, code the heuristic discussed in class.
- location: row,col tuple
- Returns: number
- """
- row,col = location
- score = 0
- for i in range(len(shape.squares)):
- lrow = i + row
- for j in range(len(shape.squares[0])):
- lcol = j + col
- if shape.squares[i][j] == False:
- if grid.squares[lrow][lcol] == True:
- score += 1
- return score
- def get_max_score(location_list, grid, shape):
- cscore = 0
- clocation = (0,0)
- for location in location_list:
- score = get_score(location, grid, shape)
- if cscore < score:
- cscore = score
- clocation = location
- elif cscore == score:
- if location[1] > clocation[1]:
- clocation = location
- elif location[0] > clocation[0]:
- clocation = location
- return clocation, cscore
- def find_max_score_location(grid, shape):
- """
- Takes a single shape, finds best position on grid. Tries original
- and three possible 90 degree rotations. Mutates shape for each rotation.
- When scores are equal, the lowest row (highest row number), right end (highest
- column) should be preferred.
- Returns tuple: (fits numberRotations location)
- fits: bool
- maxScoreRow, maxScoreCol: upper left coordinates of best position for shape on grid
- numberRotations: 0-3 rotations required for best fit.
- Calls: rotate90, generate_all_locations, get_valid_locations, get_max_score
- """
- location_list = generate_all_locations(grid,shape)
- valid_list = get_valid_locations(location_list, grid, shape)
- #print(valid_list)
- final_list = [get_max_score(valid_list, grid, shape)]
- #print(final_list)
- shape.rotate90()
- location_list = generate_all_locations(grid,shape)
- valid_list = get_valid_locations(location_list, grid, shape)
- #print(valid_list)
- final_list += [get_max_score(valid_list, grid, shape)]
- #print(final_list)
- shape.rotate90()
- location_list = generate_all_locations(grid,shape)
- valid_list = get_valid_locations(location_list, grid, shape)
- #print(valid_list)
- final_list += [get_max_score(valid_list, grid, shape)]
- #print(final_list)
- shape.rotate90()
- location_list = generate_all_locations(grid,shape)
- valid_list = get_valid_locations(location_list, grid, shape)
- #print(valid_list)
- final_list += [get_max_score(valid_list, grid, shape)]
- print(final_list)
- shape.rotate90()
- max_tupe = final_list[0]
- for tupe in final_list[1:]:
- print (max_tupe, tupe)
- if tupe[1] > max_tupe[1]:
- max_tupe = tupe
- if tupe[1] == max_tupe[1]:
- if tupe[0][0] > max_tupe[0][0]:
- max_tupe = tupe
- elif tupe[0][1] > max_tupe [0][1]:
- max_tupe = tupe
- else:
- max_tupe = max_tupe
- if max_tupe == final_list[0]:
- num_rotations = 0
- elif max_tupe == final_list[1]:
- num_rotations = 1
- elif max_tupe == final_list[2]:
- num_rotations = 2
- else:
- num_rotations = 3
- for r in range(num_rotations):
- shape.rotate90()
- return (fits(max_tupe[0], grid, shape), num_rotations, max_tupe[0])
- assertEqual(fits((0,0), Grid(3,4,[[0,0,0,0],[0,0,1,0],[0,0,0,1]]), get_shape('I')), True)
- assertEqual(fits((1,0), Grid(3,4,[[0,0,0,0],[0,0,1,0],[0,0,0,1]]), get_shape('I')), False)
- assertEqual(fits((0,0), Grid(3,4,[[0,0,0,0],[0,0,1,0],[0,0,0,1]]), get_shape('T')), True)
- assertEqual(fits((0,1), Grid(3,4,[[0,0,0,0],[0,0,1,0],[0,0,0,1]]), get_shape('T')), False)
- assertEqual(fits((1,0), Grid(3,4,[[0,0,0,0],[0,0,1,0],[0,0,0,1]]), get_shape('Z')), True)
- assertEqual(fits((0,1), Grid(3,4,[[0,0,0,0],[0,0,1,0],[0,0,0,1]]), get_shape('Z')), False)
- assertEqual(fits((0,2), Grid(5,5,[[0,0,1,0,0],[0,1,0,0,0],[0,1,1,0,1],[0,0,0,0,0],[1,0,0,1,0]]), get_shape('L')), True)
- assertEqual(fits((1,2), Grid(5,5,[[0,0,1,0,0],[0,1,0,0,0],[0,1,1,0,1],[0,0,0,0,0],[1,0,0,1,0]]), get_shape('T')), True)
- assertEqual(fits((3,1), Grid(5,5,[[0,0,1,0,0],[0,1,0,0,0],[0,1,1,0,1],[0,0,0,0,0],[1,0,0,1,0]]), get_shape('I')), True)
- assertEqual(fits((3,0), Grid(5,5,[[0,0,1,0,0],[0,1,0,0,0],[0,1,1,0,1],[0,0,0,0,0],[1,0,0,1,0]]), get_shape('Z')), True)
- assertEqual(fits((3,2), Grid(5,5,[[0,0,1,0,0],[0,1,0,0,0],[0,1,1,0,1],[0,0,0,0,0],[1,0,0,1,0]]), get_shape('Z')), False)
- if DEBUG:
- assertEqual(generate_all_locations(Grid(2,4,[]), get_shape('L')), [(0,0),(0,1)])
- assertEqual(get_max_score([(0,0),(0,1)], Grid(2,4,[]), get_shape('L')), ((0,1),0))
- assertEqual(get_valid_locations([(0,0),(0,1)], Grid(2,4,[]), get_shape('L')),[(0,0),(0,1)])
- b = [[1,0,0],[0,0,0]]
- assertEqual(get_valid_locations([(0,0)], Grid(2,3,b), get_shape('L')), [(0,0)])
- assertEqual(find_max_score_location(Grid(2,4,[]), get_shape('L')), (True, 0, (0,1)))
- assertEqual(find_max_score_location(Grid(3,4,[[0,0,0,0],[0,0,0,0],[0,1,1,1]]),get_shape('L')), (True, 2, (1,0)))
- g = Grid(2,4,[[True,False,False,False],[False,False,False,False]])
- assertEqual(find_max_score_location( g, get_shape('L')), (True, 0, (0,0)))
- g.print()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement