CISC 106 Spring 2020 Project 2
May 10, 2020
1 Background
For this project, you’ll be implementing a solution to the packing problem as it relates to tetrominoes.
Your goal will be to fill a board represented as a N × M matrix of characters by packing a
random sequence of tetrominoes as tightly1 as possible on the board until it is full. Empty
squares on the board are represented as space characters, and filled squares are represented as
one of I, J, L, O, S, T, or Z; each letter corresponding to a single square of one of the seven
tetromino shapes.
NB: Please make sure to follow the links to and read all of the footnotes in this writeup, as
they contain useful information!
2 Objectives
After completing this project you will have gained the following experience with the MATLAB
programming language and environment:
• Creating functions which return one value as well functions which return multiple values.
• Working with 2-dimensional matrices in MATLAB:
– Using loops to iterate over elements
– Using filtering and logical indexing rather than loops when applicable
– Creating and manipulating slices.
• Using MATLAB’s robust plotting API:
– Creating and configuring figures and axes
– Drawing a scene composed of simple geometric shapes.
• Using MATLAB’s extensive online documentation.
3 Outline of Steps
The following section describes the steps you must take in order to complete this project.
1That is, with the fewest gaps between them
1
Project Set Up
In MATLAB creating a project is as simple as making a new folder and then saving your code
there as a collection of .m files. Create yourself a folder for your project, and then download the
following files from Canvas and put them there:
• run game.m
• draw test board.m
• unittests.m
• assertEqual.m
Now if you open MATLAB and navigate to that folder you can open those files, look at the
code, and run the function defined in them at the REPL.2
A MATLAB project is composed of files, each with at least one function in them. You can call
the first function defined in a file by using the name of the file3
, and as such the convention is to
name that first function the same as the name of the file. For this project, you will be following
this convention.
Open the unittests.m that you downloaded from Canvas. Note that there is one test already
written for seven of the eight functions you’ll be writing for this project.4 You’ll be following the
Beginner Design Recipe when writing your functions for this project, and here is where you’ll put
all of your tests. You should add two or three more tests for each of your functions as you’re
implementing them to test different possibilities. You can run your tests any time at the REPL
by entering the command unittests.
From now on, when you see instructions saying something along the lines of ”write a function
do stuff”, you should understand that to mean first create a script and save it as do stuff5
and then implement the function in that file, also calling the function do stuff.
Part 1
Write a function draw game board which consumes a board which is a 2D matrix of characters
as described in Section 1, and a figure6
. This function will then clear whatever happens to be on
the passed in figure, and construct a new axes with that figure as parent. You’ll then use the
rectangle function to create a graphical depiction of the passed in board on the created axes
object, and return the axes object. Keep in mind that you’ll be drawing one rectangle for every
character on the board - this means you’ll probably want to consider using nested for loops!
You can run the draw test board function you downloaded in the Project Setup section to
test your draw game board. Open draw test board.m to see the example board matrix, as well as
how to create a figure and how your function will be called. See Figure 1 for how your drawn
board should look.7 You should check the documentation for axes to see how to make your
board match Figure 1. You can also take a look at this improperly configured axes document to
see some common axes misconfigurations.
Part 2
Write a function make board which consumes a whole number of rows and a whole number of
columns. This function will return a rows × columns empty board - that is, a matrix of all space
2Of course, if you try to run them now, you’ll get an error message because they call code that you will write.
3Other functions defined in the same file can only be called within that file, and are called as they’re named in the file
4As we’ll see draw game board needs to be eyeballed for correctness, and as such you won’t write unit tests for it.
5you can add the .m extension or leave it off - MATLAB will add it for you automatically
6See MATLAB’s documentation for figure
7Assuming you’re using the standard tetromino colors. Feel free to get creative and pick your own color palette! The
positions and rotations and ”squareness” of the shapes should match Figure 1 regardless of your color choices.
2
Figure 1: A correctly drawn test board, using the standard colors for the seven tetrominoes. See
the discussion about setting colors in MATLAB’s documentation for rectangle.
characters. You should be able to implement the body of this function in just a single line of code!
Look in MATLAB’s documentation on Creating and Combining Arrays - from Documentation
Home, MATLAB→Language Fundamentals→Matrices and Arrays.
Part 3
Write a function get shape which consumes a single character that should be one of I, J, L,
O, S, T, or Z and returns the matrix representing that shape. The returned matrix should be
the smallest sized matrix necessary to represent the requested shape. Elements representing
squares occupied by the shape should be the letter, and elements representing empty squares
surrounding the shape should be a space. For example, the J could be represented by the matrix:
[’J’ ’J’ ’J’;
’ ’ ’ ’ ’J’]
Part 4
Write a function get board slice which consumes a board, a shape (such as what would be
returned by get shape), an integer row, and an integer column. The function should return the
slice of the board starting from (row, column) and having the same dimensions as the shape, as
well as the ending row and ending column for the slice. For example, given the board
[’I’ ’ ’ ’ ’ ’ ’;
’I’ ’ ’ ’ ’ ’ ’;
’I’ ’O’ ’O’ ’ ’;
’I’ ’O’ ’O’ ’ ’]
3
the shape
[’L’ ’L’;
’ ’ ’L’;
’ ’ ’L’]
along with row 2 and column 3, the resulting slice would be
[’ ’ ’ ’;
’O’ ’ ’;
’O’ ’ ’]
the ending row would be 4, and the ending column would also be 4.
If attempting to place the shape at the passed in row and column would cause the shape to be
partially or fully off the board, then the empty matrix [] should instead be returned. Going with
our exmple from above, we would get the empty matrix if we instead passed in 4 for the column,
since the three rightmost blocks of the ”L” would be pushed off the right edge of the board.
Part 5
Write a function place shape which consumes a board, a shape, an integer row, and an integer
column. The function should then return a new board which is the old board modified to have
the shape placed on the board such that location (row, column) corresponds to the upper left
corner of the shape. Using the example from Part 4, with the board
[’I’ ’ ’ ’ ’ ’ ’;
’I’ ’ ’ ’ ’ ’ ’;
’I’ ’O’ ’O’ ’ ’;
’I’ ’O’ ’O’ ’ ’]
the shape
[’L’ ’L’;
’ ’ ’L’;
’ ’ ’L’]
the row 2, and column 3, the resulting board would be:
[’I’ ’ ’ ’ ’ ’ ’;
’I’ ’ ’ ’L’ ’L’;
’I’ ’O’ ’O’ ’L’;
’I’ ’O’ ’O’ ’L’]
If you take advantage of your get board slice from the previous section, you should be
able to do this in just a few lines of code without resorting to a for loop. Look at the ”Replace
Values That Meet a Condition” section of the ”Find Array Elements That Meet a Condition” page
in MATLAB’s documentation. You can find a link to this page in the documentaion for logical
operators.8 Then keep in mind that:
1. If, for example, you have two matrices A and B with the same dimensions, you can replace
all the elements of A that correspond to elements in B that are less than 10 with those
elements in B by doing A(B < 10) = B(B < 10).
2. You can replace a slice of a matrix A with matrix B by doing
A(start row:end row, start column:end column) = B, assuming B and the resulting
slice of A have the same dimensions.
8
from Documentation Home, MATLAB→Language Fundamentals→Operators and Elementary Operations→Logical
Operations.
4
Part 6
Write a function try fit which consumes a board slice and a shape, and returns two values:
1) A boolean which is true if the shape fits in this slice (that is, if all the squares that would be
occupied by the shape are spaces on the board slice), f alse otherwise; and 2) The fill score for
this fit - that is, the number of squares where a space in the shape lines up with a non-space on
the board slice. You should be able to implement the body of this function with 2 lines of code
- one for each of the return values - using relational operators to filter your matrices along with
some reducing functions9
Part 7
Write a function find best place for rotation which consumes a board and a shape and finds
the best fitting location on the board for the shape in its current rotation. If two locations are
equally good fits, then you should default to the lowest, rightmost position on the board. This
function will return the following values:
1. A boolean which is true if the shape fits on the board at all, f alse if there isn’t anywhere on
the board where it fits.
2. The row of the upper left block of the best location for the shape on the board.
3. The column of the upper left block of the best location for the shape on the board.
4. A numeric score for the shape’s best location on the board. Higher scores are better. This
score can be any heuristic you believe leads to a better packing of shapes on the board.
NB that the fit returned by try fit can be used here, either as the entire score or as a
component of it.
You should make use of your try fit and get board slice functions when implementing
this function.
Part 8
Write a function find best place which consumes a board and a shape. This function should
find the best fitting location on the board for the shape over its current rotation and three possible
90◦
rotations10 This function will return the following values:
1. A boolean which is true if the shape fits on the board at all, f alse if there isn’t anywhere on
the board where it fits.
2. The row of the upper left block of the best location for the shape on the board.
3. The column of the upper left block of the best location for the shape on the board.
4. The number of clockwise11 rotations (which will be between 0 and 3, inclusive) required for
the best fit.
You should make use of your find best place for rotation function when implementing
this function.
9Namely, the sum and all functions. You should read MATLAB’s documentation for these.
10Look up how to do this on the same documentation page that discusses creating and combing arrays referenced in
Part 2! This time you’ll want to look in the section on reshaping and rearranging.
11Yes, the direction here is important!
5
4 Putting it all Together
Open the run game.m file you downloaded in the Project Setup section. You don’t need to change
any code here, but you can look at it to get an idea of how it’s calling the code you just wrote in
the above parts. Now you should be able to call run game at the REPL and watch your program
fill up the game board as best it can.
Submit the following files on Canvas:
• unittests.m
• draw game board.m
• make board.m
• get shape.m
• get board slice.m
• place shape.m
• try fit.m
• find best place for rotation.m
• find best place.m
6
版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。