Files
Sokoban/function.c
2024-12-12 20:46:48 +01:00

226 lines
5.1 KiB
C

#include "function.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
unsigned short int **
creatArea2D (const unsigned int N)
{
unsigned short int **tab2d;
tab2d = calloc (N, sizeof (unsigned short int *));
if (tab2d == NULL)
{
return NULL;
}
bool fail = false;
unsigned int i;
for (i = 0; i < N && !fail; ++i)
{
tab2d[i] = calloc (N, sizeof (unsigned short int));
if (tab2d[i] == NULL)
{
fail = true;
}
}
if (fail)
{
unsigned int j;
for (j = 0; j < i; ++j)
{
free (tab2d[j]);
}
free (tab2d);
return NULL;
}
return tab2d;
}
short int
canIGoDirection (short int valueOfNCase, short int valueOfNPlusOneCase)
{
if (valueOfNCase != WALL)
{
if ((valueOfNCase == BOX && valueOfNPlusOneCase == EMPTY)
|| (valueOfNCase == BOX && valueOfNPlusOneCase == TARGET))
{
if (valueOfNPlusOneCase == TARGET)
{
// Box on target
return 3;
}
// move the box
return 2;
}
if ((valueOfNCase == BOX_ON_TARGET && valueOfNPlusOneCase == EMPTY)
|| (valueOfNCase == BOX_ON_TARGET && valueOfNPlusOneCase == TARGET))
{
if (valueOfNPlusOneCase == TARGET)
{
// Box on target and player on target too
return 6;
}
// move the box but player on a target
return 5;
}
if (valueOfNCase == TARGET)
{
// move player on target
return 4;
}
if (valueOfNCase == EMPTY)
{
// move player
return 1;
}
}
return 0;
}
void move (unsigned short int **tab, vect *playerPos, vect direction)
{
short int valueOfNCase
= tab[playerPos->x + direction.x][playerPos->y + direction.y];
short int valueOfNPlusOneCase
= tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2];
short int returnValue = canIGoDirection (valueOfNCase, valueOfNPlusOneCase);
short int playerState = tab[playerPos->x][playerPos->y];
switch (returnValue)
{
case 0:
break;
case 1:
// move player
tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER;
break;
case 2:
// move player and the box
tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER;
tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2]
= BOX;
break;
case 3:
// move player and the box is well-placed
tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER;
tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2]
= BOX_ON_TARGET;
break;
case 4:
// move player on a target
tab[playerPos->x + direction.x][playerPos->y + direction.y]
= PLAYER_ON_TARGET;
break;
case 5:
// move box and player on a target
tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2]
= BOX;
tab[playerPos->x + direction.x][playerPos->y + direction.y]
= PLAYER_ON_TARGET;
break;
case 6:
// move player on a target and box on a target
tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2]
= BOX_ON_TARGET;
tab[playerPos->x + direction.x][playerPos->y + direction.y]
= PLAYER_ON_TARGET;
break;
default:
printf ("Commande inconnue !\n");
}
if (returnValue != 0)
{
if (playerState == PLAYER_ON_TARGET)
{
tab[playerPos->x][playerPos->y] = TARGET;
}
else
{
tab[playerPos->x][playerPos->y] = EMPTY;
}
playerPos->x = playerPos->x + direction.x;
playerPos->y = playerPos->y + direction.y;
}
}
void inGameLoop (unsigned short int **tab2d, int N, vect *playerPos, vect *targets, int nbr_targets)
{
vect direction = { 0, 0 };
char input;
bool finish = false;
while (!finish)
{
printf ("Utilisez Z/Q/S/D pour bouger, X pour quitter : ");
input = getchar ();
if (input == 'x')
{
break; // Quitter le jeu
}
switch (input)
{
case 'd':
direction.y = 1;
direction.x = 0;
break;
case 'q':
direction.y = -1;
direction.x = 0;
break;
case 'z':
direction.x = -1;
direction.y = 0;
break;
case 's':
direction.x = 1;
direction.y = 0;
break;
default:
direction.x = 0;
direction.y = 0;
}
system ("clear");
move (tab2d, playerPos, direction);
printf ("\n");
if (isWin(tab2d, targets, nbr_targets))
{
finish = true;
}
screenDisplay (tab2d, N);
}
}
bool isWin(unsigned short int **tab2d, vect *targets, int nbr_targets)
{
int i;
for (i = 0; i < nbr_targets; ++i)
{
int x = targets[i].x;
int y = targets[i].y;
if (tab2d[x][y] != BOX_ON_TARGET)
{
return false;
}
}
return true;
}