sokosol4.c
changeset 0 be33ecaa3619
equal deleted inserted replaced
-1:000000000000 0:be33ecaa3619
       
     1 #include <stdio.h>
       
     2 #include <string.h>
       
     3 
       
     4 #define BOX '$'
       
     5 #define WALL '#'
       
     6 #define MAN '@'
       
     7 #define PLATFORM '.'
       
     8 #define BOXINPLATFORM '*'
       
     9 #define MANINPLATFORM 'E'
       
    10 #define BLANK ' '
       
    11 #define CANTO '-'
       
    12 
       
    13 #define DIR_LEFT 'A'
       
    14 #define DIR_RIGHT 'B'
       
    15 #define DIR_UP 'C'
       
    16 #define DIR_DOWN 'D'
       
    17 
       
    18 #define MAX_X 50
       
    19 #define MAX_Y 50
       
    20 #define MAX_MOVES 50
       
    21 
       
    22 #define MOVE_OK		1
       
    23 #define MOVE_BOX	2
       
    24 #define MOVE_ILLEGAL	0
       
    25 
       
    26 /* SOKOBAN Solution Finder
       
    27  *
       
    28  * Cerca totes les possibilitats de tots els nombres de combinacions possibles,
       
    29  * menys la que tots els moviments són a l'esquerra del número de combinacions
       
    30  * incials triat.
       
    31  */
       
    32 
       
    33 
       
    34 struct Map
       
    35 {
       
    36 	char Cells[MAX_X][MAX_Y];
       
    37 	int SizeX, SizeY;
       
    38 	int ManX, ManY;
       
    39 	int NumPlatforms;
       
    40 	int NumBoxesInPlatform;
       
    41 	char BoxMoved;		// Boolean
       
    42 };
       
    43 
       
    44 
       
    45 
       
    46 void ReadMap(struct Map *M, char *FileName)
       
    47 {
       
    48 	FILE *Fitxer;
       
    49 	int i,j;
       
    50 
       
    51 	if(!(Fitxer = fopen(FileName, "r")))
       
    52 	{
       
    53 		printf("Error opening %s!", FileName);
       
    54 		exit(1);
       
    55 	}
       
    56 
       
    57 	M->SizeX=0;
       
    58 	M->SizeY=0;
       
    59 	while (!feof(Fitxer))
       
    60 	{
       
    61 		fgets(M->Cells[M->SizeY++], MAX_X, Fitxer);
       
    62 	}
       
    63 	M->SizeY--;
       
    64 	M->SizeX = strlen(M->Cells[0]) - 1;
       
    65 
       
    66 	M->NumPlatforms = 0;
       
    67 	M->NumBoxesInPlatform = 0;
       
    68 	for (j = 0; j<M->SizeY; j++)
       
    69 		for (i=0; i<M->SizeX; i++)
       
    70 		{
       
    71 			if (M->Cells[j][i] == MAN)
       
    72 			{ M->ManX = i; M->ManY = j; }
       
    73 			if (M->Cells[j][i] == PLATFORM)
       
    74 				M->NumPlatforms++;
       
    75 			else if (M->Cells[j][i] == BOXINPLATFORM)
       
    76 			{
       
    77 				M->NumPlatforms++;
       
    78 				M->NumBoxesInPlatform++;
       
    79 			} else if (M->Cells[j][i] != WALL)
       
    80 				if ((M->Cells[j][i-1] == WALL &&
       
    81 					M->Cells[j-1][i] == WALL) ||
       
    82 					(M->Cells[j][i-1] == WALL &&
       
    83 					M->Cells[j+1][i] == WALL) ||
       
    84 					(M->Cells[j][i+1] == WALL &&
       
    85 					M->Cells[j-1][i] == WALL) ||
       
    86 					(M->Cells[j][i+1] == WALL &&
       
    87 					M->Cells[j+1][i] == WALL))
       
    88 				M->Cells[j][i] = CANTO;
       
    89 		}
       
    90 
       
    91 	M->Cells[M->ManY][M->ManX] = BLANK;
       
    92 	M->BoxMoved = 0;	// Needed?
       
    93 }
       
    94 
       
    95 
       
    96 void ShowMap (struct Map *M)
       
    97 {
       
    98 	int i,j;
       
    99 	for (j = 0; j<M->SizeY; j++)
       
   100 	{
       
   101 		for (i=0; i<M->SizeX; i++)
       
   102 			printf("%c", M->Cells[j][i]);
       
   103 		printf("\n");
       
   104 	}
       
   105 	printf("Man is at (%i,%i)\n", M->ManX, M->ManY);
       
   106 	printf("Platforms: %i, BoxesInPlatform: %i\n", M->NumPlatforms,
       
   107 			M->NumBoxesInPlatform);
       
   108 }
       
   109 
       
   110 
       
   111 
       
   112 void CopyMap (struct Map *Mdest, struct Map *Morig)
       
   113 {
       
   114 	memcpy((void *) Mdest, (void *) Morig, sizeof (struct Map));
       
   115 }
       
   116 
       
   117 int MoveMan (struct Map *M, int Direction)
       
   118 {
       
   119 	int NewX, NewY;
       
   120 
       
   121 /*
       
   122 	// Check if man is where it should be
       
   123 	if (M->Cells[M->ManY][M->ManX] != MAN &&
       
   124 		M->Cells[M->ManY][M->ManX] != MANINPLATFORM)
       
   125 	{
       
   126 		printf("Man isn't where it should be!\n");
       
   127 		exit(2);
       
   128 	}
       
   129 */
       
   130 
       
   131 	// Process Movement
       
   132 	if (Direction == DIR_LEFT)
       
   133 	{ NewX = M->ManX - 1; NewY = M->ManY; }
       
   134 	else if (Direction == DIR_RIGHT)
       
   135 	{ NewX = M->ManX + 1; NewY = M->ManY; }
       
   136 	else if (Direction == DIR_UP)
       
   137 	{ NewX = M->ManX; NewY = M->ManY - 1; }
       
   138 	else
       
   139 	{ NewX = M->ManX; NewY = M->ManY + 1; }
       
   140 
       
   141 
       
   142 
       
   143 	// What's in front of the man?
       
   144 
       
   145 	if (M->Cells[NewY][NewX] == WALL)
       
   146 	{
       
   147 		return MOVE_ILLEGAL;	// ILLEGAL MOVE
       
   148 	}
       
   149 	else if (M->Cells[NewY][NewX] == BOX)
       
   150 	{
       
   151 		if (M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)] ==
       
   152 			BLANK)
       
   153 		{
       
   154 			M->Cells[NewY][NewX] = BLANK;
       
   155 			M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)]
       
   156 				= BOX;
       
   157 
       
   158 			M->ManX = NewX; M->ManY = NewY;
       
   159 			M->BoxMoved = 1;
       
   160 			return MOVE_BOX;
       
   161 		}
       
   162 		else
       
   163 		if (M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)] ==
       
   164 				PLATFORM)
       
   165 		{
       
   166 			M->Cells[NewY][NewX] = BLANK;
       
   167 			M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)]
       
   168 				= BOXINPLATFORM;
       
   169 
       
   170 			M->ManX = NewX; M->ManY = NewY;
       
   171 
       
   172 			M->NumBoxesInPlatform++;
       
   173 			M->BoxMoved = 1;
       
   174 			return MOVE_BOX;
       
   175 		}
       
   176 		else
       
   177 		{
       
   178 			return MOVE_ILLEGAL;	// ILLEGAL MOVE
       
   179 		}
       
   180 	}else
       
   181 	if (M->Cells[NewY][NewX] == BOXINPLATFORM)
       
   182 	{
       
   183 		if (M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)] ==
       
   184 			BLANK)
       
   185 		{
       
   186 			M->Cells[NewY][NewX] = PLATFORM;
       
   187 			M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)]
       
   188 				= BOX;
       
   189 
       
   190 			M->ManX = NewX; M->ManY = NewY;
       
   191 			M->NumBoxesInPlatform--;
       
   192 			M->BoxMoved = 1;
       
   193 			return MOVE_BOX;
       
   194 		}
       
   195 		else
       
   196 		if (M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)] ==
       
   197 				PLATFORM)
       
   198 		{
       
   199 			M->Cells[NewY][NewX] = PLATFORM;
       
   200 			M->Cells[NewY + (NewY-M->ManY)][NewX + (NewX-M->ManX)]
       
   201 				= BOXINPLATFORM;
       
   202 
       
   203 			M->ManX = NewX; M->ManY = NewY;
       
   204 			M->BoxMoved = 1;
       
   205 			return MOVE_BOX;
       
   206 		}
       
   207 		else
       
   208 		{
       
   209 			return MOVE_ILLEGAL;	// ILLEGAL MOVE
       
   210 		}
       
   211 	}
       
   212 	else
       
   213 	{
       
   214 		M->ManX = NewX; M->ManY = NewY;
       
   215 		M->BoxMoved = 0;
       
   216 		return MOVE_OK;
       
   217 	}
       
   218 	
       
   219 	// Not Reachable
       
   220 	return MOVE_ILLEGAL;
       
   221 }
       
   222 
       
   223 int InverseMove(char Dir1, char Dir2)
       
   224 {
       
   225 	if ((Dir1 + Dir2 == DIR_LEFT + DIR_RIGHT) ||
       
   226 		(Dir1 + Dir2 == DIR_UP + DIR_DOWN))
       
   227 		return 1;
       
   228 	return 0;
       
   229 }
       
   230 
       
   231 int main(int argn, char **argv)
       
   232 {
       
   233 	struct Map Morigin;
       
   234 	struct Map M[MAX_MOVES+1];
       
   235 	char Moves[MAX_MOVES];
       
   236 	int NumMoves;
       
   237 	int OldMaps;
       
   238 	int IllegalMove;
       
   239 	int Carry;
       
   240 	int MoveResult;
       
   241 
       
   242 	int i;
       
   243 
       
   244 	if (argn != 3)
       
   245 	{
       
   246 		printf("Usage: %s <mapfile> <initial NumMoves>\n", argv[0]);
       
   247 		exit(3);
       
   248 	}
       
   249 	ReadMap(&Morigin, argv[1]);
       
   250 	sscanf(argv[2], "%i", &NumMoves);
       
   251 
       
   252 	ShowMap(&Morigin);
       
   253 
       
   254 	for (i = 0; i < NumMoves; i++)
       
   255 		Moves[i] = DIR_LEFT;
       
   256 
       
   257 	// Reget the original map
       
   258 	CopyMap(&M[0], &Morigin);
       
   259 	CopyMap(&M[NumMoves], &Morigin);	// For the first while cond.
       
   260 
       
   261 	IllegalMove = NumMoves - 1;
       
   262 	// Process the combination
       
   263 	for (i = 0; i < NumMoves; i++)
       
   264 	{
       
   265 		CopyMap(&M[i+1], &M[i]);
       
   266 		if (!MoveMan(&M[i+1], Moves[i]))
       
   267 		{
       
   268 			IllegalMove = i;
       
   269 			break;
       
   270 		}
       
   271 	}
       
   272 
       
   273 	// Process the combinations.
       
   274 	// Order: Left, Right, Up, Down
       
   275 	while (M[NumMoves].NumPlatforms != M[NumMoves].NumBoxesInPlatform)
       
   276 	{
       
   277 		// Increase the Counter
       
   278 		{
       
   279 			Carry = 1;
       
   280 			// Reset the direction of sure-invalid moves
       
   281 			for (i = IllegalMove + 1; i < NumMoves; i++)
       
   282 				Moves[i] = DIR_LEFT;
       
   283 			// Increase Counter for a new try of moves
       
   284 			for (i = IllegalMove; i >= 0 && Carry; i--)
       
   285 			{
       
   286 				Moves[i]++;
       
   287 				Carry = 0;
       
   288 				if (Moves[i] == DIR_DOWN + 1)
       
   289 				{ Moves[i] = DIR_LEFT; Carry = 1; }
       
   290 			}
       
   291 			OldMaps = i+1;	// Sure? I think it's i+1
       
   292 			// If we change the number of movements for solution
       
   293 			if (Carry)
       
   294 			{
       
   295 				if (NumMoves > MAX_MOVES)
       
   296 					break;	// MAX MOVES EXCEEDED!!!
       
   297 				NumMoves++;
       
   298 				for (i = 0; i < NumMoves; i++)
       
   299 					Moves[i] = DIR_LEFT;
       
   300 				OldMaps=0;
       
   301 				CopyMap(&M[NumMoves], &Morigin);
       
   302 					// For the first while cond.
       
   303 				printf("Provant %i moviments...\n", NumMoves);
       
   304 			}
       
   305 		}
       
   306 
       
   307 /*
       
   308 		// Print the combination
       
   309 
       
   310 		for (i=0; i < NumMoves; i++)
       
   311 		{
       
   312 			printf("%c", Moves[i]);
       
   313 		}
       
   314 		printf("\n");
       
   315 */
       
   316 
       
   317 		IllegalMove = NumMoves - 1;
       
   318 		// Process the combination
       
   319 		for (i = OldMaps; i < NumMoves - 1; i++)
       
   320 		{
       
   321 			CopyMap(&M[i+1], &M[i]);
       
   322 			if (MoveMan(&M[i+1], Moves[i]) == MOVE_ILLEGAL)
       
   323 			{
       
   324 				IllegalMove = i;
       
   325 				break;
       
   326 			} else
       
   327 			if (((Moves[i] + Moves[i-1] == DIR_LEFT + DIR_RIGHT) ||
       
   328 				(Moves[i] + Moves[i-1] == DIR_UP + DIR_DOWN)) &&
       
   329 				!M[i].BoxMoved)
       
   330 			{
       
   331 				IllegalMove = i;
       
   332 				break;
       
   333 			}
       
   334 				
       
   335 		}
       
   336 		// Here i = NumMoves - 1
       
   337 		CopyMap(&M[i+1], &M[i]);
       
   338 		if (MoveMan(&M[i+1], Moves[i]) == MOVE_ILLEGAL)
       
   339 			IllegalMove = i;
       
   340 					
       
   341 	}
       
   342 
       
   343 	// Print the combination
       
   344 	for (i=0; i < NumMoves; i++)
       
   345 	{
       
   346 		if (Moves[i] == DIR_LEFT)
       
   347 			printf("L");
       
   348 		else if (Moves[i] == DIR_RIGHT)
       
   349 			printf("R");
       
   350 		else if (Moves[i] == DIR_UP)
       
   351 			printf("U");
       
   352 		else if (Moves[i] == DIR_DOWN)
       
   353 			printf("D");
       
   354 	}
       
   355 	printf("\n");
       
   356 
       
   357 /*
       
   358 	// Print The Steps
       
   359 	for (i=0; i < NumMoves; i++)
       
   360 	{
       
   361 		ShowMap(&M[i]);
       
   362 	}
       
   363 */
       
   364 	return 0;
       
   365 
       
   366 }