I am making a program with some friends but we run into a problem in the code that often prevents us from testing it. We are making a Puzzle 15 game, we made a code in the separate "functions.c" file where we calculate the configuration inversions to check that the initial board has solution. But for some reason sometimes it still doesn't have a solution (we check all this with a separate program from the internet to solve the game automatically according to a given board).
We tried with several alternatives to calculate the inversions and the location of the empty space, but it keeps giving boards without solution (Note: It's seems that is more probable for the program to give solvable boards than unsolvable ones). I was hoping that you could help me to find the error so that the code only generates solvable configurations, thus facilitating the development when testing the game. Here is the code as reduced as possible:
// functions.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#define ROWS 4
#define COLUMNS 4
// Print the matrix.
void printMatrix(int matrix[ROWS][COLUMNS]) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
if (matrix[i][j] == 16) {
printf(" "); // Number 16 it's the empty space.
} else {
printf("%2d ", matrix[i][j]);
}
}
printf("\n\n");
}
}
// Function to count the inversions on the board.
int countInversions(int matrix[ROWS][COLUMNS]) {
int inversions = 0;
int elements[ROWS * COLUMNS];
// Copy the matrix elements to a one-dimensional array.
int k = 0;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
elements[k++] = matrix[i][j];
}
}
// Count the inversions
for (int i = 0; i < ROWS * COLUMNS - 1; i++) {
for (int j = i + 1; j < ROWS * COLUMNS; j++) {
if (elements[j] && elements[i] && elements[i] > elements[j]) {
inversions++;
}
}
}
return inversions;
}
// Function to verify if the initial board configuration is resolvable.
bool itsSolvableConfiguration(int matrix[ROWS][COLUMNS]) {
int inversions = countInversions(matrix);
// Get the row containing the empty space.
int rowEmptySpace = -1;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
if (matrix[i][j] == 16) {
rowEmptySpace = i;
break;
}
}
if (rowEmptySpace != -1) {
break;
}
}
// Verify resolvability based on the position of the empty space and the number of inversions.
return (rowEmptySpace % 2 == 0 && inversions % 2 == 0) || (rowEmptySpace % 2 != 0 && inversions % 2 != 0);
}
// Function to verify if the button entered by the user is valid.
bool itsValidChar(char button) {
return (button == 'Y' || button == 'y' || button == 'S' || button == 's');
}
// main.c
#include "functions.c"
int main(void) {
int matrix[ROWS][COLUMNS];
int numbers[16];
int i, j, k, randomPivot;
char answer;
srand(getpid());
printf("Puzzle 15\n\n");
printf("CONTROLS:-Enter the number that is adjacent to the empty space to move it to the square.\n-Enter the key (Y) to restart or start the game.\n-Enter the key (S) to exit the game.");
// Game start control - Board update.
while (1) {
printf("Load new game (Y to start / S to exit): ");
scanf(" %c", &answer);
for (int i = 0; i < 8; i++) {
printf("\n");
}
if (!itsValidChar(answer)) {
printf("\nInvalid key. Please choose a valid option.\n\n");
continue;
}
if (answer == 'S' || answer == 's') {
printf("\nThanks for playing!\n");
break;
}
for (i = 0; i < 16; i++) {
numbers[i] = i + 1;
}
// Randomizing positions with the Fisher-Yates algorithm.
for (i = 16 - 1; i >= 0; i--) {
j = rand() % (i + 1);
randomPivot = numbers[i];
numbers[i] = numbers[j];
numbers[j] = randomPivot;
}
// The matrix is filled with random numbers.
k = 0;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLUMNS; j++) {
matrix[i][j] = numbers[k++];
}
}
// Verify if the initial board configuration is resolvable.
if (!itsSolvableConfiguration(matrix)) {
for (int i = 0; i < 15; i++) {
printf("\n");
}
printf("The initial board configuration is not resolvable. Restart the game \nto obtain a valid configuration.");
for (int i = 0; i < 12; i++) {
printf("\n");
}
continue;
}
printf("Game started\n\n");
for (int i = 0; i < 8; i++) {
printf("\n");
}
// Function call to print the initial matrix.
printMatrix(matrix);
break;
}
return 0;
}