mirror of
				https://github.com/fooflington/wordsearch.git
				synced 2025-11-04 06:19:03 +00:00 
			
		
		
		
	getting there...
This commit is contained in:
		
							
								
								
									
										16
									
								
								src/dir.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/dir.c
									
									
									
									
									
								
							@@ -1,7 +1,6 @@
 | 
			
		||||
#include "dir.h"
 | 
			
		||||
#include "rnd.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int directions[] = {
 | 
			
		||||
	DIRECTION_N,
 | 
			
		||||
	DIRECTION_NE,
 | 
			
		||||
@@ -13,10 +12,10 @@ int directions[] = {
 | 
			
		||||
	DIRECTION_NW
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int get_direction(int simple) {
 | 
			
		||||
	if(simple) {
 | 
			
		||||
		if(random_number(0, 1) == 0) {
 | 
			
		||||
int get_direction(int simple)
 | 
			
		||||
{
 | 
			
		||||
	if (simple) {
 | 
			
		||||
		if (random_number(0, 1) == 0) {
 | 
			
		||||
			return DIRECTION_E;
 | 
			
		||||
		} else {
 | 
			
		||||
			return DIRECTION_S;
 | 
			
		||||
@@ -29,11 +28,12 @@ int get_direction(int simple) {
 | 
			
		||||
#ifdef DEBUG_DIR_MAIN
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int n = 32;
 | 
			
		||||
	while(--n > 0) {
 | 
			
		||||
	while (--n > 0) {
 | 
			
		||||
		printf("%d\n", get_direction(1));
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -16,4 +16,4 @@ enum direction {
 | 
			
		||||
 | 
			
		||||
int get_direction(int simple);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										203
									
								
								src/grid.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										203
									
								
								src/grid.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,69 +1,198 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 | 
			
		||||
#include "rnd.h"
 | 
			
		||||
#include "dir.h"
 | 
			
		||||
#include "grid.h"
 | 
			
		||||
 | 
			
		||||
bounds *get_bounds(int height, int width, enum direction direction, int length) {
 | 
			
		||||
	if(length > height || length > width) {
 | 
			
		||||
enum exitcodes {
 | 
			
		||||
	EXIT_WORDTOOLONG,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bounds *get_bounds(int height, int width, enum direction direction, int length)
 | 
			
		||||
{
 | 
			
		||||
	if (length > height || length > width) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bounds *b = (bounds *) malloc (sizeof(bounds));
 | 
			
		||||
	length--;
 | 
			
		||||
 | 
			
		||||
	bounds *b = (bounds *) malloc(sizeof(bounds));
 | 
			
		||||
 | 
			
		||||
	b->min_x = 0;
 | 
			
		||||
	b->max_x = width;
 | 
			
		||||
	b->max_x = width-1;
 | 
			
		||||
	b->min_y = 0;
 | 
			
		||||
	b->max_y = height;
 | 
			
		||||
	if(
 | 
			
		||||
		direction == DIRECTION_N  ||
 | 
			
		||||
		direction == DIRECTION_NE ||
 | 
			
		||||
		direction == DIRECTION_NW
 | 
			
		||||
	) {
 | 
			
		||||
	b->max_y = height-1;
 | 
			
		||||
	if (direction == DIRECTION_N ||
 | 
			
		||||
	    direction == DIRECTION_NE || direction == DIRECTION_NW) {
 | 
			
		||||
		b->min_y = length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if(
 | 
			
		||||
		direction == DIRECTION_W  ||
 | 
			
		||||
		direction == DIRECTION_NW ||
 | 
			
		||||
		direction == DIRECTION_SW
 | 
			
		||||
	) {
 | 
			
		||||
	if (direction == DIRECTION_W ||
 | 
			
		||||
	    direction == DIRECTION_NW || direction == DIRECTION_SW) {
 | 
			
		||||
		b->min_x = length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if(
 | 
			
		||||
		direction == DIRECTION_E  ||
 | 
			
		||||
		direction == DIRECTION_NE ||
 | 
			
		||||
		direction == DIRECTION_SE
 | 
			
		||||
	) {
 | 
			
		||||
	if (direction == DIRECTION_E ||
 | 
			
		||||
	    direction == DIRECTION_NE || direction == DIRECTION_SE) {
 | 
			
		||||
		b->max_x = width - length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if(
 | 
			
		||||
		direction == DIRECTION_S  ||
 | 
			
		||||
		direction == DIRECTION_SW ||
 | 
			
		||||
		direction == DIRECTION_SE
 | 
			
		||||
	) {
 | 
			
		||||
	if (direction == DIRECTION_S ||
 | 
			
		||||
	    direction == DIRECTION_SW || direction == DIRECTION_SE) {
 | 
			
		||||
		b->max_y = height - length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char** makegrid (char** words, int height, int width, int simple) {
 | 
			
		||||
 return NULL;
 | 
			
		||||
int move_x(int x, enum direction d) {
 | 
			
		||||
	if(
 | 
			
		||||
			d == DIRECTION_E  ||
 | 
			
		||||
			d == DIRECTION_NE ||
 | 
			
		||||
			d == DIRECTION_SE
 | 
			
		||||
	  ) {
 | 
			
		||||
		x++;
 | 
			
		||||
	} else if (
 | 
			
		||||
			d == DIRECTION_W  ||
 | 
			
		||||
			d == DIRECTION_NW ||
 | 
			
		||||
			d == DIRECTION_SW
 | 
			
		||||
		  ) {
 | 
			
		||||
		x--;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int move_y(int y, enum direction d) {
 | 
			
		||||
	if(
 | 
			
		||||
			d == DIRECTION_N  ||
 | 
			
		||||
			d == DIRECTION_NE ||
 | 
			
		||||
			d == DIRECTION_NW
 | 
			
		||||
	  ) {
 | 
			
		||||
		y--;
 | 
			
		||||
	} else if (
 | 
			
		||||
			d == DIRECTION_S  ||
 | 
			
		||||
			d == DIRECTION_SE ||
 | 
			
		||||
			d == DIRECTION_SW
 | 
			
		||||
		  ) {
 | 
			
		||||
		y++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char **make_grid(char **words, int height, int width, int simple, int count)
 | 
			
		||||
{
 | 
			
		||||
	char **grid = init_grid(NULL, height, width);
 | 
			
		||||
	for(int i=0; i<count; i++) {
 | 
			
		||||
		int tries = 0;
 | 
			
		||||
		int placed = 0;
 | 
			
		||||
		while(tries++ < WORDSEARCH_MAXTRIES && placed == 0) {
 | 
			
		||||
			if(place_word(words[i], grid, height, width, simple)) {
 | 
			
		||||
				placed = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return grid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int place_word(char *word, char **grid, int height, int width, int simple)
 | 
			
		||||
{
 | 
			
		||||
	int dir = get_direction(simple);
 | 
			
		||||
	bounds *b;
 | 
			
		||||
 | 
			
		||||
	if (b = get_bounds(height, width, dir, strlen(word))) {
 | 
			
		||||
		/* word will probably fit... */
 | 
			
		||||
		int x, y;
 | 
			
		||||
		x = random_number(b->min_x, b->max_x);
 | 
			
		||||
		y = random_number(b->min_y, b->max_y);
 | 
			
		||||
 | 
			
		||||
		char** tempgrid = init_grid(grid, height, width);
 | 
			
		||||
		/* Now we have two copies of the grid, try to place the word... */
 | 
			
		||||
		int i;
 | 
			
		||||
		for(i=0; i<strlen(word); i++) {
 | 
			
		||||
			if(!isalpha(word[i])) continue;
 | 
			
		||||
			if(tempgrid[y][x] != '_') {
 | 
			
		||||
				if(tempgrid[y][x] != word[i]) {
 | 
			
		||||
					/* Failed to place word */
 | 
			
		||||
					free_grid(tempgrid, height);
 | 
			
		||||
					return 0;
 | 
			
		||||
				} else {
 | 
			
		||||
					/* word crossed ok! */
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				tempgrid[y][x] = word[i];
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			x = move_x(x, dir);
 | 
			
		||||
			y = move_y(y, dir);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		free_grid(grid, height);
 | 
			
		||||
		free(b);
 | 
			
		||||
		grid = tempgrid;
 | 
			
		||||
		return 1;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* word can't fit */
 | 
			
		||||
		printf("[ERR] Word too long to place in this grid: %s\n", word);
 | 
			
		||||
		exit(EXIT_WORDTOOLONG);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clones or creates an empty grid - pass NULL in as old to get an empty grid */
 | 
			
		||||
char **init_grid(char** old, int height, int width)
 | 
			
		||||
{
 | 
			
		||||
	int row, cell;
 | 
			
		||||
	char **new = malloc(height * sizeof(char*));
 | 
			
		||||
 | 
			
		||||
	for (row=0; row < height; row++) {
 | 
			
		||||
		new[row] = malloc(width * sizeof(char));
 | 
			
		||||
		for (cell=0; cell < width; cell++) {
 | 
			
		||||
			if(old) {
 | 
			
		||||
				new[row][cell] = old[row][cell];
 | 
			
		||||
			} else {
 | 
			
		||||
				new[row][cell] = '_';
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}	
 | 
			
		||||
 | 
			
		||||
	return new;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void free_grid(char** grid, int height) {
 | 
			
		||||
	for (int i=0; i<height; i++) {
 | 
			
		||||
		free(grid[i]);
 | 
			
		||||
	}
 | 
			
		||||
	free(grid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_grid(char** grid, int height);
 | 
			
		||||
void print_grid(char** grid, int height) {
 | 
			
		||||
	for(int i=0; i<height; i++) {
 | 
			
		||||
		if(grid[i] == NULL) {
 | 
			
		||||
			printf("row error\n");
 | 
			
		||||
		} else {
 | 
			
		||||
			printf("%s\n", grid[i]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_GRID_MAIN
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
int main() {
 | 
			
		||||
	int dir = get_direction(0); 
 | 
			
		||||
	bounds* bounds = get_bounds(10, 10, dir, 8);
 | 
			
		||||
	printf("DIR=%d =>  %d < height < %d  &  %d < width < %d\n", 
 | 
			
		||||
		dir, 
 | 
			
		||||
		bounds->min_y, bounds->max_y,
 | 
			
		||||
		bounds->min_x, bounds->max_x
 | 
			
		||||
		);
 | 
			
		||||
	free(bounds);
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	char *words[4] = {
 | 
			
		||||
		"test",
 | 
			
		||||
		"word",
 | 
			
		||||
		"longer",
 | 
			
		||||
		"verylong"
 | 
			
		||||
	};
 | 
			
		||||
	char **grid = make_grid(words, 10, 10, 0, 4);
 | 
			
		||||
	print_grid(grid, 4);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								src/grid.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/grid.h
									
									
									
									
									
								
							@@ -3,16 +3,23 @@
 | 
			
		||||
 | 
			
		||||
#define WORDSEARCH_MAXTRIES 500
 | 
			
		||||
 | 
			
		||||
char** makegrid (char** words, int height, int width, int simple);
 | 
			
		||||
char **make_grid(char **words, int height, int width, int simple, int count);
 | 
			
		||||
 | 
			
		||||
typedef struct bounds {
 | 
			
		||||
    int min_y;
 | 
			
		||||
    int max_y;
 | 
			
		||||
    int min_x;
 | 
			
		||||
    int max_x;
 | 
			
		||||
	int min_y;
 | 
			
		||||
	int max_y;
 | 
			
		||||
	int min_x;
 | 
			
		||||
	int max_x;
 | 
			
		||||
} bounds;
 | 
			
		||||
 | 
			
		||||
/* returns NULL if cannot fit word; caller needs to free() the response */
 | 
			
		||||
bounds* get_bounds(int height, int width, enum direction direction, int length);
 | 
			
		||||
bounds *get_bounds(int height, int width, enum direction direction, int length);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
int place_word(char *word, char **grid, int height, int width, int simple);
 | 
			
		||||
 | 
			
		||||
char **init_grid(char** old, int height, int width);
 | 
			
		||||
void free_grid(char** grid, int height);
 | 
			
		||||
int move_x(int x, enum direction d);
 | 
			
		||||
int move_y(int y, enum direction d);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								src/rnd.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								src/rnd.c
									
									
									
									
									
								
							@@ -10,78 +10,81 @@
 | 
			
		||||
#define RND_MAXINT 10000
 | 
			
		||||
 | 
			
		||||
struct letter_frequency {
 | 
			
		||||
    int p; /* pegged to 10000 rather than 1 */
 | 
			
		||||
    char c;
 | 
			
		||||
	int p;			/* pegged to 10000 rather than 1 */
 | 
			
		||||
	char c;
 | 
			
		||||
} letter_frequencies[] = {
 | 
			
		||||
    {7,    'Z'},
 | 
			
		||||
    {10,   'J'},
 | 
			
		||||
    {11,   'Q'},
 | 
			
		||||
    {17,   'X'},
 | 
			
		||||
    {69,   'K'},
 | 
			
		||||
    {111,  'V'},
 | 
			
		||||
    {149,  'B'},
 | 
			
		||||
    {182,  'P'},
 | 
			
		||||
    {203,  'G'},
 | 
			
		||||
    {209,  'W'},
 | 
			
		||||
    {211,  'Y'},
 | 
			
		||||
    {230,  'F'},
 | 
			
		||||
    {261,  'M'},
 | 
			
		||||
    {271,  'C'},
 | 
			
		||||
    {288,  'U'},
 | 
			
		||||
    {398,  'L'},
 | 
			
		||||
    {432,  'D'},
 | 
			
		||||
    {592,  'H'},
 | 
			
		||||
    {602,  'R'},
 | 
			
		||||
    {628,  'S'},
 | 
			
		||||
    {695,  'N'},
 | 
			
		||||
    {731,  'I'},
 | 
			
		||||
    {768,  'O'},
 | 
			
		||||
    {812,  'A'},
 | 
			
		||||
    {910,  'T'},
 | 
			
		||||
    {1202, 'E'},
 | 
			
		||||
};
 | 
			
		||||
	{
 | 
			
		||||
	7, 'Z'}, {
 | 
			
		||||
	10, 'J'}, {
 | 
			
		||||
	11, 'Q'}, {
 | 
			
		||||
	17, 'X'}, {
 | 
			
		||||
	69, 'K'}, {
 | 
			
		||||
	111, 'V'}, {
 | 
			
		||||
	149, 'B'}, {
 | 
			
		||||
	182, 'P'}, {
 | 
			
		||||
	203, 'G'}, {
 | 
			
		||||
	209, 'W'}, {
 | 
			
		||||
	211, 'Y'}, {
 | 
			
		||||
	230, 'F'}, {
 | 
			
		||||
	261, 'M'}, {
 | 
			
		||||
	271, 'C'}, {
 | 
			
		||||
	288, 'U'}, {
 | 
			
		||||
	398, 'L'}, {
 | 
			
		||||
	432, 'D'}, {
 | 
			
		||||
	592, 'H'}, {
 | 
			
		||||
	602, 'R'}, {
 | 
			
		||||
	628, 'S'}, {
 | 
			
		||||
	695, 'N'}, {
 | 
			
		||||
	731, 'I'}, {
 | 
			
		||||
	768, 'O'}, {
 | 
			
		||||
	812, 'A'}, {
 | 
			
		||||
	910, 'T'}, {
 | 
			
		||||
1202, 'E'},};
 | 
			
		||||
 | 
			
		||||
/* from http://stackoverflow.com/questions/822323/how-to-generate-a-random-number-in-c */
 | 
			
		||||
int random_number(int min_num, int max_num) {
 | 
			
		||||
int random_number(int min_num, int max_num)
 | 
			
		||||
{
 | 
			
		||||
	static int initialised = 0;
 | 
			
		||||
    int result  = 0;
 | 
			
		||||
    int low_num = 0;
 | 
			
		||||
    int hi_num  = 0;
 | 
			
		||||
    if(min_num < max_num) {
 | 
			
		||||
        low_num = min_num;
 | 
			
		||||
        hi_num = max_num + 1; // this is done to include max_num in output.
 | 
			
		||||
    } else {
 | 
			
		||||
        low_num = max_num + 1;// this is done to include max_num in output.
 | 
			
		||||
        hi_num = min_num;
 | 
			
		||||
    }
 | 
			
		||||
    if(!initialised) {
 | 
			
		||||
    	srand(time(NULL));
 | 
			
		||||
    	initialised = 1;
 | 
			
		||||
    }
 | 
			
		||||
    result = ( rand() % (hi_num - low_num) ) + low_num;
 | 
			
		||||
    return result;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
	int low_num = 0;
 | 
			
		||||
	int hi_num = 0;
 | 
			
		||||
	if (min_num < max_num) {
 | 
			
		||||
		low_num = min_num;
 | 
			
		||||
		hi_num = max_num + 1;	// this is done to include max_num in output.
 | 
			
		||||
	} else {
 | 
			
		||||
		low_num = max_num + 1;	// this is done to include max_num in output.
 | 
			
		||||
		hi_num = min_num;
 | 
			
		||||
	}
 | 
			
		||||
	if (!initialised) {
 | 
			
		||||
		srand(time(NULL));
 | 
			
		||||
		initialised = 1;
 | 
			
		||||
	}
 | 
			
		||||
	result = (rand() % (hi_num - low_num)) + low_num;
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char get_random_letter() {
 | 
			
		||||
char get_random_letter()
 | 
			
		||||
{
 | 
			
		||||
	int rnd = random_number(0, RND_MAXINT);
 | 
			
		||||
	for(int i=0; i < ALPHABET_SIZE; i++) {
 | 
			
		||||
		if(rnd < letter_frequencies[i].p) {
 | 
			
		||||
	for (int i = 0; i < ALPHABET_SIZE; i++) {
 | 
			
		||||
		if (rnd < letter_frequencies[i].p) {
 | 
			
		||||
			return letter_frequencies[i].c;
 | 
			
		||||
		}
 | 
			
		||||
		rnd -= letter_frequencies[i].p;
 | 
			
		||||
	}
 | 
			
		||||
    return '\0';
 | 
			
		||||
	return '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_RND_MAIN
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int n = 32;
 | 
			
		||||
	while(--n > 0) {
 | 
			
		||||
	while (--n > 0) {
 | 
			
		||||
		printf("%c", get_random_letter());
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user