Color Hangman

Simple Hangman Game for the command-line, maybe I’ll put a already developed Version with Socketsupport online somedayy.

The Game uses ANSI Terminalcolors, has a Highscorelist and 3 skill-levels. Needs wordlist.txt as word-source in the same directory as the binary. If not available, a optional file could given via parameter (other language, etc). The Word-Sourcefile must contain one word a line, don’t forget the return after the LAST word or it will be ignored.

Known Bugs

/***************************************************************************
 *   Copyright (C) 2008 by Manuel Krischer   *
 *   manuel@edv-krischer.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_WORDS     1024
#define MAX_WORD_LENGTH     32
#define HIGHSCORE_MEMBER 10

/*Player variables - content changes with the skill-level*/
unsigned int lives = 0; /*number of trys*/
unsigned int level = 0; /**/

/*name of the scorefile*/
char *scorefile = "scores.txt";

/*made struct for highscore*/
struct highscore {
            char name[8];
    unsigned int points;
};

/*initialise struct with zeros*/
struct highscore ranking[10] = {
                "noname",0,
                "noname",0,
                "noname",0,
                "noname",0,
                "noname",0,
                "noname",0,
                "noname",0,
                "noname",0,
                "noname",0,
                "noname",0
                                };

unsigned int double_damage = 0; /*if set to 1, submitting a letter twice costs a live*/
long score = 0;

/*
main shit
*/
int main(int argc, char *argv[]) {

    /*check if user wants new wordfile, otherwise take default wordlist.txt*/
    char wordfile[512];            /*name of the file with the words*/
    int wordcount;                /*number of words found in file*/

    if (argc > 1 && (strlen(argv[1]) < 512)) {
        strcpy(wordfile,argv[1]);
    }
    else {
        strcpy(wordfile, "wordlist.txt");
    }

    char wordarray[MAX_WORDS][MAX_WORD_LENGTH];

    /*Programm starts with Output here*/
    printf("\n\033[1;31m* * *  H A N G M A N   4   F R E A K S  * * *\033[0m\n\n");

    /*call the read function to get words in the word array. only needed once a run!*/
    wordcount = read_words(wordfile, wordarray, MAX_WORDS, MAX_WORD_LENGTH);
    if (wordcount < 0) {
                fprintf(stderr, "Error: File not Exist!\n");
        return 1;
    }
    /*now it's time to read the highscore from file*/
    read_highscore();

/*STARTING MENU LOOP HERE*/
    char choose[2];
    do {

        printf("\n  \033[1;47m Please make your selection:               \033[0m\n");
        printf("  \033[1;42m (1) \033[0m Easy Game (simple Rules, small score)\n");
        printf("  \033[1;43m (2) \033[0m Medium Game (normal Rules and score) \n");
        printf("  \033[1;41m (3) \033[0m Hard Game (strict Rules, big score)  \n");
        printf("  \033[1;44m (4) \033[0m View Highscore                       \n");
        printf("  \033[1;45m (5) \033[0m Exit Hangman                         \n\n");
        printf("\n  Input > ");
        gets(choose);
            if (atoi(choose) == 1) {
                    printf("\n\n  \033[1;42m You are a wimp! Easy Game is for kids and loser!\033[0m\n");
                    printf("  Level: Don't hurt me, daddy!\n");
                    level = 1;
                    /* start the gamefunction */
                    score = play(wordarray, wordcount);
                    /*check if score passes old value, if true prompt for name*/
                    if (check_highscore(score) == 1) {
                        new_highscore(score);
                        show_highscore();
                    }
                    else {
                        printf("\nNo new Highscore reached with %d Points!\n", score);
                    }
            }
            if (atoi(choose) == 2) {
                    printf("\n\n  \033[1;43m Come on! You don't trust yourself for real!\033[0m\n");
                    printf("  Level: Damn, I'm good!\n");
                    level = 2;
                    score = play(wordarray, wordcount);
                    /*check if score passes old value, if true prompt for name*/
                    if (check_highscore(score) == 1) {
                        new_highscore(score);
                        show_highscore();
                    }
                    else {
                        printf("\nNo new Highscore reached with %d Points!\n", score);
                    }
            }
            if (atoi(choose) == 3) {
                    printf("\n\n  \033[1;41m Mess with best or die like the rest!\033[0m\n");
                    printf("  Level: Bring 'em on!\n");
                    level = 3;
                    score = play(wordarray, wordcount);
                    /*check if score passes old value, if true prompt for name*/
                    if (check_highscore(score) == 1) {
                        new_highscore(score);
                        show_highscore();
                    }
                    else {
                        printf("\n  No new Highscore reached with\033[1;35m %d Points!\033[0m\n", score);
                    }
            }
            if (atoi(choose) == 4) {
                    show_highscore(0);
            }
    } while (atoi(choose) != 5);
    /*game ends here*/
    printf("\n  \033[5;45m You don't wanna leave yet, won't you? \033[0m\n\n");
  return EXIT_SUCCESS;
}

/* read_words()
need wordfile, an char array for the words, a number of words to read in and max_length of single words <= arraysize
gives back number of words read in, -1 for errors and 0 for empty file.
*/
int read_words(char *wordfile, char array[][MAX_WORD_LENGTH], int max_words) {
    int rows=0, chars=0;
    FILE * filed = fopen(wordfile, "r");
    if (filed == 0 ) {
                return -1;
        }
    char temp[MAX_WORD_LENGTH+1];
    /*get first line, set null-byte instead of linechange*/
    fgets(temp, MAX_WORD_LENGTH, filed);
    while (! feof(filed) && rows < max_words-1) {
        chars = strlen(temp);
        temp[chars-1] = '\0';
        strcpy(array[rows++],temp);
        fgets(temp, MAX_WORD_LENGTH, filed);
    }
return rows;
}

/* print_words(array_with_words)
simply prints out the whole word list
*/
print_words(char array[][MAX_WORD_LENGTH], int max) {
    int i;
    for (i=0; i<max; i++) {
        printf("%3d: %s\n",i+1, array[i]);
    }
}

/* give_rnd_word()
gives random number from given array as char array
*/
int give_rnd_word(int max) {
    char word[MAX_WORD_LENGTH];
    int i;
    /*initialize randomnumber generator*/
    srand(time(NULL));
    /*Random number between zero and max_words*/
        while ( i > max-1 || i < 0) {
            i = rand()%max;
        }
    /*printf("Zahl %d\n",i);*/
return i;
}


/* show_highscore()
show the actual highscore
*/
int show_highscore(long score) {
  int i;
    printf("\n  \033[1;42m * * *   HIGHSCORE   * * *  \033[0m\n");
    for (i=0; i<HIGHSCORE_MEMBER; i++) {
      /*mark the new score*/
        if (ranking[i].points == score && score != 0) {
            printf("  \033[0;43m\033[1;33m%3d. %11s\033[1;33m %10d \033[0m\033[0m\n", i+1, ranking[i].name, ranking[i].points);
        }
        else {
            printf("  %3d. %11s %10d\n",i+1,ranking[i].name, ranking[i].points);
        }
    }
    printf("\n\n");
return 0;
}

/* read_highscore()
reads the highscore file and put the content into the struct
*/
read_highscore(){
     int geschafft = 0;
     int i = 0, j = 0, k = 0;
     char string[32];
     char temp[24];

     FILE * datei = fopen(scorefile, "r");
     if (datei == 0)  {
         return -1;
      }
      /*array aus Datei lesen*/
     for (i=0; i<HIGHSCORE_MEMBER; i++) {
         fgets(string, 32 ,datei);
         strcpy(ranking[i].name,strtok(string," "));
         ranking[i].points = atoi(strtok(NULL,";"));
     }
     fclose(datei);
return 0;
}

/* new_highscore(score)
enter the new highscore in the struct, sort the struct and writes it back to disk
*/
int new_highscore(long score) {
    char player[512];

    printf("\n  \033[0;43m You really made it into the Highscore!\033[0m");
    printf("\n  \033[0;32mPlease enter your Name [10 Chars]: \033[0m");
    gets(player);

    /*copy player values to the last place*/
    ranking[HIGHSCORE_MEMBER-1].points = score;
    strcpy(ranking[HIGHSCORE_MEMBER-1].name, player);

    /*sort struct by points*/
    int i,j;
    struct highscore *temp;
    temp = (struct highscore *)malloc(sizeof(struct highscore *));
        if(NULL == temp) {
           printf("memory failure...\n");
           return 1;
       }
    for(i=0; i<HIGHSCORE_MEMBER; i++) {
           for(j=i+1; j<HIGHSCORE_MEMBER; j++) {
              if(ranking[i].points < ranking[j].points) {
                  *temp      = ranking[j];
                  ranking[j] = ranking[i];
                  ranking[i] = *temp;
              }
           }
       }
    /*write everything in the scorefile*/
    FILE * filed = fopen(scorefile, "w");
    if (filed == 0)  {
        printf("opening scorefile failure\n");
        return -1;
    }
    for (i=0; i<HIGHSCORE_MEMBER; i++) {
        fprintf(filed,"%10s %10d;\n", ranking[i].name, ranking[i].points);
    }
    fclose(filed);
return 0;
}

/* check_highscore(score)
Checks if the new Score is higher than actual scores, return 1 if it's higher, else zero
*/
check_highscore(long score) {
    int high = 0,i;
    /*compare the scores*/
    for (i=0; i<HIGHSCORE_MEMBER; i++) {
        if (score > ranking[i].points) {
            high = 1;
        }
    }
return high;
}

/* play()
runs the real game, returns highscore value
*/
int play(char array[][MAX_WORD_LENGTH], int max) {
    int i,j,k; /*some counting ints*/

    char word_to_play[MAX_WORD_LENGTH];    /*storage of the random word selected*/
    char visual[MAX_WORD_LENGTH];        /*visualisation array*/
    /*copy random word to play-array*/
     strcpy(word_to_play, array[(give_rnd_word(max))]);
    int wordlength = strlen(word_to_play);
    //printf("Random selected word: %s\n", word_to_play); /*throw away for release*/
    /*initiaizing for skillllevel*/
    if (level == 1) { /*EEEEEEEEAAAASSSSY*/
        lives = wordlength;
        if (lives < 5) {
            lives += 2;
        }
        double_damage = 0;
    }
    if (level == 2) { /*medium*/
        lives = wordlength-1;
        if (lives < 4) {
            lives += 1;
        }
        if (lives > 10) {
            lives = 10;
        }
        double_damage = 0;
    }
    if (level == 3) { /*real hardcore*/
        lives = (wordlength>>1)-2;
        /*printf("%d %d",lives, wordlength);*/
        if (lives < 3) {
            lives = 3;
        }
        if (lives > 8) {
            lives = 8;
        }
        double_damage = 1;
    }

    /*initialize the visualarray*/
    for (i=0; i<wordlength; i++) {
        visual[i] = '-';
    }
    visual[wordlength] = '\0';
    /*zero some vars*/
    int trys = 0;  /*number of trys to get the word*/
    int true = 0;  /*set to 1, if the character is found, set to 2 if charakter is already typed*/
    int rightchars = 0;
    char character[2];
    char already_taken[256];
    char *color = "\033[1;32m";
    fflush(stdin);

    while (strcmp(visual, word_to_play) != 0 ) {
        true = 0;
        j=0;
        trys++;

        /*Color the amount of lives*/
        if (lives < 7 ) color = "\033[1;35m";
        if (lives < 5 ) color = "\033[1;33m";
        if (lives < 3 ) color = "\033[1;31m";

        printf("\n  Your Task: [%s] - %s%d lives left\033[0m\n", visual, color, lives);
        printf("  Input > ");

        gets(character);
        character[1] = '\0';

        /*copy char to the already_taken array*/
        already_taken[k++] = character[0];

        /*search if char is in the search_word*/
        for (i=0; i<wordlength; i++) {
            if (character[0] == word_to_play[i]) {
                visual[i] = word_to_play[i];
                true = 1;
                j++;
            }
        }
        /*check if char is here for the second time*/
        for (i=0; i<k-1; i++) {
            if (character[0] == already_taken[i]) {
                j--;
                true = 2;
            }
        }

        /*Check for penalties*/
        if (true == 0)  {
            printf ("  \033[1;31mThis Character is not inside the word! \033[0m\n");
            lives--;
        }
        if (true == 1) {
            printf ("  \033[1;32mFound '%c' %d time(s)! \033[0m\n",character[0], j);
            rightchars++; /*Number of right characters*/

        }
        if (true == 2) {
            printf ("  \033[1;33mCharacter already tried! \033[0m\n");
            if (double_damage == 1) {
                lives--;
            }
        }
        /*check for lives*/
        if (lives < 1) {
            printf("\n\n  \033[5;41m You wouldn't made it with another 25 tries, Loser! \033[0m\n\n\n\n\n\n");
            score = level*rightchars*10;
            return score;
        }
    }
    /*calculate score*/
    if (strcmp(visual, word_to_play) == 0) {
        /*use: level, lives, rightchars, wordlength*/
        score = (( ((lives)/(wordlength/2))*100 - (2*(trys-wordlength))) * (150*level*rightchars));
    }
    printf("\n  \033[1;33mYour Score: %d\033[0m\n",score);
return score;
}