Browse Source

first commit

Iman Anwarzai 1 year ago
commit
dcbd424a78
15 changed files with 277255 additions and 0 deletions
  1. BIN
      .DS_Store
  2. 19 0
      Makefile
  3. BIN
      boggle
  4. 78 0
      dictionary.c
  5. 22 0
      dictionary.h
  6. BIN
      dictionary.o
  7. 161 0
      game.c
  8. BIN
      game.o
  9. BIN
      user_data
  10. 162 0
      users.c
  11. BIN
      users.o
  12. 27 0
      utils.h
  13. 276643 0
      wordlist.txt
  14. 143 0
      words.c
  15. BIN
      words.o

BIN
.DS_Store


+ 19 - 0
Makefile

@@ -0,0 +1,19 @@
+CC = gcc
+CFLAGS = -Wall -std=gnu99
+
+default: boggle
+
+boggle: game.o words.o users.o dictionary.o
+	$(CC) $(CFLAGS) -o boggle game.o words.o users.o dictionary.o
+
+game.o: game.c utils.h
+	$(CC) $(CFLAGS) -c game.c
+words.o: words.c utils.h dictionary.h
+	$(CC) $(CFLAGS) -c words.c dictionary.c
+users.o: users.c utils.h
+	$(CC) $(CFLAGS) -c users.c
+dictionary.o: dictionary.c
+	$(CC) $(CFLAGS) -c dictionary.c
+
+clean:
+	rm game.o words.o users.o

BIN
boggle


+ 78 - 0
dictionary.c

@@ -0,0 +1,78 @@
+
+#include <string.h>
+#include "dictionary.h"
+
+
+//form hash value for string s
+//this produces a starting value in the dictionary array
+unsigned hash(const char *s) {
+	unsigned hashval;
+	for (hashval = 0; *s != '\0'; s++)
+		hashval = *s + 31 * hashval;
+	return hashval ;
+}
+
+//Performs search for a key in the hashtable.
+//if the string s is in the dictionary, it is in the list of blocks
+//beginning in array entry hash(s).
+//if lookup finds entry for s, it returns a pointer to the node
+//if not - it returns NULL
+DNode * lookup (DNode ** dictionary, int hash_size, const char *key) {
+	DNode * np;
+	unsigned int hashval = hash(key);
+	for (np = dictionary [hashval % hash_size]; np !=NULL; np = np->next)
+		if (strcmp (key, np->key) == 0)
+			return np; //found
+	return NULL; //not found
+}
+
+//insert uses lookup to detemine whether key is already in the dictionary
+//if not, a new entry is created
+DNode * insert (DNode ** dictionary, int hash_size,  const char * key) {
+	unsigned int hashval;
+	DNode *np;
+
+	if ((np = lookup (dictionary, hash_size, key)) == NULL ) { //
+		np = (DNode *) malloc (sizeof (*np));
+
+		if (np == NULL || (np->key = copystr (key)) == NULL)
+			return NULL;
+
+		hashval = hash (key) % hash_size;
+
+		//now links itself on top of array entry
+		np->next = dictionary [hashval];
+		dictionary [hashval] = np;
+	}
+	return np;
+}
+
+void free_dictionary (DNode ** dictionary, int hash_size) {
+	int i;
+	for (i=0; i<hash_size; i++) { //iterate over hash array
+		if (dictionary [i]!=NULL) { //if there is an entry at position i
+			DNode *head = dictionary[i]; //find the head of the linked list
+			DNode *current = head;
+			while (current != NULL) {
+				DNode * temp = current;
+				current = current->next;
+                if (temp->key !=NULL)
+                    free (temp->key);
+				free (temp);
+			}
+			dictionary[i] = NULL;  //BUG fix
+		}
+	}
+}
+
+char *copystr(const char *s) { /* make a duplicate of s */
+	char *p;
+	int len = strlen(s);
+
+	p = (char *) malloc(len+1); /* +1 for �\0� */
+	if (p != NULL)
+		strncpy(p, s, len);
+	p[len] = '\0';
+
+	return p;
+}

+ 22 - 0
dictionary.h

@@ -0,0 +1,22 @@
+#ifndef DICTIONARY_H
+#define DICTIONARY_H
+
+#include <stdlib.h>
+#define BIG_HASH_SIZE 20000
+#define SMALL_HASH_SIZE 100
+
+typedef struct d_node {
+	char* key;
+    struct d_node *next;
+}DNode;
+
+char * copystr (const char *);
+unsigned hash(const char *s);
+
+DNode * lookup (DNode ** dictionary, int hash_size, const char *key);
+
+DNode * insert (DNode ** dictionary, int hash_size, const char * key);
+
+void free_dictionary (DNode ** dictionary, int hash_size);
+
+#endif

BIN
dictionary.o


+ 161 - 0
game.c

@@ -0,0 +1,161 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include <signal.h>
+#include <unistd.h>
+#include "utils.h"
+
+int round_num;
+int score;
+int word_score;
+int old_score;
+int skip;
+
+char dice[16][6] = {
+  {'R', 'I', 'F', 'O', 'B', 'X'},
+  {'I', 'F', 'E', 'H', 'E', 'Y'},
+  {'D', 'E', 'N', 'O', 'W', 'S'},
+  {'U', 'T', 'O', 'K', 'N', 'D'},
+  {'H', 'M', 'S', 'R', 'A', 'O'},
+  {'L', 'U', 'P', 'E', 'T', 'S'},
+  {'A', 'C', 'I', 'T', 'O', 'A'},
+  {'Y', 'L', 'G', 'K', 'U', 'E'},
+  {'Q', 'B', 'M', 'J', 'O', 'A'},
+  {'E', 'H', 'I', 'S', 'P', 'N'},
+  {'V', 'E', 'T', 'I', 'G', 'N'},
+  {'B', 'A', 'L', 'I', 'Y', 'T'},
+  {'E', 'Z', 'A', 'V', 'N', 'D'},
+  {'R', 'A', 'L', 'E', 'S', 'C'},
+  {'U', 'W', 'I', 'L', 'R', 'G'},
+  {'P', 'A', 'C', 'E', 'M', 'D'}
+};
+char* actions[2] = {"quit", "logout"};
+char* messages[7] = {"Too Short", "Already Found", "Not on Board", "Not a Word", "Welcome to Boggle", "Hello Again", "New Round"};
+
+void swap(int* i, int* j) {
+  int temp = *i;
+  *i = *j;
+  *j = temp;
+}
+
+void generate_board() {
+  srand(time(0));
+  int order[16];
+  int i;
+  for (i = 0; i < 16; i++) {
+    order[i] = i;
+  }
+  for (i = 0; i < 16; i++) {
+    swap(order + i, order + (rand() % (16-i)) + i);
+  }
+  for (i = 0; i < 16; i++) {
+    board[i] = dice[order[i]][rand() % 6];
+  }
+}
+
+void refresh_screen(int score, int bonus, char* prev) {
+  system("clear");
+  printf("Round %d\n", round_num);
+  for (int i = 0; i < 4; i++) {
+    for (int j = 0; j < 4; j++) {
+      printf("%c ", board[4*i+j]);
+    }
+    printf("\n");
+  }
+  printf("Score: %d\n", score);
+  if (bonus > 0) {
+    printf("Last Word: %s (%d points)\n", prev, bonus);
+  }
+  else {
+    printf("%s\n", messages[0-bonus]);
+  }
+}
+
+void handler(int code) {
+  if (code == SIGALRM) {
+    round_num++;
+    reset_words();
+    generate_board();
+    if (word_score > -4) {
+      word_score = -6;
+    }
+    refresh_screen(score, word_score, NULL);
+    skip = 0;
+    alarm(TIME_INTERVAL);
+  }
+  else if (code == SIGINT) {
+    system("clear");
+    scoreboard();
+    printf("Game Over\n");
+    write_users();
+    free_dictionaries();
+    free_players();
+    exit(0);
+  }
+}
+
+int main() {
+  int action;
+  char input[17];
+  strcpy(input, "a");
+  initialzie_dictionary();
+  read_users();
+  struct sigaction newact;
+  newact.sa_handler = handler;
+  newact.sa_flags = 0;
+  sigemptyset(&newact.sa_mask);
+  sigaction(SIGALRM, &newact, NULL);
+  sigaction(SIGINT, &newact, NULL);
+  word_score = login();
+  skip = 0;
+  round_num = 0;
+
+  while (1) {
+    score = 0;
+    old_score = 0;
+    strcpy(input, "a");
+    raise(SIGALRM);
+    skip = 1;
+    while (1) {
+      scanf("%16s", input);
+      if (skip) {
+        word_score = verify_word(input);
+        if (word_score > 0) {
+          score += word_score;
+        }
+        refresh_screen(score, word_score, input);
+      }
+      else
+      {
+        skip = 1;
+      }
+      if (!(strcmp(input, "q") && strcmp(input, "u"))) {
+        if (input[0] == 'q') {
+          action = 0;
+        }
+        else {
+          action = 1;
+        }
+        update_scores(score, old_score);
+        scoreboard();
+        printf("Type y to confirm %s.  Type anything else to cancel\n", actions[action]);
+        scanf("%1s", input);
+        if (input[0] == 'y') {
+          break;
+        }
+        else {
+          old_score = score;
+        }
+      }
+    }
+    if (action == 0) {
+      raise(SIGINT);
+    }
+    else {
+      word_score = login();
+      round_num = 0;
+    }
+  }
+}

BIN
game.o


BIN
user_data


+ 162 - 0
users.c

@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "utils.h"
+
+User *head;
+User *current;
+User *array_end;
+
+int total_users;
+
+int read_users() {
+  FILE *users_file;
+  int error;
+
+  users_file = fopen("user_data", "rb");
+  if (users_file == NULL) {
+      fprintf(stderr, "Error: could not open file\n");
+      return 1;
+  }
+
+  error = fread(&total_users, sizeof(int), 1, users_file);
+  if (error) {
+    User* buffer = malloc(total_users*sizeof(User));
+    fread(buffer, sizeof(User), total_users, users_file);
+    head = buffer;
+    User *temp = head;
+    for (int i = 1; i < total_users; i++) {
+      temp->next = buffer+i;
+      temp = buffer+i;
+    }
+    array_end = buffer + total_users - 1;
+  }
+  else
+  {
+    total_users = 0;
+    array_end = NULL;
+  }
+  error = fclose(users_file);
+  if (error != 0) {
+      fprintf(stderr, "Error: fclose failed\n");
+      return 1;
+  }
+  return 0;
+}
+
+int write_users() {
+  User *temp = head;
+  User buffer[total_users];
+  FILE *users_file;
+  int error;
+  users_file = fopen("user_data", "wb");
+  if (users_file == NULL) {
+    fprintf(stderr, "Error: could not open file\n");
+    return 1;
+  }
+  fwrite(&total_users, sizeof(int), 1, users_file);
+  for (int i = 0; i < total_users; i++) {
+    buffer[i] = *temp;
+    temp = temp->next;
+  }
+  error = fwrite(buffer, sizeof(User), total_users, users_file);
+  if (error != total_users) {
+    fprintf(stderr, "Error: fwrite failed\n");
+    return 1;
+  }
+  error = fclose(users_file);
+  if (error != 0) {
+      fprintf(stderr, "Error: fclose failed\n");
+      return 1;
+  }
+  return 0;
+}
+
+int login() {
+  char name[9];
+  char c;
+  int invalid_input = 1;
+  system("clear");
+  while(invalid_input) {
+    printf("Username: ");
+    scanf("%8s", name);
+    invalid_input = 0;
+    for (int i = 0; i < strlen(name); i++) {
+      c = name[i];
+      if ((!isalnum(c)) && (c != '-') && (c != '_')) {
+        printf("Invlaid character: %c\n", c);
+        invalid_input = 1;
+      }
+    }
+  }
+
+  if (head == NULL) {
+    head = malloc(sizeof(User));
+    strcpy(head->name, name);
+    head->max_score = 0;
+    head->total_games = 0;
+    head->total_score = 0;
+    head->next = NULL;
+    current = head;
+    total_users++;
+    return -4;
+  }
+  else {
+    User *temp = head;
+    while(temp->next != NULL && strcmp(name, temp->name)) {
+      temp = temp->next;
+    }
+    if (strcmp(name, temp->name)) {
+      User* new_user = malloc(sizeof(User));
+      strcpy(new_user->name, name);
+      new_user->max_score = 0;
+      new_user->total_games = 0;
+      new_user->total_score = 0;
+      new_user->next = NULL;
+      temp->next = new_user;
+      current = new_user;
+      total_users++;
+      return -4;
+    }
+    else {
+      current = temp;
+      return -5;
+    }
+  }
+}
+
+void update_scores(int new_score, int old_score) {
+  if (new_score > current->max_score) {
+    current->max_score = new_score;
+  }
+  if (!old_score) {
+    current->total_games++;
+  }
+  current->total_score += new_score - old_score;
+}
+
+void scoreboard() {
+  system("clear");
+  User *temp = head;
+  printf("Name | Max Score | Total Games | Total Score\n");
+  while (temp) {
+    printf("%s, %d, %d, %d\n", temp->name, temp->max_score, temp->total_games, temp->total_score);
+    temp = temp->next;
+  }
+}
+
+void free_players() {
+  if (array_end) {
+    User *curr = array_end->next;
+  	User *temp;
+  	while(curr) {
+  		temp = curr->next;
+  		free(curr);
+  		curr = temp;
+    }
+  }
+  if (head) {
+    free(head);
+  }
+}

BIN
users.o


+ 27 - 0
utils.h

@@ -0,0 +1,27 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#define TIME_INTERVAL 60
+
+typedef struct user {
+  char name[9];
+  int max_score;
+  int total_games;
+  int total_score;
+  struct user * next;
+} User;
+
+int board[16];
+
+int login();
+int verify_word(char* word);
+void scoreboard();
+int initialzie_dictionary();
+void update_scores(int new_score, int old_score);
+void free_dictionaries();
+void free_players();
+void reset_words();
+int write_users();
+int read_users();
+
+#endif

File diff suppressed because it is too large
+ 276643 - 0
wordlist.txt


+ 143 - 0
words.c

@@ -0,0 +1,143 @@
+#include "dictionary.h"
+#include "utils.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#define MAX_LINE 100
+
+
+int scores[5] = {1, 1, 2, 3, 5};
+int used[16];
+static DNode* dictionary [BIG_HASH_SIZE];
+static DNode* submitted_words [BIG_HASH_SIZE];
+DNode* result;
+
+int initialzie_dictionary() {
+	FILE *input_FP;
+	char line [MAX_LINE];
+	char * file_name;
+
+	file_name = "wordlist.txt";
+
+	if(!(input_FP = fopen ( file_name , "r" )))    {
+        fprintf(stderr,"Could not open file \"%s\" for reading dictionary words\n", file_name);
+        return 1;
+    }
+
+	while( fgets (line, MAX_LINE, input_FP)!=NULL ) {
+		line[strcspn(line, "\r\n")] = '\0';  //trim new line characters
+		insert (dictionary, BIG_HASH_SIZE, line);
+	}
+	fclose (input_FP);
+  return 0;
+}
+
+int search(char* word, int place, int depth) {
+  if (depth == strlen(word)) {
+    return 1;
+  }
+  else if (board[place] == word[depth] && !used[place]) {
+    used[place] = 1;
+    if (place%4) {
+      if (search(word, place-1, depth+1)) {
+        return 1;
+      }
+      if (place > 3) {
+        if (search(word, place-5, depth+1)) {
+          return 1;
+        }
+      }
+      if (place < 12)  {
+        if (search(word, place+3, depth+1)) {
+          return 1;
+        }
+      }
+    }
+
+    if (place%4 != 3) {
+      if (search(word, place+1, depth+1)) {
+        return 1;
+      }
+      if (place > 3) {
+        if (search(word, place-3, depth+1)) {
+          return 1;
+        }
+      }
+      if (place < 12) {
+        if (search(word, place+5, depth+1)) {
+          return 1;
+        }
+      }
+    }
+
+    if (place > 3) {
+      if (search(word, place-4, depth+1)) {
+        return 1;
+      }
+    }
+    if (place < 12) {
+      if (search(word, place+4, depth+1)) {
+        return 1;
+      }
+    }
+    used[place] = 0;
+    return 0;
+  }
+  else {
+    return 0;
+  }
+}
+
+int in_dictionary(char* word) {
+  result = lookup (dictionary, BIG_HASH_SIZE, word);
+	return result != NULL;
+}
+
+int already_submitted(char* word) {
+  result = lookup(submitted_words, BIG_HASH_SIZE, word);
+  return result != NULL;
+}
+
+int verify_word(char* word) {
+
+  int len = strlen(word);
+  if (len < 3) {
+    return 0;
+  }
+  for (int i = 0; i < len; i++) {
+    word[i] = toupper(word[i]);
+  }
+  if (already_submitted(word)) {
+    return -1;
+  }
+  else if (in_dictionary(word)) {
+    for (int i = 0; i < 16; i++) {
+      if (board[i] == word[0]) {
+        for (int j = 0; j < 16; j++) {
+          used[j] = 0;
+        }
+        if (search(word, i, 0)) {
+          insert (submitted_words, BIG_HASH_SIZE, word);
+          if (len > 7) {
+            return 11;
+          }
+          else {
+            return scores[len-3];
+          }
+        }
+      }
+    }
+    return -2;
+  }
+  return -3;
+}
+
+void reset_words() {
+	free_dictionary(submitted_words, BIG_HASH_SIZE);
+}
+
+void free_dictionaries() {
+  free_dictionary(dictionary, BIG_HASH_SIZE);
+	reset_words();
+}

BIN
words.o