|
[Home] [Puzzles & Projects] [Delphi Techniques] [Math Topics] [Library] [Utilities] |
|
Problem DescriptionDrag the lettered blocks onto the template to form valid words reading across and down crossword style. No need to rotate pieces and each piece is used exactly once. Here's what the downloaded puzzle looks like:
Background & TechniquesThe puzzle is the first and only example of this type I've found in my many
years as a fan of the Mensa "Puzzle-A-Day" calendars. It's from the June
18, 2010 puzzle page. Non-programmers are welcome to read on, but may want to jump to bottom of this page to download the executable program now. Programmer's Notes:Job 1 for implementing a computer model of a real world object (this puzzle, for example), is to determine the data structures which will let us describe and manipulate the parts. In this case, TStringGrid controls are logical candidates for the lettered blocks and the board template which controls where the blocks can be placed. Using Delphi's ability to define new classes, I defined a TBlock class as a TStringGrid descendent with a few additional fields. Namely
There's an array, Block, of TBlock controls defining the 8 blocks. Each block gets a lot of information from 8 TStringGrid controls that I defined using Delphi's visual design capabilities. See TBlock.Create and TBlock.Assign for the details. This allows us to reference any of the blocks using common code referencing Block[i]. Setting the Dragmode property to dmAutomatic allows the blocks to be dragged using the mouse. The board . template, named Board, is a 5 x 4 TStringGrid which has OnDragOver and OnDragDrop exits to allow properly oriented block to be dropped on it. In order to identify where the blocks can land and where they should be when the puzzle is solved I defined a 3-dimensional BlockMap array [0..4, 0..3, 0..1] containing two integer values for each of the 5 columns and 4 rows of the template grid. The first digit is simply an index number assigned to each block target location, '0' to '3' for the horizontal blocks and '4' to '7' for the vertical blocks. The four top left and bottom right cells are assigned a value of '-1 to indicate that no block can be dropped there. The second digit for each cell contains an offset value of '0' for the top left cell of each block and '-1' for the other cell for each block. This way, when the user drops a block on the board, the drop cell plus the offset value will point us to the first cell of the block. Here's how BlockMap identifies the block locations:
How do we use Blockmap?
Another slightly tricky bit is converting clicked pixel positions to cell locations. The TStringGrid MousetoCell method does this for us. When we drop a block on the board, we also use the Cellrect method to determine exact pixel values on which to drop the block. There's probably some other stuff that needs describing, but it's getting late. As usual, use the feedback link to ask if you have questions or suggestions.
Running/Exploring the Program
Suggestions for Further Explorations
|
[Feedback] [Newsletters (subscribe/view)] [About me]Copyright © 2000-2011, Gary Darby
All rights reserved.
|