CSE333 16au -- Homework #3

Out: Thursday January 26, 2017
Due: Monday February 6, 2017, 11:59 PM.
Teams: Two person teams are required.
Note: The midterm is Friday, February 3.

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:

  • select a candy. In our implementation that happens by clicking on one.
  • swap two candies. In our implementation that happens by clicking on one of the four direction arrows, causing the selected candy to be swapped with the candy in the indicated direction (unless there is no candy in that direction). A side-effect (in the model) of swapping candies is that the moves mae field is incremented by one. When the view is refreshed after a swap, it shows the updated number of moves made.
The main goal of all this is to make sure you can display a board, can provide some way for the user to select and swap adjacent candies, and can update the number of moves made field. That's it. It doesn't much matter exactly what your board looks like nor what the actions are that cause candies to be moved. Additionally, there are no real elements of game play implemented. That comes next, when we implement the model component.

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.

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.

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:
  • a hw3-sample-solution executable, built on attu. Invoke it like this: ./hw3-sample-solution test10by10.json

  • a sample makefile that shows how to compile and link against GTK+. The sample makefile assumes you're working in a directory that is a sibling to your hw2 directory, and that you built a library, libhw2.a, out of your 2d array code that lives in the hw2 directory. It further assumes that the jansson directory, distributed as part of hw2, is another sibling to your hw3 directory.

  • a utility program, makeboard, that generates randomly populated boards of arbitrary size.
    (./makeboard --help)

How many colors are there?
The code we're distributing is prepared only for color numbers 0 through 5. You're free to support more colors than that, but you don't have to.

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:

  • hw4: implement the model component in C++. The model provides all of the game play (that we implement). We expect that the goal will be to explode every square on the board at least once. We don't yet know what patterns will cause explosions, nor whether or not there will striped or other special candies produced by explosions.

  • hw5: separate the model and view/control so that they can run on separate machines. (We'll be using some kind of networking to communicate between the two pieces.)

  • hw6: implement a multi-threaded "Candy Crush solver." Your solver will try to find the most promising move it can in some limited amount of time. It will then take that move and search again. Our goal is to have the solvers from all the teams connect to a view server we write. Our server will display the best play of a board by each team. The teams' solvers will compete to see which can explode every square in the fewest moves.

  • You should submit your code and any other files required to build and run it.
  • Your code should build with the command make.
  • After building it, it must be possible to invoke your application with the command ./hw3 someFileName
  • You should submit a pdf document that tells us how to run your project and then how to interact with it while it's running. (What do we click on?, etc.)
  • Put the names and login names of both members of your team at the top of the pdf document.
  • Submit everything to the course dropbox.
  • We're expecting you to use your hw2 solution as part of the solution for hw3. If you don't, you should explain why not in your pdf file.