add spell checking support
authorLaurent MAZET <laurent.mazet@thalesgroup.com>
Tue, 11 Jun 2024 17:20:13 +0000 (19:20 +0200)
committerLaurent MAZET <laurent.mazet@thalesgroup.com>
Tue, 11 Jun 2024 17:20:13 +0000 (19:20 +0200)
display.c
display.h
function.c
function.h
scrabble.c
type.h

index 218ce78d6abab01413876eca74a0f68d5c584278..d4fd871707969a6188447bc0e9f2372fcba0c476 100644 (file)
--- a/display.c
+++ b/display.c
@@ -138,16 +138,19 @@ int _helpwindow (char *msg, int xoffset, int yoffset, int length)
     return j;
 }
 
-int helpwindow (char *msg, char *msg2, int xoffset, int yoffset)
+void _displaytitle (char *title, int xoffset, int yoffset)
 {
-    char *title = "Help message";
-    int length = strmaxlen (msg, '\n');
-
     int i;
-    for (i = 0; (i < length) && (title[i] != '\0'); i++) {
-        mvaddch (yoffset , xoffset + i, title[i]);
+    for (i = 0; title[i] != '\0'; i++) {
+        mvaddch (yoffset, xoffset + i, title[i]);
         mvaddch (yoffset + 1, xoffset + i, ACS_HLINE);
     }
+}
+
+int helpwindow (char *msg, char *msg2, int xoffset, int yoffset)
+{
+    _displaytitle ("Help message", xoffset, yoffset);
+    int length = strmaxlen (msg, '\n');
     int j = 2;
     j += _helpwindow (msg, xoffset, yoffset + j, length);
     j++;
@@ -158,15 +161,9 @@ int helpwindow (char *msg, char *msg2, int xoffset, int yoffset)
 
 void valuewindow (bag_t *bag, int xoffset, int yoffset, int length, char current)
 {
-    char *title = "Tile values";
+    _displaytitle ("Tile values", xoffset, yoffset);
     int i;
     int n = length / 5;
-
-    for (i = 0; (i < length) && (title[i] != '\0'); i++) {
-        mvaddch (yoffset, xoffset + i, title[i]);
-        mvaddch (yoffset + 1, xoffset + i, ACS_HLINE);
-    }
-
     int N = (bag->nbletters + n - 1) / n;
     for (i = 0; i < bag->nbletters; i++) {
         int x = xoffset + (i % 2) + 5 * (i / N);
@@ -216,15 +213,31 @@ void drawwindow (draw_t *game, int score, int xoffset, int yoffset, int mode)
 
 void scorewindow (int score, int xoffset, int yoffset)
 {
-    char *title = "Score";
-    int i;
-    for (i = 0; title[i] != '\0'; i++) {
-        mvaddch (yoffset, xoffset + i, title[i]);
-        mvaddch (yoffset + 1, xoffset + i, ACS_HLINE);
-    }
+    _displaytitle ("Score", xoffset, yoffset);
     char str[12] = {0};
     sprintf (str, " %3d", score);
     mvaddstr (yoffset + 2, xoffset, str);
 }
 
+void spellwindow (word_t *words, int xoffset, int yoffset, int mode)
+{
+    _displaytitle ("Spelling", xoffset, yoffset);
+    int i, n = 0;
+    for (i = 0; i < words->maxnbwords; i++) {
+        if (words->status[i] != none) {
+            if (mode) {
+                set_color ((words->status[i] == correct) ? wgreen : wred);
+                mvaddstr (yoffset + 2 + n, xoffset, words->tab[i]);
+                set_color (white);
+            } else {
+                int j;
+                for (j = 0; words->tab[i][j] != '\0'; j++) {
+                    mvaddch (yoffset + 2 + n, xoffset + j, ' ');
+                }
+            }
+            n++;
+        }
+    }
+}
+
 /* vim: set ts=4 sw=4 et: */
index ad9d86cbe0c58ec9729fc3839d54d59518941be6..e8ef41dbbb239f194870e3d21942e377432e3b5e 100644 (file)
--- a/display.h
+++ b/display.h
@@ -17,6 +17,8 @@ void drawwindow (draw_t *game, int score, int xoffset, int yoffset, int mode);
 
 void scorewindow (int score, int xoffset, int yoffset);
 
+void spellwindow (word_t *words, int xoffset, int yoffset, int mode);
+
 #endif /* __DISPLAY_H__ */
 
 /* vim: set ts=4 sw=4 et: */
index 267f0133677c5ea68002bef522706c2f686998f3..97fd3fccc39239540e5a9de6c121b88ae4968b3e 100644 (file)
@@ -331,4 +331,117 @@ int isturnempty (play_t *turn)
     return ret;
 }
 
+word_t *initword (int maxnbwords, int maxlength)
+{
+    int i;
+    word_t *words = (word_t *) calloc (1, sizeof (word_t));
+    words->tab = (char **) calloc (maxnbwords, sizeof (char *));
+    for (i = 0; i < maxnbwords; i++) {
+        words->tab[i] = (char *) calloc (maxlength, 1);
+    }
+    words->status = (spelling_e *) calloc (maxnbwords, sizeof (spelling_e));
+    words->maxnbwords = maxnbwords;
+    return words;
+}
+
+void freeword (word_t *words)
+{
+    if (words) {
+        if (words->tab) {
+            int i;
+            for (i = 0; i < words->maxnbwords; i++) {
+               free (words->tab[i]);
+            }
+        }
+        free (words->tab);
+        free (words->status);
+    }
+    free (words);
+}
+
+spelling_e _checkdict (char *word, char *dict)
+{
+    spelling_e ret = incorrect;
+    FILE *fd = fopen (dict, "r");
+    if (fd) {
+        while (!feof (fd)) {
+            char str[128] = {0};
+            fscanf (fd, "%s", str);
+            if (strcmp (word, str) == 0) {
+                ret = correct;
+                break;
+            }
+        }
+        fclose (fd);
+    } else {
+        ret = correct;
+    }
+    return ret;
+}
+
+void checkspelling (word_t *words, play_t *play, play_t *turn, char *dict)
+{
+    int i, j;
+
+    /* clean */
+    for (i = 0; i < words->maxnbwords; i++) {
+        words->tab[i][0] = '\0';
+        words->status[i] = none;
+    }
+
+    int n = 0;
+
+    /* words in line */
+    for (j = 0; j < play->ysize; j++) {
+        int nbletters = 0;
+        int accountable = 0;
+        for (i = 0; i < play->xsize; i++) {
+            char letter = *_getletteraddr (play, i, j);
+            if (letter != ' ') {
+                words->tab[n][nbletters++] = letter;
+                if (*_getletteraddr (turn, i, j) != ' ') {
+                    accountable = 1;
+                }
+            }
+            if (((letter == ' ') || (i == play->xsize - 1)) && (accountable)) {
+                if (nbletters > 1) {
+                    words->tab[n][nbletters] = '\0';
+                    words->status[n] = _checkdict (words->tab[n], dict);
+                }
+                n++;
+            }
+            if (letter == ' ') {
+                nbletters = 0;
+                accountable = 0;
+            }
+        }
+    }
+
+    /* words in column */
+    for (i = 0; i < play->xsize; i++) {
+        int nbletters = 0;
+        int accountable = 0;
+        for (j = 0; j < play->ysize; j++) {
+            char letter = *_getletteraddr (play, i, j);
+            if (letter != ' ') {
+                words->tab[n][nbletters++] = letter;
+                if (*_getletteraddr (turn, i, j) != ' ') {
+                    accountable = 1;
+                }
+            }
+            if (((letter == ' ') || (i == play->xsize - 1)) && (accountable)) {
+                if (nbletters > 1) {
+                    words->tab[n][nbletters] = '\0';
+                    words->status[n] = _checkdict (words->tab[n], dict);
+                }
+                n++;
+            }
+            if (letter == ' ') {
+                nbletters = 0;
+                accountable = 0;
+            }
+        }
+    }
+}
+
 /* vim: set ts=4 sw=4 et: */
index 67ca4fb38d7151a6fe8559e8e1eaa3358ecf3947..e30a0352e422292de2b6fdce1c87eb4c014ba194 100644 (file)
@@ -41,6 +41,12 @@ int evalscore (play_t *play, play_t *turn, board_t *board, bag_t *bag);
 
 int isturnempty (play_t *turn);
 
+word_t *initword (int maxnbwords, int maxlength);
+
+void freeword (word_t *words);
+
+void checkspelling (word_t *words, play_t *play, play_t *turn, char *dict);
+
 #endif /* __FUNCTION_H__ */
 
 /* vim: set ts=4 sw=4 et: */
index 512e9f16c8682c44a1a4779744e865e492a004ce..a14fd3ae9d65c9f106c7bf8d6d10c78d7d4dc28f 100644 (file)
@@ -26,6 +26,7 @@ char *version = "0.1";
 char *boardname = "15x15-7";
 char *language = "fr";
 int nbplayers = 2;
+char *dict = NULL;
 
 int xoffset = 4;
 int yoffset = 3;
@@ -48,8 +49,9 @@ char *help =
 int usage (int ret)
 {
     FILE *fd = ret ? stderr : stdout;
-    fprintf (fd, "usage: %s [-b board] [-h] [-l lang] [-n nb] [-v level]\n", progname);
+    fprintf (fd, "usage: %s [-b board] [-d dict] [-h] [-l lang] [-n nb] [-v level]\n", progname);
     fprintf (fd, " -b: board (%s)\n", boardname);
+    fprintf (fd, " -d: dictionary (%s)\n", (dict) ? dict : "none");
     fprintf (fd, " -h: help message\n");
     fprintf (fd, " -l: language (%s)\n", language);
     fprintf (fd, " -n: number of players (%d)\n", nbplayers);
@@ -91,6 +93,15 @@ int main (int argc, char *argv[])
                 return usage (1);
             }
             break;
+        case 'd':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg) {
+                dict = arg;
+            } else {
+                VERBOSE (ERROR, fprintf (stderr, "%s: no dictionary specified\n", progname));
+                return usage (1);
+            }
+            break;
         case 'l':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
             if (arg) {
@@ -136,6 +147,15 @@ int main (int argc, char *argv[])
         VERBOSE (ERROR, fprintf (stderr, "incorrect number of player [1, 4] (%d)\n", nbplayers));
         return 1;
     }
+    if (dict) {
+        FILE *fd = fopen (dict, "r");
+        if (fd) {
+            fclose (fd);
+        } else {
+            VERBOSE (ERROR, fprintf (stderr, "dictionary not found\n"));
+            return 1;
+        }
+    }
 
     srand (time (NULL));
 
@@ -154,6 +174,8 @@ int main (int argc, char *argv[])
         turn[n] = initplay (board->xsize, board->ysize);
     }
 
+    word_t *words = initword (board->length * 2, max (board->xsize, board->ysize) + 1);
+
     initscr ();
     noecho ();
     cbreak ();
@@ -176,9 +198,12 @@ int main (int argc, char *argv[])
 
     int helplen = helpwindow (help, getextrahelp (language), xhelpwin, yhelpwin);
 
-    int xscorewin = xhelpwin + helplen+ xoffset;
+    int xscorewin = xhelpwin + helplen + xoffset;
     int yscorewin = yhelpwin;
 
+    int xspellwin = xscorewin;
+    int yspellwin = yscorewin + 3 + 1;
+
     int mode = 0;
     showboard (play, board, xoffset, yoffset, mode);
 
@@ -203,7 +228,11 @@ int main (int argc, char *argv[])
         valuewindow (bag, xvaluewin, yvaluewin, 10, highlight);
         scorewindow (nbpoints, xscorewin, yscorewin);
 
-        switch (getch ()) {
+        checkspelling (words, play, turn[n], dict);
+        spellwindow (words, xspellwin, yspellwin, 1);
+        int ch = getch ();
+        spellwindow (words, xspellwin, yspellwin, 0);
+        switch (ch) {
         case '\t':
         case 'c':
             letter = getnextletter (game[n]);
@@ -305,12 +334,15 @@ int main (int argc, char *argv[])
     free (ydrawwin);
     free (score);
     freedraw (draw);
+    freeword (words);
 
     return 0;
 }
 
 /* test: scrabble.exe -b 2>&1 | grep 'no board' */
 /* test: scrabble.exe -b 6x6-7i 2>&1 | grep 'not found' */
+/* test: scrabble.exe -d 2>&1 | grep 'no dictionary' */
+/* test: scrabble.exe -d none.dict 2>&1 | grep 'not found' */
 /* test: scrabble.exe -h | grep usage */
 /* test: scrabble.exe -l 2>&1 | grep 'no language' */
 /* test: scrabble.exe -l aa 2>&1 | grep 'not found' */
diff --git a/type.h b/type.h
index af66756e2119890654156cc5fddafff2182b7dd8..d184813b4742143c4f08592500b6eed5b1a6d1b0 100644 (file)
--- a/type.h
+++ b/type.h
@@ -38,6 +38,18 @@ typedef struct {
     int index;
 } draw_t;
 
+typedef enum {
+    incorrect = -1,
+    none = 0,
+    correct = 1
+} spelling_e;
+
+typedef struct {
+    int maxnbwords;
+    char **tab;
+    spelling_e *status;
+} word_t;
+
 #endif /* __TYPE_H__ */
 
 /* vim: set ts=4 sw=4 et: */