Code Review

I've written this code for a hangman game. I think i started off well, but ended up overcomplicating it.
I'd be really grateful if someone could tell me how to make it more efficient and possibly simpler. Thanks!

One other thing! I was advised not to use goto and i've read up on all the dangers of using it and all - but I still think it's okay provided you use it within a single function and you don't overuse it. Surely goto can be used sparingly???


SOURCE CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#include <iostream>
#include <fstream>
#include <cstring> 
#include <cstdlib>

#define MAX_WRONG 8 
#define USED_LETTERS_CAPACITY 26 //letters in the alphabet

using namespace std;

int getRandom();   //returns random number which is used to choose word from list
int getCategory(); //user chooses category
void getWord(int, int, char []); 
char getch(char[]); //gets and checks user input
void initializeArrays(char [],char [],int,char[]);  
void drawBlanks(char [],int,int,char[]); 
bool check(char [],char [],int,char); //returns true if correct letter guessed 
bool isGameOver(char[],int); //returns true if all blanks filled
void showWinScreen(); //shows drawing of a free man
void showLoseScreen(char[]);//shows drawing of a dead man
bool playAgain(); 
bool isUsed(char[],char); //checks if letter is used

int main()
{
	replay:
	system("clear");

	int random = getRandom();
	int category = getCategory();
	char word[100];
	getWord(random,category,word);
	int wrong = 0;
	int length = strlen(word);
	char blanks[length];
	char usedLetters[USED_LETTERS_CAPACITY];

	initializeArrays(blanks, word,length,usedLetters);	

	do
	{
		system("clear");
		drawBlanks(blanks,length,wrong,usedLetters);
		char ch = getch(usedLetters);
		if(!check(blanks,word,length,ch)){wrong++;}
		if(isGameOver(blanks,length))
		{
			showWinScreen();
			if(playAgain()){goto replay;}
			else break;			
		}
	}while(wrong<=MAX_WRONG);
	if(wrong>MAX_WRONG)
	{
		showLoseScreen(word);
		if(playAgain()){goto replay;}
		else return 0;
	}	
}

void getWord(int random,int category,char word[])
{
	ifstream iFile;

	switch (category) 
	{
	case 1:{iFile.open("~/Desktop/C++/Hangman/Categories/Countries.txt");break;	}
	case 2:{iFile.open("~/Desktop/C++/Hangman/Categories/Books.txt"); break;	}
	case 3:{iFile.open("~/Desktop/C++/Hangman/Categories/LongEng.txt"); break;	}
	case 4:{iFile.open("~/Desktop/C++/Hangman/Categories/LongMed.txt"); break;	}
	default:{iFile.open("~/Desktop/C++/Hangman/Categories/Countries.txt"); break;}
	}

	string line;
	int line_no=0;
	while(getline(iFile,line))
	{
		line_no++;
		if(line_no==random)
		{
			strcpy(word,line.c_str());
		}
	}
		
}

void initializeArrays(char blanks[],char word[],int length,char usedLetters[])
{
        //assign all values in blanks[] to '_'
	int i;
	for(i=0;i<length;i++)
	{
		if(word[i]==' '){blanks[i]=' ';}
		else {blanks[i]='_';}
	}

        //without this, the condition in line 193 wont work.
	for(i=0;i<USED_LETTERS_CAPACITY;i++)
	{
		usedLetters[i]=' ';
	}
}

void drawBlanks(char blanks[], int length,int wrong,char usedLetters[])
{
	int i;

	for(i=0;i<length;i++)
	{
		cout<<blanks[i]<<" ";
	}
	cout<<endl;
	
	cout<<"Wrong Guesses: "<<wrong<<"/9"<<endl;
	cout<<endl;
	
	cout<<"Used Letters: ";
	for(i=0; i<USED_LETTERS_CAPACITY; i++)
	{
		cout<<usedLetters[i]<<" ";
	}
	cout<<endl;
}

bool check(char blanks[],char word[],int length,char ch)
{
	bool isCorrect = false;
	for(int i=0;i<length; i++)
	{
		if(word[i]==ch)
		{
			blanks[i]=ch;
			isCorrect = true;
		}
		
	}
	return isCorrect;
}

bool isGameOver(char blanks[],int length)
{
	int guessed=0;
	cout<<length<<endl;
	for(int i=0;i<length;i++)
	{
		if(blanks[i]!='_'){guessed++;}
	}
	if (guessed==length){return true;}
	else return false;
}

bool playAgain()
{
	cout<<"Would you like to play again (Y/N)?";
	char response;
	cin>>response;
	if(response == 'Y' || response == 'y'){return true;}
	return false;
}


char getch(char usedLetters[])
{
	char ch;
	prompt: cout<<"Enter Letter: "; cin>>ch;
	if(isupper(ch)){ch=tolower(ch);}
	if(!isUsed(usedLetters, ch)){return ch;	}
	else
	{ 
		cout<<"That letter's been used! ";	
		goto prompt;
	}
}

bool isUsed(char usedLetters[], char ch)
{
	int i;

	//check if char ch is in the usedLetters array.
	//if it is return true
	//if it isn't, add the letter to array of used letters
	//and then return false.

	for(i=0;i<USED_LETTERS_CAPACITY;i++)
	{
		if(usedLetters[i]==ch){return true;}
		else continue;
	}

	for(i=0;i<USED_LETTERS_CAPACITY;i++)
	{
		if(usedLetters[i]==' '){usedLetters[i]=ch; break;}

                /*what i wanted to write here was if the array element is empty, 
put the used character in the empty element. 
So I wrote if(usedLetters[i]=='') but the compiler had a problem with this.
So i changed it to what you see now.*/
	}

	return false; 
}

Last edited on
closed account (z05DSL3A)
Re:The use of goto

See: http://www.stevemcconnell.com/ccgoto.htm
Topic archived. No new replies allowed.