Mosaic
Mosaic

The game mosaic is a single-player logic puzzle.

Rules

According to the Simon Tatham's Portable Puzzle Collection:

‍Given a grid of squares, you must color it either black or white. Some squares contain clue numbers. Each clue tells you the number of black squares in the 3×3 region surrounding the clue - including the clue square itself.

So, to play this game, you have to choose the white or black color of each square to fill in all the grid. For example, if an empty cell contains the number 0, then the 3x3 neighbourhood must be white. Similarly, if a square contains the number 9, the 3x3 neighbourhood will be black.

Moreover, we will limit our game to a square grid of size 5x5.

You can try this game here.

By convention, the square in the i-th row and j-th column of the grid is referred to as the coordinate (i, j), and the coordinate (0, 0) corresponds to the top left corner (like in matrices).

In summary, the game uses the following squares, that can be printed in a terminal:

  • empty squares: 0 1 2 3 4 5 6 7 8 9 and ' ' if unconstrained
  • white squares: 🄋 ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ and □ if unconstrained
  • black squares: 🄌 ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ and ■ if unconstrained

Example

As an example, let's see the instance of the game, considered thereafter as the default game:

default

Hereafter, its solution obtained after playing all the following moves:

solution

This text representation will be the one used in our game, and more especially in the game_print() function used by the game_text program.

Project Architecture

Our project is based on a single library named game library (libgame.a), whose interface is divided into several header files:

This interface manipulates an opaque data type, that is the structure game, by means of pointers or const pointers (cgame).

About Const Pointer:

Based on this library, our project will provide several programs, including but not limited to the following:

  • game_text: a simple text-based program to play our game in a terminal ;
  • game_test: a program with many tests to check the validity of the library functions ;
  • game_solve: a program that computes the solution of a given game instance ;
  • game_sdl: a program to play our game in graphic mode (based on the SDL library).

Error Policy

There are many different ways to deal with program errors... Concerning the "game" library, we suppose that function calls to these interfaces (game.h, ...) must systematically be made with valid arguments (see preconditions). Also, the behavior of the library is not defined if a third-party program passes bad arguments to it. In practice, this means that the responsibility of checking that the arguments are valid is relieved to the high-level program (game_text, ...). In short, garbage in, garbage out.

In order to debug your program easily, we recommend to use the assert() macro, as it allows you to activate checks only in DEBUG mode and not in RELEASE mode. More precisely, if you pass the -DNDEBUG option at compilation time, the macro assert() generates no code, and hence does nothing at all.

For example:

#include <assert.h>
#include <stdlib.h>
int* copyArray(int size, int * array)
{
assert(size > 0); // check size parameter
assert(array != NULL); // check array parameter
int * newarray = malloc(size*sizeof(int)); // allocate memory for a new array
assert(newarray != NULL); // check memory allocation
for(int i = 0 ; i < size ; i++) // copy array values
newarray[i] = array[i];
return newarray;
}

References