[gcc] pacman en c (mode console curses)

Description

Voilà le dernier projet d'un cours que j'ai suivi. J'utilise la librairie curses pour le mode graphique du jeu. Je ne pense pas qu'elle soit disponible sous windows (ou p-e avec cygwin). Je pense peut-être l'améliorer plus tard, hiérarchie de niveaux, difficultés,etc...Et passer en mode fenêtré avec GTK+ ou autre (nouveau pour moi).
Voilà, le code est propre, commenté (en anglais).
Pour les labirynthes : S=MUR , p=PacMan , d=DRAGON , t=TRESOR , v= Voleur.
Une partie du code est tiré de la solution des profs, le projet étant étalé sur plusieurs semaines. Ce code est toutefois celui que j'ai rendu et sur lequel j'ai été coté.

Voilà c'est tout, le Makefile est fourni avec, pour compiler, il suffit de taper MAKE après avoir dézippé le tout.

MAj : Voila un screen (bizarement g du remmetre des # comme murs car les carres blanc ne marchent plus avec mandrake 10 O_o). J'ai ajouté l'éxéctuable Unix compilé. Pour le win32..wait & see....maybe for a long time.....

Source / Exemple :


//Code du PacMan.c !

#include <pthread.h>
#include "PacManInput.h"
#include "PacManOutput.h"
#include "PacManScene.h"
#include <stdlib.h>         // For exit()
#include <stdio.h>          // For file reading
#include <stdbool.h>        // For booleans
#define _XOPEN_SOURCE 500	/* for usleep() */
#include <unistd.h>		/* for usleep() */
#define MUTEX
#ifdef MUTEX
pthread_mutex_t mutex;
#endif

/*---------------------------------------------------------------------*

  • Game constants.
  • ---------------------------------------------------------------------*/
static const float DRAGON_FAC = 0.5; // Score ratio reaching a dragon static const float GHOST_FAC = 0.5; // Score ratio reaching a ghost static const int TREASURE_SUM = 50; // Score bonus reaching a treasure static const int THIEF_SUM = 100; // Score ratio reaching a thief(boss) /*---------------------------------------------------------------------*
  • Data structure gathering all the informations about a possible
  • state of the game.
  • ---------------------------------------------------------------------*/
typedef struct pmAgentList_t { // Data type for a linked list of agents PmAgent agent; // One agent struct pmAgentList_t *next; // Pointer to the next agent in the list } PmAgentList; typedef struct { int width, height; // Size of the labyrinth PmAgent pacman; // PacMan's position PmScene* scene; // Maze description PmAgentList *dragons; // Linked list of dragons int numCrumbs; // Number of crumbs yet to eat int numTreasures; // Number of treasures yet to recover int initTreasures; // Number of treasures at the start int score; // Current score // New fields : PmAgentList *ghosts; // Linked list of ghosts PmAgent thief; // Thief's position bool isKnowthief; // Is there is a thief in the lab PmiCommand userCommand; // The user command for pacman } PmState; /*---------------------------------------------------------------------*
  • Error function displaying a message and terminating the program.
*
  • PARAMETERS
  • msg the error message to display
*
  • RETURN:
  • nothing
  • ---------------------------------------------------------------------*/
static void error_exit(const char *msg) { // Close the input and the output pmiClose(); pmoClose(); printf("Fatal error: %s\n", msg); // Print the message exit(1); // Terminate the program } /*---------------------------------------------------------------------*
  • Free a game state.
*
  • PARAMETERS
  • pmState the game state to free
*
  • RETURN:
  • nothing
  • ---------------------------------------------------------------------*/
static void freeGameState(PmState *pmState) { while (pmState->dragons) { // Free the dragon list PmAgentList *head = pmState->dragons; pmState->dragons = head->next; free(head); } while (pmState->ghosts) { // Free the ghosts list PmAgentList *head = pmState->ghosts; pmState->ghosts = head->next; free(head); } pmsDeleteScene(pmState->scene); // Free the scene free(pmState); // Free the game state structure } /*---------------------------------------------------------------------*
  • Initializes one cell in the labyrinth according to some character
  • from the maze description file.
*
  • PARAMETERS
  • pmState the state of the game
  • x, y the coordinates of the cell to initialize
  • thisChar the character from the maze description file
  • isPacManPositionKnown a pointer to a Boolean flag telling whether
  • PacMan's initial position is already known
*
  • RETURN:
  • nothing
  • ---------------------------------------------------------------------*/
static void initCell(PmState *pmState, int x, int y, int thisChar, bool *isPacManPositionKnown) { // Deduce the cell content from the character if (thisChar != 'S' && thisChar != 'p') { // The space contains one crumb pmState->numCrumbs++; pmsPutCell(pmState->scene, x, y, CRUMB); if (pmoDrawCell(x, y, CRUMB)) error_exit("pmoDrawCell(CRUMB)"); } switch (thisChar) { case ' ' : // Blank space break; case 'S' : // Solid space pmsPutCell(pmState->scene, x, y, SOLID); if (pmoDrawCell(x, y, SOLID)) error_exit("pmoDrawCell(SOLID)"); break; case 'p' : // PacMan's initial position if (*isPacManPositionKnown) error_exit("Two PacMan's initial positions given"); // Set PacMan's initial position pmState->pacman.x = x; pmState->pacman.y = y; pmState->pacman.type = PACMAN;
  • isPacManPositionKnown = true;
pmsPutAgent(pmState->scene, &pmState->pacman); if (pmoDrawAgent(&pmState->pacman)) error_exit("pmoDrawCell(PACMAN)"); break; case 'd' : { // Dragon // Allocate a new dragon PmAgentList *newDragon = malloc(sizeof(PmAgentList)); if (!newDragon) error_exit("malloc(dragon)"); // Set informations for the dragon newDragon->agent.x = x; newDragon->agent.y = y; newDragon->agent.type = DRAGON; // Add the new dragon in the dragon list newDragon->next = pmState->dragons; pmState->dragons = newDragon; pmsPutAgent(pmState->scene, &newDragon->agent); if (pmoDrawAgent(&newDragon->agent)) error_exit("pmoDrawCell(DRAGON)"); break; } case 'g' : { // Ghost // Allocate a new ghost PmAgentList *newGhost = malloc(sizeof(PmAgentList)); if (!newGhost) error_exit("malloc(ghost)"); // Set informations for the ghost newGhost->agent.x = x; newGhost->agent.y = y; newGhost->agent.type = GHOST; // Add the new ghost in the ghost list newGhost->next = pmState->ghosts; pmState->ghosts = newGhost; pmsPutAgent(pmState->scene, &newGhost->agent); if (pmoDrawAgent(&newGhost->agent)) error_exit("pmoDrawCell(GHOST)"); break; } case 'v' : //Thief if (pmState->isKnowthief) error_exit("Two thiefs's initial positions given"); pmState->isKnowthief = true; // Set Thief's initial position pmState->thief.x = x; pmState->thief.y = y; pmState->thief.type = THIEF; pmsPutAgent(pmState->scene, &pmState->thief); if (pmoDrawAgent(&pmState->thief)) error_exit("pmoDrawCell(THIEF)"); break; case 't' : { // Treasure pmState->numTreasures++; pmState->initTreasures++; // For thief factor pmsPutCell(pmState->scene, x, y, TREASURE); if (pmoDrawCell(x, y, TREASURE)) error_exit("pmoDrawCell(TREASURE)"); break; } default: // Error error_exit("Unknown cell content"); } } /*---------------------------------------------------------------------*
  • Reads a maze and display its content on screen.
*
  • PARAMETERS
  • filename the name of the file containing the labyrinth
  • pmState the state of the game
*
  • RETURN:
  • nothing
  • ---------------------------------------------------------------------*/
static void initLabyrinth(const char* filename, PmState *pmState) { // Open the given file in read mode FILE *file = fopen(filename, "r"); if (!file) error_exit(filename); // Some useful variables bool isPacManPositionKnown = false; // Becomes true when 'p' is met int thisChar = fgetc(file); while (thisChar != EOF) { // This block is executed once for each line in the file int posX = 0; while (thisChar != '\n' && thisChar != EOF) { // This block is executed once for each character in the current line initCell(pmState, posX++, pmState->height, thisChar, &isPacManPositionKnown); // Read the next character in the line thisChar = fgetc(file); } if (posX != pmState->width) error_exit("Maze with different column sizes"); // Read the first character of the next line if (thisChar != EOF) thisChar = fgetc(file); pmState->height++; } // The maze is read : close the opened file fclose(file); // Check the validity of the maze if (!isPacManPositionKnown) error_exit("The maze file doesn't give PacMan's initial position"); } /*---------------------------------------------------------------------*
  • Reads the width of a maze in a labyrinth description file.
*
  • PARAMETERS
  • filename the name of the file containing the labyrinth
*
  • RETURN:
  • the width of the maze
  • ---------------------------------------------------------------------*/
static int readLabyrinthWidth(const char *filename) { // Open the given file in read mode FILE *file = fopen(filename, "r"); if (!file) error_exit(filename); int width = 0; // Count the number of characters in the first line of the file while (true) { int thisChar = fgetc(file); if (thisChar == '\n' || thisChar == EOF) { if (!width) error_exit("Maze with empty columns"); fclose(file); return width; } width++; } } /*---------------------------------------------------------------------*
  • Checks whether a cell is accessible for PacMan.
*
  • PARAMETERS
  • pmState the game state
  • x, y the cell coordinates
*
  • RETURN:
  • true iff the cell is accessible
  • ---------------------------------------------------------------------*/
static bool isAccessible(PmState *pmState, int x, int y,PmCellContent type) { // Checks whether the cell exists if (x < 0 || x >= pmState->width || y < 0 || y >= pmState->height) return false; //Disable the possibily for Dragons & Thief to go //to a cellule containg a solid or an other agent //(agent who is not pacman) if (type == DRAGON || type==THIEF){ if ((pmsGetCell(pmState->scene, x, y) & DRAGON) || (pmsGetCell(pmState->scene, x, y) & GHOST) || (pmsGetCell(pmState->scene, x, y) & THIEF) || (pmsGetCell(pmState->scene, x, y) & SOLID)) return false; } //Disable the possibily for Ghosts to go to //a cellule containing an other //(agent who is not pacman) if (type == GHOST){ if ((pmsGetCell(pmState->scene, x, y) & DRAGON) || (pmsGetCell(pmState->scene, x, y) & THIEF) || (pmsGetCell(pmState->scene, x, y) & GHOST)) return false; } //return false if the cellule who want to go pacman //is a solid. if (type == PACMAN) return !(pmsGetCell(pmState->scene, x, y) & SOLID); //return true, the agent can move. return true; } /*---------------------------------------------------------------------*
  • Updates the score.
*
  • PARAMETERS
  • pmState the game state
  • command the action to do
*
  • RETURN:
  • nothing
  • ---------------------------------------------------------------------*/
static void updateScore(PmState *pmState) { // Read PacMan's position int x = pmState->pacman.x; int y = pmState->pacman.y; // Get the contents of this cell PmCellContent content = pmsGetCell(pmState->scene, x, y); if (content & CRUMB) { // A crumb is in the cell pmState->score++; pmState->numCrumbs--; pmsClearCell(pmState->scene, x, y, CRUMB); } if (content & TREASURE) { // A treasure is in the cell pmState->score += TREASURE_SUM; pmState->numTreasures--; pmsClearCell(pmState->scene, x, y, TREASURE); } if (content & DRAGON) // A dragon is in the cell pmState->score *= DRAGON_FAC; if (content & GHOST) // A ghost is in the cell pmState->score *= GHOST_FAC; if (content & THIEF) // A thief is in the cell pmState->score -= THIEF_SUM; } /*---------------------------------------------------------------------*
  • Move Dragons according to the position of Pacman.
*
  • PARAMETERS
  • params a pointer to pmState structure
* *
  • RETURN:
  • NULL
  • ---------------------------------------------------------------------*/
void* moveDragons(void* params) { //change the void* pointer to a PmState pointer //Not elegant but this is a solution for the warning //arg 3(must be void*) in function pthread_create. PmState* pmThreads = (PmState*)params; #ifdef MUTEX pthread_mutex_lock(&mutex); #endif while ((pmThreads->score > 0) && (pmThreads->userCommand != QUIT)){ int x = pmThreads->pacman.x; int y = pmThreads->pacman.y; int numDragons=0; PmAgentList *head = pmThreads->dragons; while (pmThreads->dragons) { pmThreads->dragons = pmThreads->dragons->next; numDragons++; } pmThreads->dragons = head; PmiCommand command=NONE; for (int i=0; i < numDragons; i++){ int agentPosX = pmThreads->dragons->agent.x; int agentPosY = pmThreads->dragons->agent.y; PmCellContent agentType = pmThreads->dragons->agent.type; //Clear the cell where was Dragon if (pmoDrawCell(agentPosX, agentPosY, pmsClearCell(pmThreads->scene, agentPosX, agentPosY, DRAGON))) error_exit("pmoDrawCell(DRAGON)"); if (agentPosX < x) { if (agentPosY == y) command=RIGHT; else if (agentPosY > y) command=UPRIGHT; else if (agentPosY < y) command=BOTRIGHT; } else if (agentPosX > x) { if (agentPosY == y) command=LEFT; else if (agentPosY > y) command=UPLEFT; else if (agentPosY < y) command=BOTLEFT; } else if (agentPosX == x){ if (agentPosY > y) command=UP; else if (agentPosY < y) command=DOWN; } switch (command) { case UP: if (isAccessible(pmThreads, agentPosX, agentPosY - 1,agentType)) pmThreads->dragons->agent.y--; break; case DOWN: if (isAccessible(pmThreads, agentPosX, agentPosY + 1,agentType)) pmThreads->dragons->agent.y++; break; case LEFT: if (isAccessible(pmThreads, agentPosX - 1, agentPosY,agentType)) pmThreads->dragons->agent.x--; break; case RIGHT: if (isAccessible(pmThreads, agentPosX + 1, agentPosY,agentType)) pmThreads->dragons->agent.x++; break; case BOTRIGHT: if (isAccessible(pmThreads, agentPosX + 1, agentPosY,agentType)) pmThreads->dragons->agent.x++; agentPosX = pmThreads->dragons->agent.x; if (isAccessible(pmThreads, agentPosX, agentPosY + 1,agentType)) pmThreads->dragons->agent.y++; break; case BOTLEFT: if (isAccessible(pmThreads, agentPosX - 1, agentPosY,agentType)) pmThreads->dragons->agent.x--; agentPosX = pmThreads->dragons->agent.x; if (isAccessible(pmThreads, agentPosX, agentPosY + 1,agentType)) pmThreads->dragons->agent.y++; break; case UPRIGHT: if (isAccessible(pmThreads, agentPosX + 1, agentPosY,agentType)) pmThreads->dragons->agent.x++; agentPosX = pmThreads->dragons->agent.x; if (isAccessible(pmThreads, agentPosX, agentPosY - 1,agentType)) pmThreads->dragons->agent.y--; break; case UPLEFT: if (isAccessible(pmThreads, agentPosX - 1, agentPosY,agentType)) pmThreads->dragons->agent.x--; agentPosX = pmThreads->dragons->agent.x; if (isAccessible(pmThreads, agentPosX, agentPosY - 1,agentType)) pmThreads->dragons->agent.y--; break; default: return NULL; } //Put the agent at its new position pmsPutAgent(pmThreads->scene,&pmThreads->dragons->agent); // Display Dragon at its new position if (pmoDrawAgent(&pmThreads->dragons->agent)) error_exit("pmoDrawCell(DRAGON)"); // Refresh the display if (pmoFlush()) error_exit("pmoFlush"); pmThreads->dragons = pmThreads->dragons->next; } #ifdef MUTEX pthread_mutex_unlock(&mutex); #endif if (pmThreads->userCommand!=QUIT) sleep(1); //reset the pointer to the head pmThreads->dragons = head; } return NULL; } /*---------------------------------------------------------------------*
  • Move Ghosts according to the position of Pacman.
*
  • PARAMETERS
  • params a pointer to pmState structure
* *
  • RETURN:
  • NULL
  • ---------------------------------------------------------------------*/
static void* moveGhosts(void* params) { //change the void* pointer to a PmState pointer //Not elegant but this is a solution for the warning //arg 3(must be void*) in function pthread_create. PmState* pmThreads = (PmState*)params; PmiCommand command=NONE; #ifdef MUTEX pthread_mutex_lock(&mutex); #endif while ((pmThreads->score > 0) && (pmThreads->userCommand!=QUIT)){ int x = pmThreads->pacman.x; int y = pmThreads->pacman.y; int numGhosts=0; //Pointer at the top of the agent list PmAgentList *head = pmThreads->ghosts; //Get the number of agent while (pmThreads->ghosts) { pmThreads->ghosts = pmThreads->ghosts->next; numGhosts++; } //Reset the pointer to the head of the agent list pmThreads->ghosts = head; for (int i=0; i < numGhosts; i++){ int agentPosX = pmThreads->ghosts->agent.x; int agentPosY = pmThreads->ghosts->agent.y; PmCellContent agentType = pmThreads->ghosts->agent.type; //Clear the cell where was Ghost if (pmoDrawCell(agentPosX, agentPosY, pmsClearCell(pmThreads->scene, agentPosX, agentPosY, GHOST))) error_exit("pmoDrawCell(GHOST)"); if (agentPosX < x) { if (agentPosY == y) command=RIGHT; else if (agentPosY > y) command=UPRIGHT; else if (agentPosY < y) command=BOTRIGHT; } else if (agentPosX > x) { if (agentPosY == y) command=LEFT; else if (agentPosY > y) command=UPLEFT; else if (agentPosY < y) command=BOTLEFT; } else if (agentPosX == x){ if (agentPosY > y) command=UP; else if (agentPosY < y) command=DOWN; } switch (command) { case UP: if (isAccessible(pmThreads, agentPosX, agentPosY - 1,agentType)) pmThreads->ghosts->agent.y--; break; case DOWN: if (isAccessible(pmThreads, agentPosX, agentPosY + 1,agentType)) pmThreads->ghosts->agent.y++; break; case LEFT: if (isAccessible(pmThreads, agentPosX - 1, agentPosY,agentType)) pmThreads->ghosts->agent.x--; break; case RIGHT: if (isAccessible(pmThreads, agentPosX + 1, agentPosY,agentType)) pmThreads->ghosts->agent.x++; break; case BOTRIGHT: if (isAccessible(pmThreads, agentPosX + 1, agentPosY,agentType)){ pmThreads->ghosts->agent.x++; agentPosX = pmThreads->ghosts->agent.x; if (isAccessible(pmThreads, agentPosX, agentPosY + 1,agentType)) pmThreads->ghosts->agent.y++; } break; case BOTLEFT: if (isAccessible(pmThreads, agentPosX - 1, agentPosY,agentType)){ pmThreads->ghosts->agent.x--; agentPosX = pmThreads->ghosts->agent.x; if (isAccessible(pmThreads, agentPosX, agentPosY + 1,agentType)) pmThreads->ghosts->agent.y++; } break; case UPRIGHT: if (isAccessible(pmThreads, agentPosX + 1, agentPosY,agentType)){ pmThreads->ghosts->agent.x++; agentPosX = pmThreads->ghosts->agent.x; } if (isAccessible(pmThreads, agentPosX, agentPosY - 1,agentType)) pmThreads->ghosts->agent.y--; break; case UPLEFT: if (isAccessible(pmThreads, agentPosX - 1, agentPosY,agentType)){ pmThreads->ghosts->agent.x--; agentPosX = pmThreads->ghosts->agent.x; if (isAccessible(pmThreads, agentPosX, agentPosY - 1,agentType)) pmThreads->ghosts->agent.y--; } break; default: return NULL; } //Put the agent at its new position pmsPutAgent(pmThreads->scene,&pmThreads->ghosts->agent); // Display Ghost at its new position if (pmoDrawAgent(&pmThreads->ghosts->agent)) error_exit("pmoDrawCell(GHOST)"); // Refresh the display if (pmoFlush()) error_exit("pmoFlush"); pmThreads->ghosts = pmThreads->ghosts->next; } #ifdef MUTEX pthread_mutex_unlock(&mutex); #endif if (pmThreads->userCommand!=QUIT) sleep(2); pmThreads->ghosts = head; } return NULL; } /*---------------------------------------------------------------------*
  • Move the Thief according to the position of Pacman.
*
  • PARAMETERS
  • params a pointer to pmState structure
* *
  • RETURN:
  • NULL
  • ---------------------------------------------------------------------*/
void* moveThief(void* params) { //change the void* pointer to a PmState pointer //Not elegant but this is a solution for the warning //arg 3(must be void*) in function pthread_create. PmState* pmThreads = (PmState*)params; #ifdef MUTEX pthread_mutex_lock(&mutex); #endif while ((pmThreads->score > 0) && pmThreads->userCommand != QUIT){ int x = pmThreads->pacman.x; int y = pmThreads->pacman.y; PmiCommand command=NONE; int agentPosX = pmThreads->thief.x; int agentPosY = pmThreads->thief.y; PmCellContent agentType = pmThreads->thief.type; //Clear the cell where was Dragon if (pmoDrawCell(agentPosX, agentPosY, pmsClearCell(pmThreads->scene, agentPosX, agentPosY, THIEF))) error_exit("pmoDrawCell(THIEF)"); if (agentPosX < x) { if (agentPosY == y) command=RIGHT; else if (agentPosY > y) command=UPRIGHT; else if (agentPosY < y) command=BOTRIGHT; } else if (agentPosX > x) { if (agentPosY == y) command=LEFT; else if (agentPosY > y) command=UPLEFT; else if (agentPosY < y) command=BOTLEFT; } else if (agentPosX == x){ if (agentPosY > y) command=UP; else if (agentPosY < y) command=DOWN; } switch (command) { case UP: if (isAccessible(pmThreads, agentPosX, agentPosY - 2,agentType)) pmThreads->thief.y-=2; break; case DOWN: if (isAccessible(pmThreads, agentPosX, agentPosY + 2,agentType)) pmThreads->thief.y+=2; break; case LEFT: if (isAccessible(pmThreads, agentPosX - 2, agentPosY,agentType)) pmThreads->thief.x-=2; break; case RIGHT: if (isAccessible(pmThreads, agentPosX + 2, agentPosY,agentType)) pmThreads->thief.x+=2; break; case BOTRIGHT: if (isAccessible(pmThreads, agentPosX + 2, agentPosY,agentType)) pmThreads->thief.x+=2; agentPosX = pmThreads->thief.x; if (isAccessible(pmThreads, agentPosX, agentPosY + 2,agentType)) pmThreads->thief.y+=2; break; case BOTLEFT: if (isAccessible(pmThreads, agentPosX - 2, agentPosY,agentType)) pmThreads->thief.x-=2; agentPosX = pmThreads->thief.x; if (isAccessible(pmThreads, agentPosX, agentPosY + 2,agentType)) pmThreads->thief.y+=2; break; case UPRIGHT: if (isAccessible(pmThreads, agentPosX + 2, agentPosY,agentType)) pmThreads->thief.x+=2; agentPosX = pmThreads->thief.x; if (isAccessible(pmThreads, agentPosX, agentPosY - 2,agentType)) pmThreads->thief.y-=2; break; case UPLEFT: if (isAccessible(pmThreads, agentPosX - 2, agentPosY,agentType)) pmThreads->thief.x-=2; agentPosX = pmThreads->thief.x; if (isAccessible(pmThreads, agentPosX, agentPosY - 2,agentType)) pmThreads->thief.y-=2; break; default: return NULL; } //Put the agent at its new position pmsPutAgent(pmThreads->scene,&pmThreads->thief); // Display Dragon at its new position if (pmoDrawAgent(&pmThreads->thief)) error_exit("pmoDrawCell(THIEF)"); // Refresh the display if (pmoFlush()) error_exit("pmoFlush"); if (pmThreads->userCommand!=QUIT) sleep(2); } #ifdef MUTEX pthread_mutex_unlock(&mutex); #endif return NULL; } /*---------------------------------------------------------------------*
  • Move PacMan according to some command.
*
  • PARAMETERS
  • pmState the game state
  • command the action to do
*
  • RETURN:
  • nothing
  • ---------------------------------------------------------------------*/
static void movePacman(PmState *pmState, PmiCommand command) { // Read PacMan's position int x = pmState->pacman.x; int y = pmState->pacman.y; PmCellContent agentType = pmState->pacman.type; // Move PacMan according to the command (self-documenting) switch (command) { case UP: if (isAccessible(pmState, x, y - 1,agentType)) pmState->pacman.y--; break; case DOWN: if (isAccessible(pmState, x, y + 1,agentType)) pmState->pacman.y++; break; case LEFT: if (isAccessible(pmState, x - 1, y,agentType)) pmState->pacman.x--; break; case RIGHT: if (isAccessible(pmState, x + 1, y,agentType)) pmState->pacman.x++; break; default: return; } // Clear the cell where was PacMan if (pmoDrawCell(x, y, pmsClearCell(pmState->scene, x, y, PACMAN))) error_exit("pmoDrawCell(PACMAN)"); // Display PacMan at its new position if (pmoDrawAgent(&pmState->pacman)) error_exit("pmoDrawCell(PACMAN)"); // Refresh the display if (pmoFlush()) error_exit("pmoFlush"); } /*---------------------------------------------------------------------*
  • Tests whether the game is over. The game is finished when the score
  • becomes negative ; or where there is no crumb and no treasure
  • remaining.
*
  • PARAMETERS
  • pmState the game state
*
  • RETURN:
  • true only when the game is over
  • ---------------------------------------------------------------------*/
static inline bool isGameOver(PmState *pmState) { return (pmState->score <= 0 || (!pmState->numCrumbs && !pmState->numTreasures)); } /*---------------------------------------------------------------------*
  • Display statistics for the game (self-documenting).
*
  • PARAMETERS
  • pmState the game state
*
  • RETURN:
  • nothing
  • ---------------------------------------------------------------------*/
static void displayStatistics(PmState *pmState) { char buffer[64]; sprintf(buffer, "Score : %5d", pmState->score); if (pmoWriteString(5, pmState->height + 1, buffer)) error_exit("pmoWriteString()"); sprintf(buffer, "Remaining crumbs : %5d", pmState->numCrumbs); if (pmoWriteString(5, pmState->height + 2, buffer)) error_exit("pmoWriteString()"); sprintf(buffer, "Remaining treasures : %5d", pmState->numTreasures); if (pmoWriteString(5, pmState->height + 3, buffer)) error_exit("pmoWriteString()"); if (isGameOver(pmState) && pmoWriteString(3, pmState->height + 5, "> Game over, hit q to exit <")) error_exit("pmoWriteString()"); // Refresh the display if (pmoFlush()) error_exit("pmoFlush"); } /*---------------------------------------------------------------------*
  • Main function
  • ---------------------------------------------------------------------*/
int main(int argc, char* argv[]) { // Initialize the input and the output if (pmiOpen()) error_exit("pmiOpen"); if (pmoOpen()) error_exit("pmoOpen"); if (argc < 2) error_exit("No labyrinth filename given"); //create the threads variables pthread_t dragonMove; pthread_t ghostMove; pthread_t thiefMove; #ifdef MUTEX pthread_mutex_init(&mutex, NULL); #endif // Initialize the game state PmState *pmState = malloc(sizeof(PmState)); if (!pmState) error_exit("malloc(pmState)"); pmState->isKnowthief = false; pmState->width = readLabyrinthWidth(argv[1]); // Read the maze width pmState->height = 0; pmState->scene = pmsInitScene(pmState->width); // Allocate the scene pmState->dragons = NULL; pmState->ghosts = NULL; pmState->numCrumbs = 0; pmState->numTreasures = 0; pmState->score = 1; // Read a game state from the description file given in argument initLabyrinth(argv[1], pmState); //a pointer to pmState structure void* params = pmState; /* Start three threads: */ if (pthread_create(&dragonMove, NULL, moveDragons, params)) printf("thread error\n"); if (pthread_create(&ghostMove, NULL, moveGhosts, params)) printf("thread error\n"); if (pmState->isKnowthief){ if (pthread_create(&thiefMove, NULL, moveThief, params)) printf("thread error\n"); } // Main loop int keepPlaying = true; PmiCommand command=NONE; PmiCommand temp; while (keepPlaying) { displayStatistics(pmState); // if the user give a command, the command // is given to the variable 'command' who // will change the direction of pacman if ((temp = pmiGetCommand()) != 0){ command=temp; pmState->userCommand=command; } //Quit if 'q' is given if (temp == QUIT) { keepPlaying = false; } else if (!isGameOver(pmState)) { // The game is not finished yet movePacman(pmState, command); updateScore(pmState); } } //Waiting the end of threads if (pmState->ghosts) pthread_join(ghostMove, NULL); if (pmState->dragons) pthread_join(dragonMove, NULL); if (pmState->isKnowthief) pthread_join(thiefMove, NULL); #ifdef MUTEX pthread_mutex_destroy(&mutex); #endif //Free the game state freeGameState(pmState); // Close the input and the output if (pmiClose()) error_exit("pmiClose"); if (pmoClose()) error_exit("pmoClose"); return 0; }

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.