getting there...

This commit is contained in:
foo 2017-01-07 12:42:18 +00:00
parent 2027d6b61e
commit 86463e38bf
6 changed files with 246 additions and 107 deletions

View File

@ -1,7 +1,6 @@
#include "dir.h" #include "dir.h"
#include "rnd.h" #include "rnd.h"
int directions[] = { int directions[] = {
DIRECTION_N, DIRECTION_N,
DIRECTION_NE, DIRECTION_NE,
@ -13,8 +12,8 @@ int directions[] = {
DIRECTION_NW DIRECTION_NW
}; };
int get_direction(int simple)
int get_direction(int simple) { {
if (simple) { if (simple) {
if (random_number(0, 1) == 0) { if (random_number(0, 1) == 0) {
return DIRECTION_E; return DIRECTION_E;
@ -29,7 +28,8 @@ int get_direction(int simple) {
#ifdef DEBUG_DIR_MAIN #ifdef DEBUG_DIR_MAIN
#include <stdio.h> #include <stdio.h>
int main() { int main()
{
int n = 32; int n = 32;
while (--n > 0) { while (--n > 0) {
printf("%d\n", get_direction(1)); printf("%d\n", get_direction(1));

197
src/grid.c Normal file → Executable file
View File

@ -1,69 +1,198 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "rnd.h" #include "rnd.h"
#include "dir.h" #include "dir.h"
#include "grid.h" #include "grid.h"
bounds *get_bounds(int height, int width, enum direction direction, int length) { enum exitcodes {
EXIT_WORDTOOLONG,
};
bounds *get_bounds(int height, int width, enum direction direction, int length)
{
if (length > height || length > width) { if (length > height || length > width) {
return NULL; return NULL;
} }
length--;
bounds *b = (bounds *) malloc(sizeof(bounds)); bounds *b = (bounds *) malloc(sizeof(bounds));
b->min_x = 0; b->min_x = 0;
b->max_x = width; b->max_x = width-1;
b->min_y = 0; b->min_y = 0;
b->max_y = height; b->max_y = height-1;
if( if (direction == DIRECTION_N ||
direction == DIRECTION_N || direction == DIRECTION_NE || direction == DIRECTION_NW) {
direction == DIRECTION_NE ||
direction == DIRECTION_NW
) {
b->min_y = length; b->min_y = length;
} }
if( if (direction == DIRECTION_W ||
direction == DIRECTION_W || direction == DIRECTION_NW || direction == DIRECTION_SW) {
direction == DIRECTION_NW ||
direction == DIRECTION_SW
) {
b->min_x = length; b->min_x = length;
} }
if( if (direction == DIRECTION_E ||
direction == DIRECTION_E || direction == DIRECTION_NE || direction == DIRECTION_SE) {
direction == DIRECTION_NE ||
direction == DIRECTION_SE
) {
b->max_x = width - length; b->max_x = width - length;
} }
if( if (direction == DIRECTION_S ||
direction == DIRECTION_S || direction == DIRECTION_SW || direction == DIRECTION_SE) {
direction == DIRECTION_SW ||
direction == DIRECTION_SE
) {
b->max_y = height - length; b->max_y = height - length;
} }
return b; return b;
} }
char** makegrid (char** words, int height, int width, int simple) { int move_x(int x, enum direction d) {
return NULL; 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 #ifdef DEBUG_GRID_MAIN
#include <stdio.h> #include <stdio.h>
int main() { int main()
int dir = get_direction(0); {
bounds* bounds = get_bounds(10, 10, dir, 8); char *words[4] = {
printf("DIR=%d => %d < height < %d & %d < width < %d\n", "test",
dir, "word",
bounds->min_y, bounds->max_y, "longer",
bounds->min_x, bounds->max_x "verylong"
); };
free(bounds); char **grid = make_grid(words, 10, 10, 0, 4);
print_grid(grid, 4);
} }
#endif #endif

View File

@ -3,7 +3,7 @@
#define WORDSEARCH_MAXTRIES 500 #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 { typedef struct bounds {
int min_y; int min_y;
@ -15,4 +15,11 @@ typedef struct bounds {
/* returns NULL if cannot fit word; caller needs to free() the response */ /* 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);
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 #endif

View File

@ -13,36 +13,37 @@ struct letter_frequency {
int p; /* pegged to 10000 rather than 1 */ int p; /* pegged to 10000 rather than 1 */
char c; char c;
} letter_frequencies[] = { } letter_frequencies[] = {
{7, 'Z'}, {
{10, 'J'}, 7, 'Z'}, {
{11, 'Q'}, 10, 'J'}, {
{17, 'X'}, 11, 'Q'}, {
{69, 'K'}, 17, 'X'}, {
{111, 'V'}, 69, 'K'}, {
{149, 'B'}, 111, 'V'}, {
{182, 'P'}, 149, 'B'}, {
{203, 'G'}, 182, 'P'}, {
{209, 'W'}, 203, 'G'}, {
{211, 'Y'}, 209, 'W'}, {
{230, 'F'}, 211, 'Y'}, {
{261, 'M'}, 230, 'F'}, {
{271, 'C'}, 261, 'M'}, {
{288, 'U'}, 271, 'C'}, {
{398, 'L'}, 288, 'U'}, {
{432, 'D'}, 398, 'L'}, {
{592, 'H'}, 432, 'D'}, {
{602, 'R'}, 592, 'H'}, {
{628, 'S'}, 602, 'R'}, {
{695, 'N'}, 628, 'S'}, {
{731, 'I'}, 695, 'N'}, {
{768, 'O'}, 731, 'I'}, {
{812, 'A'}, 768, 'O'}, {
{910, 'T'}, 812, 'A'}, {
{1202, 'E'}, 910, 'T'}, {
}; 1202, 'E'},};
/* from http://stackoverflow.com/questions/822323/how-to-generate-a-random-number-in-c */ /* 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; static int initialised = 0;
int result = 0; int result = 0;
int low_num = 0; int low_num = 0;
@ -62,7 +63,8 @@ int random_number(int min_num, int max_num) {
return result; return result;
} }
char get_random_letter() { char get_random_letter()
{
int rnd = random_number(0, RND_MAXINT); int rnd = random_number(0, RND_MAXINT);
for (int i = 0; i < ALPHABET_SIZE; i++) { for (int i = 0; i < ALPHABET_SIZE; i++) {
if (rnd < letter_frequencies[i].p) { if (rnd < letter_frequencies[i].p) {
@ -76,7 +78,8 @@ char get_random_letter() {
#ifdef DEBUG_RND_MAIN #ifdef DEBUG_RND_MAIN
#include <stdio.h> #include <stdio.h>
int main() { int main()
{
int n = 32; int n = 32;
while (--n > 0) { while (--n > 0) {
printf("%c", get_random_letter()); printf("%c", get_random_letter());