NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/52974: [hangman] fix several bugs with word selection



>Number:         52974
>Category:       bin
>Synopsis:       [hangman] fix several bugs with word selection
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb 02 11:35:00 +0000 2018
>Originator:     Eitan Adler
>Release:        HEAD
>Organization:
>Environment:
>Description:
There are several bugs in the current word selection for hangman:
- the first word will never be selected (as there are two fgets to find a complete word)
- if a minimum length that is longer than all words in the dictionary is selected hangman will... hang
- word selection is not uniformly random since longer words are less likely to be picked (and words after longer words are more likely to be picked)
>How-To-Repeat:

>Fix:
be aware: its 3:30am when I wrote this. There is a good chance I messed up:

Index: extern.c
===================================================================
RCS file: /cvsroot/src/games/hangman/extern.c,v
retrieving revision 1.8
diff -u -r1.8 extern.c
--- extern.c	7 Aug 2003 09:37:20 -0000	1.8
+++ extern.c	2 Feb 2018 11:33:41 -0000
@@ -42,7 +42,8 @@
 
 bool    Guessed[26];
 
-char    Word[BUFSIZ], Known[BUFSIZ];
+char    *Word;
+char	Known[BUFSIZ];
 const char *const Noose_pict[] = {
 	"     ______",
 	"     |    |",
@@ -75,4 +76,6 @@
 
 FILE   *Dict = NULL;
 
-off_t   Dict_size;
+char **Dict_array;
+
+int Dict_count;
Index: getword.c
===================================================================
RCS file: /cvsroot/src/games/hangman/getword.c,v
retrieving revision 1.10
diff -u -r1.10 getword.c
--- getword.c	19 Jun 2012 05:45:00 -0000	1.10
+++ getword.c	2 Feb 2018 11:33:41 -0000
@@ -47,27 +47,11 @@
 void
 getword(void)
 {
-	FILE *inf;
 	char *wp, *gp;
 	long pos;
 
-	inf = Dict;
-	for (;;) {
-		pos = (double) rand() / (RAND_MAX + 1.0) * (double) Dict_size;
-		fseek(inf, pos, SEEK_SET);
-		if (fgets(Word, BUFSIZ, inf) == NULL)
-			continue;
-		if (fgets(Word, BUFSIZ, inf) == NULL)
-			continue;
-		Word[strlen(Word) - 1] = '\0';
-		if (strlen(Word) < Minlen)
-			continue;
-		for (wp = Word; *wp; wp++)
-			if (!islower((unsigned char)*wp))
-				goto cont;
-		break;
-cont:		;
-	}
+	pos = (double) rand() / (RAND_MAX + 1.0) * (double) Dict_count;
+	Word = Dict_array[pos];
 	gp = Known;
 	wp = Word;
 	while (*wp) {
Index: hangman.h
===================================================================
RCS file: /cvsroot/src/games/hangman/hangman.h,v
retrieving revision 1.14
diff -u -r1.14 hangman.h
--- hangman.h	26 Aug 2011 06:18:17 -0000	1.14
+++ hangman.h	2 Feb 2018 11:33:41 -0000
@@ -65,7 +65,8 @@
 
 extern bool Guessed[];
 
-extern char Word[], Known[];
+extern char *Word;
+extern char Known[];
 extern const char *const Noose_pict[];
 
 extern int Errors, Wordnum;
@@ -79,7 +80,9 @@
 
 extern FILE *Dict;
 
-extern off_t Dict_size;
+extern char **Dict_array;
+
+extern int Dict_count;
 
 void    die(int) __dead;
 void    endgame(void);
Index: setup.c
===================================================================
RCS file: /cvsroot/src/games/hangman/setup.c,v
retrieving revision 1.11
diff -u -r1.11 setup.c
--- setup.c	19 Jun 2012 05:45:00 -0000	1.11
+++ setup.c	2 Feb 2018 11:33:41 -0000
@@ -50,6 +50,8 @@
 setup(void)
 {
 	const char *const *sp;
+	char line[BUFSIZ];
+	int nlines;
 	static struct stat sbuf;
 
 	noecho();
@@ -73,5 +75,16 @@
 		err(1, "fopen %s", Dict_name);
 	}
 	fstat(fileno(Dict), &sbuf);
-	Dict_size = sbuf.st_size;
+	Dict_array = malloc(sizeof (char*) * (sbuf.st_size/2));
+	Dict_count = 0;
+
+	while(fgets(line, BUFSIZ, Dict) != NULL) {
+		if (strlen(line) >= Minlen) {
+			Dict_array[Dict_count] = strdup(line);
+			Dict_count++;
+		}
+	}
+	if (Dict_count == 0) {
+		errx(1, "no words with minimum length");
+	}
 }



Home | Main Index | Thread Index | Old Index