initial commit
This commit is contained in:
1 parent
255f0e2faf
commit
2bd4cee4ab
6 files changed
+576
No files matched your search
@@ -0,0 +1,25 @@
|
||||
CC=gcc # compilateur
|
||||
CFLAGS=-Wall -std=c99 # options de compilation
|
||||
LDFLAGS=-L. # options de link
|
||||
LDLIBS=-lgame # bibliothèques
|
||||
CPPFLAGS= # options de preprocessing
|
||||
AR= ar
|
||||
|
||||
all: game_text
|
||||
|
||||
libgame.a: game_aux.o game.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
game_text: game_text.o libgame.a
|
||||
$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)
|
||||
|
||||
.PHONY: clean dep
|
||||
|
||||
include dep
|
||||
|
||||
# génération des dépendances
|
||||
dep:
|
||||
$(CC) -MM *.c > dep
|
||||
|
||||
clean:
|
||||
rm -f dep game_aux.o *~ game_text game_text.o libgame.a
|
||||
@@ -0,0 +1,314 @@
|
||||
/**
|
||||
* @file game.h
|
||||
* @brief Basic Game Functions.
|
||||
* @details See @ref index for further details.
|
||||
* @copyright University of Bordeaux. All rights reserved, 2021.
|
||||
**/
|
||||
|
||||
#ifndef __GAME_H__
|
||||
#define __GAME_H__
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* @brief Standard unsigned integer type.
|
||||
**/
|
||||
typedef unsigned int uint;
|
||||
|
||||
/**
|
||||
* @brief Size of the default game grid.
|
||||
**/
|
||||
#define DEFAULT_SIZE 7
|
||||
|
||||
/**
|
||||
* @brief Different squares used in the game.
|
||||
* @details The value of a square is an integer represented on one byte, with a
|
||||
* low-order half-byte that codes for the square state (blank, black wall, light
|
||||
* bulb or mark) and a high-order half-byte that codes for the additionnal
|
||||
* square flags (lighted or error). While each square has a single state, it can
|
||||
* have zero, one or several flags (combined with bitwise operations). For
|
||||
* instance, a light bulb can have both the lighted and error flags. In this
|
||||
* case, the raw square value is S_LIGHTBULB | F_LIGHTED | F_ERROR, using the
|
||||
* bitwise OR operator (|). For more details on bitwise operations, see
|
||||
* https://en.wikipedia.org/wiki/Bitwise_operations_in_C.
|
||||
**/
|
||||
typedef enum {
|
||||
/* states */
|
||||
S_BLANK = 0, /**< a blank square */
|
||||
S_LIGHTBULB = 1, /**< a light bulb */
|
||||
S_MARK = 2, /**< a marked square (as not-a-light) */
|
||||
S_BLACK = 8, /**< black wall base code */
|
||||
S_BLACK0 = S_BLACK, /**< a numbered black wall (with 0 adjacent lights) */
|
||||
S_BLACK1, /**< a numbered black wall (with 1 adjacent light) */
|
||||
S_BLACK2, /**< a numbered black wall (with 2 adjacent lights) */
|
||||
S_BLACK3, /**< a numbered black wall (with 3 adjacent lights) */
|
||||
S_BLACK4, /**< a numbered black wall (with 4 adjacent lights) */
|
||||
S_BLACKU, /**< an unnumbered black wall (any number of adjacent lights) */
|
||||
/* flags */
|
||||
F_LIGHTED = 16, /**< lighted flag */
|
||||
F_ERROR = 32 /**< error flag */
|
||||
} square;
|
||||
|
||||
/** state mask used in square enum */
|
||||
#define S_MASK 0x0F
|
||||
|
||||
/** flag mask used in square enum */
|
||||
#define F_MASK 0xF0
|
||||
|
||||
/** square mask used in square enum */
|
||||
#define A_MASK 0xFF
|
||||
|
||||
/**
|
||||
* @brief The structure pointer that stores the game state.
|
||||
**/
|
||||
typedef struct game_s *game;
|
||||
|
||||
/**
|
||||
* @brief The structure constant pointer that stores the game state.
|
||||
* @details That means that it is not possible to modify the game using this
|
||||
* pointer.
|
||||
**/
|
||||
typedef const struct game_s *cgame;
|
||||
|
||||
/**
|
||||
* @brief Creates a new game with default size and initializes it.
|
||||
* @param squares an array describing the initial square values (<a
|
||||
* href="https://en.wikipedia.org/wiki/row-_and_column-major_order">row-major
|
||||
* storage</a>)
|
||||
* @pre @p squares must be an initialized array of default size squared.
|
||||
* @return the created game
|
||||
**/
|
||||
game game_new(square *squares);
|
||||
|
||||
/**
|
||||
* @brief Creates a new empty game with defaut size.
|
||||
* @details All squares are initialized with blank squares.
|
||||
* @return the created game
|
||||
**/
|
||||
game game_new_empty(void);
|
||||
|
||||
/**
|
||||
* @brief Duplicates a game.
|
||||
* @param g the game to copy
|
||||
* @return the copy of the game
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
**/
|
||||
game game_copy(cgame g);
|
||||
|
||||
/**
|
||||
* @brief Tests if two games are equal (same states and same flags).
|
||||
* @param g1 the first game
|
||||
* @param g2 the second game
|
||||
* @return true if the two games are equal, false otherwise
|
||||
* @pre @p g1 must be a valid pointer toward a game structure.
|
||||
* @pre @p g2 must be a valid pointer toward a game structure.
|
||||
**/
|
||||
bool game_equal(cgame g1, cgame g2);
|
||||
|
||||
/**
|
||||
* @brief Deletes the game and frees the allocated memory.
|
||||
* @param g the game to delete
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
**/
|
||||
void game_delete(game g);
|
||||
|
||||
/**
|
||||
* @brief Sets the value of a given square.
|
||||
* @details This function is useful for initializing the squares of an empty
|
||||
* game.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @param s the square value
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @pre @p s must be a valid square value.
|
||||
**/
|
||||
void game_set_square(game g, uint i, uint j, square s);
|
||||
|
||||
/**
|
||||
* @brief Gets the raw value of a given square.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return the square value
|
||||
**/
|
||||
square game_get_square(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Gets the state of a given square.
|
||||
* @details See description of enum square.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return the square state
|
||||
**/
|
||||
square game_get_state(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Gets the flags of a given square.
|
||||
* @details See description of enum square.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return the square flags
|
||||
**/
|
||||
square game_get_flags(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Test if a given square is blank.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return true if the square is blank
|
||||
**/
|
||||
bool game_is_blank(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Test if a given square is a lightbulb.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return true if the square is a lightbulb
|
||||
**/
|
||||
bool game_is_lightbulb(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Test if a given square is black (whether or not it is numbered).
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return true if the square is black
|
||||
**/
|
||||
bool game_is_black(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Get the number of lightbulbs expected against a black wall.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return the back wall number, or -1 if it is unumbered
|
||||
**/
|
||||
int game_get_black_number(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Test if a given square is marked (as not-a-light).
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return true if the square is marked
|
||||
**/
|
||||
bool game_is_marked(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Test if a given square is lighted.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return true if the square is lighted
|
||||
**/
|
||||
bool game_is_lighted(cgame g, uint i, uint j);
|
||||
|
||||
/**
|
||||
* @brief Test if a given square has an error flag
|
||||
* @details An error can only occur on an numbered black wall or on a light
|
||||
* bulb.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @return true if the square has an error flag
|
||||
**/
|
||||
bool game_has_error(cgame g, uint i, uint j);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Checks if a given move is legal.
|
||||
* @details This function checks that it is possible to play a move at a given
|
||||
* position in the grid. More precisely, a move is said to be legal: 1) if the
|
||||
* coordinates (i,j) are inside the grid, 2) if @p s is either a blank, light
|
||||
* bulb or mark square, and 3) if the current square at (i,j) is not a black
|
||||
* square.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @param s the square value
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @return false if the move is not legal.
|
||||
**/
|
||||
bool game_check_move(cgame g, uint i, uint j, square s);
|
||||
|
||||
/**
|
||||
* @brief Plays a move in a given square.
|
||||
* @details The grid flags are updated consequently after each move.
|
||||
* @param g the game
|
||||
* @param i row index
|
||||
* @param j column index
|
||||
* @param s the square value
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
* @pre @p i < game height
|
||||
* @pre @p j < game width
|
||||
* @pre @p s must be either BLANK, LIGHTBULB or MARK.
|
||||
* @pre The game square at position (i,j) must not be a black square.
|
||||
**/
|
||||
void game_play_move(game g, uint i, uint j, square s);
|
||||
|
||||
/**
|
||||
* @brief Update all grid flags.
|
||||
* @details This is a low-level function, which is not intended to be used
|
||||
* directly by end-user during the game.
|
||||
* @param g the game
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
**/
|
||||
void game_update_flags(game g);
|
||||
|
||||
/**
|
||||
* @brief Checks if the game is won.
|
||||
* @param g the game
|
||||
* @details This function checks that all the game rules (decribed on @ref
|
||||
* index) are satisfied, ie. that all the blank squares are ligthed, without any
|
||||
* errors.
|
||||
* @return true if the game ended successfully, false otherwise
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
**/
|
||||
bool game_is_over(cgame g);
|
||||
|
||||
/**
|
||||
* @brief Restarts a game.
|
||||
* @details All the game is reset to its initial state. In particular, all the
|
||||
* squares except black walls are reset to blank, and all flags are cleared.
|
||||
* @param g the game
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
**/
|
||||
void game_restart(game g);
|
||||
|
||||
#endif // __GAME_H__
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
#ifndef __GAME_AUX_H__
|
||||
#define __GAME_AUX_H__
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "game.h"
|
||||
|
||||
int charPrintCell(square sqState){
|
||||
if (sqState == S_BLANK){
|
||||
return ' ';
|
||||
}
|
||||
if ((sqState == S_LIGHTBULB) || (sqState == (S_LIGHTBULB|F_ERROR)) | (sqState == (S_LIGHTBULB|F_LIGHTED)) | (sqState == (S_LIGHTBULB|F_ERROR|F_LIGHTED))){
|
||||
return '*';
|
||||
}
|
||||
if ((sqState == S_MARK) || (sqState == (S_MARK|F_ERROR)) | (sqState == (S_MARK|F_LIGHTED))){
|
||||
return '-';
|
||||
}
|
||||
if (sqState == S_BLACK0 || sqState == (S_BLACK0|F_ERROR)){
|
||||
return '0';
|
||||
}
|
||||
if (sqState == S_BLACK1 || sqState == (S_BLACK1|F_ERROR)){
|
||||
return '1';
|
||||
}
|
||||
if (sqState == S_BLACK2 || sqState == (S_BLACK2|F_ERROR)){
|
||||
return '2';
|
||||
}
|
||||
if (sqState == S_BLACK3 || sqState == (S_BLACK3|F_ERROR)){
|
||||
return '3';
|
||||
}
|
||||
if (sqState == S_BLACK4 || sqState == (S_BLACK4|F_ERROR)){
|
||||
return '4';
|
||||
}
|
||||
if (sqState == S_BLACKU || sqState == (S_BLACKU|F_ERROR)){
|
||||
return 'w';
|
||||
}
|
||||
if (sqState == F_LIGHTED){
|
||||
return '.';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void game_print(cgame g){
|
||||
if (g != NULL){
|
||||
uint i;
|
||||
printf(" 0");
|
||||
for (i = 1; i < DEFAULT_SIZE; i++){
|
||||
printf("%u",i);
|
||||
}
|
||||
printf("\n -");
|
||||
for (i = 1; i < DEFAULT_SIZE; i++){
|
||||
printf("-");
|
||||
}
|
||||
printf("\n");
|
||||
for (i = 0; i < DEFAULT_SIZE; i++){
|
||||
printf("%u |",i);
|
||||
for (uint j = 0; j < DEFAULT_SIZE; j++){
|
||||
printf("%c",charPrintCell(game_get_square(g,i,j)));
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
printf(" -");
|
||||
for (i = 1; i < DEFAULT_SIZE; i++){
|
||||
printf("-");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
game game_default(void){
|
||||
game g = game_new_empty();
|
||||
game_set_square(g,0,2,S_BLACK1);
|
||||
game_set_square(g,1,2,S_BLACK2);
|
||||
game_set_square(g,2,5,S_BLACKU);
|
||||
game_set_square(g,2,6,S_BLACK2);
|
||||
game_set_square(g,4,0,S_BLACK1);
|
||||
game_set_square(g,4,1,S_BLACKU);
|
||||
game_set_square(g,5,4,S_BLACK2);
|
||||
game_set_square(g,6,4,S_BLACKU);
|
||||
return g;
|
||||
}
|
||||
|
||||
game game_default_solution(void){
|
||||
game g = game_default();
|
||||
game_set_square(g,0,0,S_LIGHTBULB);
|
||||
game_set_square(g,1,1,S_LIGHTBULB);
|
||||
game_set_square(g,0,3,S_LIGHTBULB);
|
||||
game_set_square(g,1,6,S_LIGHTBULB);
|
||||
game_set_square(g,2,2,S_LIGHTBULB);
|
||||
game_set_square(g,3,6,S_LIGHTBULB);
|
||||
game_set_square(g,4,4,S_LIGHTBULB);
|
||||
game_set_square(g,5,0,S_LIGHTBULB);
|
||||
game_set_square(g,5,5,S_LIGHTBULB);
|
||||
game_set_square(g,6,1,S_LIGHTBULB);
|
||||
game_update_flags(g);
|
||||
return g;
|
||||
}
|
||||
|
||||
#endif
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file game_aux.h
|
||||
* @brief Auxiliarry Game Functions.
|
||||
* @details See @ref index for further details.
|
||||
* @copyright University of Bordeaux. All rights reserved, 2021.
|
||||
**/
|
||||
|
||||
#ifndef __GAME_AUX_H__
|
||||
#define __GAME_AUX_H__
|
||||
#include <stdbool.h>
|
||||
#include "game.h"
|
||||
|
||||
/**
|
||||
* @brief Prints a game as text on the standard output stream.
|
||||
* @details The different squares are respectively displayed as text, based on a
|
||||
* square-character mapping table, as described in @ref index.
|
||||
* @param g the game
|
||||
* @pre @p g must be a valid pointer toward a game structure.
|
||||
**/
|
||||
void game_print(cgame g);
|
||||
|
||||
/**
|
||||
* @brief Creates the default game.
|
||||
* @details See the description of the default game in @ref index.
|
||||
* @details https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/lightup.html#7x7:b1f2iB2g1Bi2fBb
|
||||
* @return the created game
|
||||
**/
|
||||
game game_default(void);
|
||||
|
||||
/**
|
||||
* @brief Creates the default game solution.
|
||||
* @details See the description of the default game in @ref index.
|
||||
* @details https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/lightup.html#7x7:b1f2iB2g1Bi2fBb
|
||||
* @return the created game
|
||||
**/
|
||||
game game_default_solution(void);
|
||||
|
||||
#endif // __GAME_AUX_H__
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "game.h"
|
||||
#include "game_aux.h"
|
||||
|
||||
bool checkerr(game g, char taberr[]){
|
||||
if (taberr == NULL || g == NULL){
|
||||
return -1;
|
||||
}
|
||||
uint err = 0;
|
||||
taberr[0] = '\0';
|
||||
for (int i=0; i < DEFAULT_SIZE; i++){
|
||||
for (int j=0;j < DEFAULT_SIZE; j++){
|
||||
//check each case
|
||||
if (game_has_error(g,i,j)){
|
||||
// if error append taberr with coo+,
|
||||
taberr[err] = i+48;
|
||||
err++;
|
||||
taberr[err] = ':';
|
||||
err++;
|
||||
taberr[err] = j+48;
|
||||
err++;
|
||||
taberr[err] = ' ';
|
||||
err++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if taberr changes print
|
||||
if (taberr[0] != '\0'){
|
||||
taberr[err] = '\0';
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void printhelp(void){
|
||||
printf("Liste des différentes commandes :\n");
|
||||
printf("h : Affiche cette aide.\n");
|
||||
printf("r : Réinitialise la partie.\n");
|
||||
printf("q : Quitter la partie (abandon).\n");
|
||||
printf("l <i> <j> : Place une ampoule (*light bulb*) dans la case (<i>,<j>).\n");
|
||||
printf("m <i> <j> : Place une marque (*mark*) dans la case (<i>,<j>).\n");
|
||||
printf("b <i> <j> : Place placer une case vide (*blank*) à la position (<i>,<j>).\n");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// Create new game
|
||||
game g = game_default();
|
||||
// test if game is over
|
||||
uint i;
|
||||
uint j;
|
||||
char taberr[DEFAULT_SIZE*DEFAULT_SIZE*4];
|
||||
char c;
|
||||
// print game
|
||||
game_print(g);
|
||||
while (!game_is_over(g)){
|
||||
// print errors
|
||||
if (checkerr(g,taberr)){
|
||||
printf("Il y a un problème case: %s\n",taberr);
|
||||
}
|
||||
printf("Entrez une commande (h pour afficher l'aide): ");
|
||||
if (scanf(" %c",&c)){
|
||||
if (c == 'h'){
|
||||
printhelp();
|
||||
}else if (c == 'r'){
|
||||
game_restart(g);
|
||||
printf("Partie réinitialisé avec success !\n");
|
||||
game_update_flags(g);
|
||||
game_print(g);
|
||||
}else if (c == 'q'){
|
||||
printf("shame\n");
|
||||
return EXIT_SUCCESS;
|
||||
}else if (c == 'l' || c == 'm' || c == 'b'){
|
||||
if (scanf(" %u %u",&i,&j) == 2){
|
||||
if (i < DEFAULT_SIZE && j < DEFAULT_SIZE && !game_is_black(g,i,j)){
|
||||
if (c == 'l'){
|
||||
game_set_square(g,i,j,S_LIGHTBULB);
|
||||
game_update_flags(g);
|
||||
game_print(g);
|
||||
}else if (c == 'm'){
|
||||
game_set_square(g,i,j,S_MARK);
|
||||
game_update_flags(g);
|
||||
game_print(g);
|
||||
}else if (c == 'b') {
|
||||
game_set_square(g,i,j,S_BLANK);
|
||||
game_update_flags(g);
|
||||
game_print(g);
|
||||
}
|
||||
}else {
|
||||
printf("Erreur: (<i>,<j>) invalide.\n");
|
||||
}
|
||||
}else {
|
||||
printf("Commande inconnue.\n");
|
||||
}
|
||||
}else{
|
||||
printf("Commande inconnue.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("congratulation\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in new issue
Block a user