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.
/***************************************************************************
* 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;
}