October 26, 2024
Chicago 12, Melborne City, USA
C#

Infinite loop when trying to place strings of length N in an NxN matrix — Word Soup Program in C


I’ve been attempting to make a word soup program in C for an assignment: the program accepts user-inputted words and places them onto an NxN board, where each cell is a character.

However, I’m running into a problem: whenever I try to place a word of length exactly N (the width or height of the matrix), the program fails to fit it properly in a single row or column as intended.

Here’s the full code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

int input_lower_upper_limit(int inf, int sup, const char *message);
void initial_fill(int N, char board[N][N]);
void input_words(int K, int N, char words[K][N]);
void to_uppercase(char *p, int N);
void insert_into_board(int K, int N, char board[N][N], char words[K][N]);

int main()
{
    srand(time(0)); // Will be used later to replace the '.' chars once the words are fitted in
    int i, j;

    // Initial memory allocation for the board and array of words:
    int N = input_lower_upper_limit(10, 35, "Enter the size of the matrix: ");
    char (*board)[N] = malloc(N * N * sizeof(char));
    if (board == NULL)
    {
        printf("ERROR: Could not allocate memory for the board.\n");
        exit(EXIT_FAILURE);
    }

    int K = input_lower_upper_limit(N/2, 2*N, "Enter the number of words you want to input: ");
    char (*words)[N] = malloc(K * N * sizeof(char));
    if (words == NULL)
    {
        printf("ERROR: Could not allocate memory for the words.\n");
        free(board);
        exit(EXIT_FAILURE);
    }

    // Main functionality of the program:
    initial_fill(N, board);
    input_words(K, N, words);
    insert_into_board(K, N, board, words);

    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }

    // Free all allocated memory:
    free(words);
    free(board);
    return 0;
}

int input_lower_upper_limit(const int inf, const int sup, const char *message) {
    int n;
    do
    {
        printf("%s", message);
        scanf("%d", &n);
        fflush(stdin);

        if (n < inf || n > sup) printf("ERROR: The number entered must be between %d and %d.\n", inf, sup);
    }
    while (n < inf || n > sup);

    return n;
}

void initial_fill(const int N, char board[N][N])
{
    int i, j;
    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
        {
            board[i][j] = '.';
//          board[i][j] = rand()%26 + 65;
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
}

void input_words(const int K, const int N, char words[K][N])
{
    int i;
    for (i = 0; i < K; i++)
    {
        printf("Enter word %d: ", i + 1);
        fgets(words[i], N+2, stdin);
        to_uppercase(words[i], N);
        words[i][strcspn(words[i], "\n")] = '\0';
        printf("words[%d] = %s\n", i, words[i]);
    }
}

void to_uppercase(char *p, const int N)
{
    int i;
    for (i = 0; i < N; i++)
    {
        if (p[i] >= 'a' && p[i] <= 'z')
        {
            p[i] -= 32;
        }
    }   
}

int check_space(int N, int x, int y, int dir, char board[N][N], char *word)
{
    int i, len = strlen(word);
    for (i = 0; i < len; i++)
    {
        int nx = x, ny = y;
        if (dir == 0) nx += i;       // LR
        else if (dir == 1) nx -= i;  // RL
        else if (dir == 2) ny += i;  // UD
        else if (dir == 3) ny -= i;  // DU

        if (nx < 0 || nx >= N || ny < 0 || ny >= N || board[nx][ny] != '.')
            return 0;  // No space or overlap
    }
    return 1;  // Space is free
}

void insert_into_board(const int K, const int N, char board[N][N], char words[K][N])
{
    int i, j, h, dir, len;
    int x_initial, y_initial;
    for (i = 0; i < K; i++) // Iterate over each word
    {
        len = strlen(words[i]);
        int placed = 0;
        while (!placed)  // Try until placement is successful
        {
            for (h = 0; h < K; h++)
            {
                if (strlen(words[h]) > N/2)
                {
                    if (rand()%2) dir = rand()%2;
                    else          dir = rand()%2 + 2;
                }
                else dir = rand()%4; // 0: LR - 1: RL - 2: UD - 3: DU
            }

            // Generate valid random starting positions
            x_initial = (dir == 0 || dir == 1) ? rand() % (N - len + 1) : rand() % N;
            y_initial = (dir == 2 || dir == 3) ? rand() % (N - len + 1) : rand() % N;

            printf("Printing before check_space()\n"); // Infinite loop happens here.
            if (check_space(N, x_initial, y_initial, dir, board, words[i]))
            {
                
                // Place the word if space is valid
                for (j = 0; j < len; j++)
                {
                    int x = x_initial, y = y_initial;
                    if (dir == 0) x += j;       // LR
                    else if (dir == 1) x -= j;  // RL
                    else if (dir == 2) y += j;  // UD
                    else if (dir == 3) y -= j;  // DU

                    board[x][y] = words[i][j];
                }
                placed = 1;  // Placement successful
            }
        }
    }
}

For example, with N = 10, K = 5, inputting a 9-letter word like "cavaliers" will work as intended and results in something like this:

C A V A L I E R S .
. C A V A L I E R S
. . . . . . . . . .
. . . . . . . . . .
C A V A L I E R S .
. . . . . . . . . .
C A V A L I E R S .
. . . . . . . . . .
. . . . . . . . . .
. C A V A L I E R S

However, an infinite loop will happen when the length of the words is exactly equal to N. For example, when a 10-letter word like "tablespoon" is inputted, the error will occur and the program will never stop printing the line "Printing before check_space()", which is where I think my code is failing.

(One) expected result:

T A B L E S P O O N
N O O P S E L B A T
. . . . . . . . . .
. . . . . . . . . .
T A B L E S P O O N
N O O P S E L B A T
. . . . . . . . . .
T A B L E S P O O N
. . . . . . . . . .
. . . . . . . . . .

Actual result: Program enters an infinite loop.

I’ve tried adjusting the starting position calculation numbers and verifying space availability with checks, but I’m still missing something. Any insight into how I can fix the program to properly fit the max size is appreciated.



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video