This assignment takes us one step closer to our final goal, which involves a Model-View-Controller implementation of a simplified but distributed and multi-threaded version of Candy Crush. In this assignment we concentrate on implementing a first version of the view component.
For now, the model is simply a 2d array whose elements are integers from some small, consecutive range, representing candy colors. The model is initialized from a file whose name is given as the sole command line argument, e.g., ./hw3 test10by10.json. In our example, that file has these contents:
{"rows": 10, "columns": 10, "data": [5, 3, 1, 2, 1, 2, 5, 3, 0, 4, 3, 1, 5, 3, 3, 1, 2, 0, 3, 5, 5, 0, 4, 0, 2, 5, 0, 5, 2, 1, 4, 5, 4, 3, 5, 5, 0, 3, 0, 4, 1, 1, 5, 0, 4, 0, 5, 5, 4, 1, 2, 4, 1, 1, 4, 2, 0, 4, 5, 1, 3, 2, 4, 5, 5, 2, 2, 3, 5, 2, 1, 4, 3, 4, 5, 0, 2, 2, 5, 1, 1, 1, 5, 3, 0, 3, 3, 5, 0, 2, 0, 3, 2, 2, 1, 0, 4, 3, 3, 3]}The view visualizes the contents of a 2D array. An example is shown below. You do not have to replicate this example exactly. Your view can be something that appeals to you more than ours, for instance. The view will not be a major component in the final product, though, so don't spend inordinate time on making it nice unless doing so appeals to you.
Note that the 0th row of the data (5, 3, 1, 2, 1, 2 ,5, 3, 0, 4) is displayed at the bottom of the grid. Row 1 is displayed immediately above that, etc.
The controller in our implementation fields events generated by interactions with the view. The events are:
Please note that what you build now will be enhanced (modified) in some small ways in later assignments. We'll need a way to display which cells in the board have been fired and which not (something like jelly in the original game). We'll need a way to save a game, which is both a board and a number of moves made. We might want to have some notion of gravity. We'll need to have some notion of what candy sequences cause explosions, and which cells are removed when explosions occur, etc. For now, though, making sure we can create the display and field events on it are the only goals.
We'll be using GTK+ for drawing and capturing events like mouse clicks:
GTK+, or the GIMP Toolkit, is a multi-platform toolkit for creating graphical user interfaces. Offering a complete set of widgets, GTK+ is suitable for projects ranging from small one-off tools to complete application suites.To get started using GTK+, I suggest looking at Getting Started with GTK+. Read the first two sections (Basics and Packing) and then the section on Opening Files. We provide in hw3.tar.gz:GTK+ is cross-platform and boasts an easy to use API, speeding up your development time.
GTK+ is written in C but has been designed from the ground up to support a wide range of languages, not only C/C++. Using GTK+ from languages such as Perl and Python (especially in combination with the Glade GUI builder) provides an effective method of rapid application development.
GTK+ is free software and part of the GNU Project. However, the licensing terms for GTK+, the GNU LGPL, allow it to be used by all developers, including those developing proprietary software, without any license fees or royalties.
How many colors are there?
Which color does each integer represent?
It completely doesn't matter. Each integer should always
represent some one color, whatever it is, and no two integers should
represent the same color.
I hate trying to figure out how to use GTK+. Why don't you just
tell us what to do?
This assignment is mostly about gaining experience with what it's
like trying to use big, production libraries. I'm leaving that to
you. There isn't really very much code to write.
When a move occurs, do I update both the model and the view, or do
I update the model and completely redraw the view, or something
else?
Excellent question. It's tempting to try to update the view,
because the view and the controller are so intertwined. This is
especially the case when the change to the model of some controller
event is as simple as swap. Updating the view essentially requires
you to implement the game logic twice, though, once in the model and
once in the view. That's bad. Additionally, down the road we will be
running the view and the model on separate machines. The simplest
interface between them is to ship an entire board state from the model
to the view, and for the view to then display that state. An
optimization would be for the model to ship an update list of some
sort. Optimizations tend to be difficult to get correct, and so
require a lot of time and discipline for debugging. We're short on
both! On the other hand, completely redrawing the view each update
can be a performance issue, if updates are frequent.
So, as with everything else, I want to leave this decision to your judgement and for you to experience the consequences, but it should be pretty clear which side of this I think is best for getting the overall project done.
Can I implement more of the actual game play now?
You can go ahead and try to do that if you like. But, the game
play is part of the implementation of the model, and this assignment
hardly has a model at all. So, it's likely you'll need to adapt
whatever you do now in the model for what lies ahead.
What lies ahead?
The plan is this: