|
 |
|
 |
08-24-2005, 10:56 PM
|
#16 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
By the way, do the main game loop first. I want to see how you do that again.
This time no bool* myVar. Ditch the "*".
The first thing you need to ask yourself:
'Who/what is responsible for terminating the program on client's request'
In your original code you had the answer wrong. Find a different one. Remember, every function or every block of code should be valued by its behaviour. I cannot stress that enough. You always want to think about behaviour and responsibilities. That is the "soul" of object oriented programming in real practice. Start now, become good soon.
__________________
|
|
|
08-27-2005, 10:20 PM
|
#17 (permalink)
|
|
Scott
Join Date: Aug 2005
Posts: 29
|
Heres the game loop.
Code:
void first_part(std::string * scrambledWord, std::string * word)
{
std::cout << "Welcome to Word-Scramble." << std::endl;
std::cout << "Your Word is: " << *scrambledWord << std::endl;
middle_part(word);
}
//-----------------------------------------------------------------------------
void middle_part(std::string * word)
{
bool tryAgain = true;
std::string guess;
//Start Loop
while (tryAgain)
{
std::cout << "What is the word? (type \"give up\" to get the answer): ";
std::cin >> guess;
std::cout << std::endl;
tryAgain = process(guess, *word);
}
end_part();
}
//-----------------------------------------------------------------------------
bool process(std::string guess, std::string word)
{
bool tryAgain = true;
//Give up?
if (guess == "give")
{
//Yup, Give up
std::cout << "The Word is: " << word << std::endl;
tryAgain = false;
}
else
{
//Is it right?
if (guess == word)
{
//Yup, It's right
std::cout << "Correct! You Win!" << std::endl;
tryAgain = false;
}
else
{
//Nope not right
std::cout << "No, that\'s not the word. Try Again" << std::endl;
}
}
return tryAgain;
}
//-----------------------------------------------------------------------------
void end_part()
{
bool playAgain;
std::cout << "Thanks, for playing." << std::endl;
//Let the functions finish
}
first_part() is called by main() after the word has been scrambled.
I think this works better. How would I start the program over at the user request? (that would be found in the end_part() function).
Missed your second reply so i've been woring on the scramble function too.
Code:
std::string scramble_word(std::string sWord)
{
int wordLength=0;
std::string scrambledWord;
int letter;
int count=0;
int lettersLeft;
std::string sLetter;
wordLength = sWord.length();
lettersLeft = wordLength;
std::cout << "Scrambling Word";
while (count <= (wordLength-1))
{
//choose a letter from sWord
letter = (choose_rand(lettersLeft) - 1);
std::cout << ".";
//Asign it to scrambledWord[count]
sLetter = sWord[letter];
scrambledWord.append(sLetter);
//Remove chosen letter from sWord
int i = (letter);
while (i<(lettersLeft-1))
{
sWord[i] = sWord[i+1];
i++;
}
lettersLeft--;
count++;
}
return scrambledWord;
}
it works resonably well but would work better if i had a random number generator that could come up with a different number several times per second. any suggestions there?
I'll take a crack at your puzzle code.
thanks
Scott
|
|
|
08-28-2005, 04:44 AM
|
#18 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Don't do this "part" method. Use a simple global game loop. Also observe the usage of std::random_shuffle. Makes your life quite easy. After you've seen the code things are easy for you to do implement the rest:
Code:
#include <fstream>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
#include <algorithm>
unsigned choose_word(unsigned);
unsigned calculate_lines(std::ifstream&);
std::string fetch_word(std::ifstream&, unsigned);
int main()
{
using std::endl;
using std::cout;
using std::cin;
std::string sWord;
std::string sGuess = "quit";
unsigned nLines(0);
std::ifstream dictionary("dictionary.txt");
if (!dictionary)
{
std::cout << "ERROR: There was error opening the file dictionary.txt." << std::endl;
std::cout<< "Please read readme.txt for possible solutions." << std::endl;
std::cout<< "Terminating program...";
exit(1);
}
while(1)
{
cout << "1 = Play Game" << endl;
cout << "2 = Quit App" << endl;
char appRun;
cin >> appRun;
if(appRun == '2')
{
break;
}
if(appRun == '1')
{
//Let's first determine how many words there are.
nLines = calculate_lines(dictionary);
//We know how many words there are, so let's choose a random word line.
unsigned RandomLine;
RandomLine = choose_word(nLines);
//We know which line to pick. So let's retreive the word on that line.
sWord = fetch_word(dictionary, RandomLine);
std::random_shuffle(sWord.begin(), sWord.end());
}
else
{
cout << endl << "ERROR: you didn't enter \"1\" or \"2\" " << endl;
cout << "Please try again." << endl << endl;
}
}
return 0;
}
//---------------------------------------------------
//So how many lines (=words) has this file?
unsigned calculate_lines(std::ifstream& dict)
{
unsigned lns(0);
std::string sBuffer;
while( std::getline(dict, sBuffer) )
{
++lns;
}
//Did something went wrong during the read of this stream?
if(!dict.eof())
{
//Yep, something went wront. Ring the alarms!
std::cout<<"ERROR: something go wrong during file reading.";
dict.close();
std::cout<<"exiting app...";
}
//Do not forget to reset the state of the dictionary file object since it is
//in a error state due to EOF.
dict.clear();
//And let the file pointer point to the beginning as it was before all this.
dict.seekg(0, std::ios::beg);
return lns;
}
//---------------------------------------------------
unsigned choose_word(unsigned maxnum)
{
unsigned randnum;
std::srand(std::time(0));
randnum= std::rand() % maxnum + 1;
return randnum;
}
//----------------------------------------------------
std::string fetch_word(std::ifstream& dict, unsigned line)
{
std::string buffer;
while( std::getline(dict, buffer) && line != 1)
{
--line;
}
//Do not forget to reset the state of the dictionary file object since it is
//in a error state due to EOF.
dict.clear();
//And let the file pointer point to the beginning as it was before all this.
dict.seekg(0, std::ios::beg);
return buffer;
}
Soo... what do you think?
__________________
|
|
|
08-28-2005, 05:06 AM
|
#19 (permalink)
|
|
Registered User
Join Date: Aug 2005
Posts: 20
|
You could first parse the file into an array or vector of strings, then do all the looking up on that. Should reduce the complexity a bit, and maybe improve performance a little.
|
|
|
08-28-2005, 05:25 AM
|
#20 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Yes the first thing that popped in my mind as well. But if you look around on this forum you'll see peeps having difficulties with stream handling. Once their fight against basic C++ is over they can shift their attention.
If I stored the words in a container they would not have learned how to count lines and wouldn't have seen that one needs to parse all lines to count the total lines in file. It's the only portable way.
__________________
|
|
|
08-29-2005, 04:33 PM
|
#21 (permalink)
|
|
Scott
Join Date: Aug 2005
Posts: 29
|
Valmont,
I got the rest of the game loop in. Heres the whole program
Code:
#include <fstream>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
#include <algorith>
unsigned choose_word(unsigned);
unsigned calculate_lines(std::ifstream&);
std::string fetch_word(std::ifstream&, unsigned);
bool process(std::string, std::string);
int main()
{
using std::endl;
using std::cout;
using std::cin;
std::string sWord;
std::string sGuess = "quit";
unsigned nLines(0);
std::ifstream dictionary("dictionary.txt");
if (!dictionary)
{
std::cout << "ERROR: There was error opening the file dictionary.txt." << std::endl;
std::cout<< "Please read readme.txt for possible solutions." << std::endl;
std::cout<< "Terminating program...";
std::exit(1);
}
while(1)
{
cout << "1 = Play Game" << endl;
cout << "2 = Quit App" << endl;
char appRun;
cin >> appRun;
if(appRun == '2')
{
break;
}
if(appRun == '1')
{
//Let's first determine how many words there are.
nLines = calculate_lines(dictionary);
//We know how many words there are, so let's choose a random word line.
unsigned RandomLine;
RandomLine = choose_word(nLines);
//We know which line to pick. So let's retreive the word on that line.
sWord = fetch_word(dictionary, RandomLine);
//Make a copy and shuffle
std::string word = sWord;
std::random_shuffle(sWord.begin(), sWord.end());
//Start Game
std::cout << "Welcome to Word-Scramble." << std::endl;
std::cout << "Your Word is: " << sWord << std::endl;
bool tryAgain = true;
std::string guess;
//Start Loop
while (tryAgain)
{
std::cout << "What is the word? (type \"3\" to get the answer): ";
std::cin >> guess;
std::cout << std::endl;
tryAgain = process(guess, word);
}
std::cout << "Thanks, for playing." << std::endl;
}
else
{
cout << endl << "ERROR: you didn't enter \"1\" or \"2\" " << endl;
cout << "Please try again." << endl << endl;
}
}
return 0;
}
//---------------------------------------------------
//So how many lines (=words) has this file?
unsigned calculate_lines(std::ifstream& dict)
{
unsigned lns(0);
std::string sBuffer;
while( std::getline(dict, sBuffer) )
{
++lns;
}
//Did something went wrong during the read of this stream?
if(!dict.eof())
{
//Yep, something went wront. Ring the alarms!
std::cout<<"ERROR: something go wrong during file reading.";
dict.close();
std::cout<<"exiting app...";
}
//Do not forget to reset the state of the dictionary file object since it is
//in a error state due to EOF.
dict.clear();
//And let the file pointer point to the beginning as it was before all this.
dict.seekg(0, std::ios::beg);
return lns;
}
//---------------------------------------------------
unsigned choose_word(unsigned maxnum)
{
unsigned randnum;
std::srand(std::time(0));
randnum= std::rand() % maxnum + 1;
return randnum;
}
//----------------------------------------------------
std::string fetch_word(std::ifstream& dict, unsigned line)
{
std::string buffer;
while( std::getline(dict, buffer) && line != 1)
{
--line;
}
//Do not forget to reset the state of the dictionary file object since it is
//in a error state due to EOF.
dict.clear();
//And let the file pointer point to the beginning as it was before all this.
dict.seekg(0, std::ios::beg);
return buffer;
}
//-----------------------------------------------------------------------------
bool process(std::string guess, std::string word)
{
bool tryAgain = true;
//Give up?
if (guess == "3")
{
//Yup, Give up
std::cout << "The Word is: " << word << std::endl;
tryAgain = false;
}
else
{
//Is it right?
if (guess == word)
{
//Yup, It's right
std::cout << "Correct! You Win!" << std::endl;
tryAgain = false;
}
else
{
//Nope not right
std::cout << "No, that\'s not the word. Try Again" << std::endl;
}
}
return tryAgain;
}
#include <algorithm> didn't work so i looked in my include files and the file was named algorth so I changed it.
Also the random_shuffle() function doesn't compile for me. I get this error:
"_algo.c": E2268 Call to undefined function 'rand' in function _STL::int __random_number<int>(int) at line 432
Thanks
Scott
|
|
|
08-30-2005, 06:48 AM
|
#22 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Well done so far.
Here is a nice tip: check out redhead's reply in the thread below.
http://codenewbie.com/forum/showthre...8610#post18610
Download Dev-Cpp or Code::Blocks for ISO compliance and good IDE and visual debugger. You won't have STL problems anymore. Debugging works easy as well. I think you will like it. I use both myself at work!
So let's move on with your code.
Your function bool process().
The word "process" could be meaning anything. It's not very informative. Pretend I am a total stranger. And I look for the first time at your code. What could "process" possibly mean to me as a stranger. Could be anything...
Behaviour & Responsibilities
We talked about that earlier. Once you figured out how to do things basically, you may want to think about which part of the program should be doing whatever needs to be done. Your "process()" function does a lot:
- It checks user input for correct guess.
- It offers a supporting role for the gaming engine (it may let you guess again or it may let you give up).
- It even knows what plans the engine has for you.
That's one kick-ass function you got there. It has a lot of responsibilities. We don't want that  .
So I skinned that function down and renamed a few stuff here and there. Remember, to chose the right names for the things so strangers know what you mean. You communicate through code. Never forget that!
Your task
Grab the complete working code from below (at the very end of this post) and wrap this part in some sort of a function. This will be THE game engine. THE controller. THE boss.
Code:
//Start Game
std::cout << "Welcome to Word-Scramble." << std::endl;
std::cout << "Your Word to guess is: " << sShuffledWord << std::endl;
std::string sClientGuess;
//Begin user guessing sequence.
while (1)
{
std::cout << "What is the word? (type \"?\" to get the answer): ";
std::cin >> sClientGuess;
if(sClientGuess == "?")
{
//Client gives up guessing.
std::cout << "The correct word is: " << sWord << std::endl;
break;
}
std::cout << std::endl;
if( check_guess(sClientGuess, sWord) )
{
//User guessed the word so quit guessing sequence.
break;
}
}
When you succeeded you want to check out what else you could do to keep "main()" simple and readable for strangers like me. You want to hide the all the complex things so stranger can concentrate on your global idea first.
Here is the complete code: have fun! (and don't forget to download that stuff)
Code:
#include <fstream>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
#include <algorithm>
unsigned choose_word(unsigned);
unsigned calculate_lines(std::ifstream&);
std::string fetch_word(std::ifstream&, unsigned);
bool check_guess(const std::string, const std::string);
int main()
{
using std::endl;
using std::cout;
using std::cin;
std::string sWord;
std::string sGuess = "quit";
unsigned nLines(0);
std::ifstream dictionary("dictionary.txt");
if (!dictionary)
{
std::cout << "ERROR: There was error opening the file dictionary.txt." << std::endl;
std::cout<< "Please read readme.txt for possible solutions." << std::endl;
std::cout<< "Terminating program...";
std::exit(1);
}
while(1)
{
cout << "1 = Play Game" << endl;
cout << "2 = Quit App" << endl;
char appRun;
cin >> appRun;
if(appRun == '2')
{
break;
}
if(appRun == '1')
{
//Let's first determine how many words there are.
nLines = calculate_lines(dictionary);
//We know how many words there are, so let's choose a random word line.
unsigned RandomLine;
RandomLine = choose_word(nLines);
//We know which line to pick. So let's retreive the word on that line.
sWord = fetch_word(dictionary, RandomLine);
//Make a copy and shuffle
std::string sShuffledWord = sWord;
std::random_shuffle(sShuffledWord.begin(), sShuffledWord.end());
//Start Game
std::cout << "Welcome to Word-Scramble." << std::endl;
std::cout << "Your Word to guess is: " << sShuffledWord << std::endl;
std::string sClientGuess;
//Begin user guessing sequence.
while (1)
{
std::cout << "What is the word? (type \"?\" to get the answer): ";
std::cin >> sClientGuess;
if(sClientGuess == "?")
{
//Client gives up guessing.
std::cout << "The correct word is: " << sWord << std::endl;
break;
}
std::cout << std::endl;
if( check_guess(sClientGuess, sWord) )
{
//User guessed the word so quit guessing sequence.
break;
}
}
}
else //Incorrect main menu usage.
{
cout << endl << "ERROR: you didn't enter \"1\" or \"2\" " << endl;
cout << "Please try again." << endl << endl;
}
}
std::cout << "Thanks, for playing." << std::endl;
return 0;
}
//---------------------------------------------------
//So how many lines (=words) has this file?
unsigned calculate_lines(std::ifstream& dict)
{
unsigned lns(0);
std::string sBuffer;
while( std::getline(dict, sBuffer) )
{
++lns;
}
//Did something went wrong during the read of this stream?
if(!dict.eof())
{
//Yep, something went wront. Ring the alarms!
std::cout<<"ERROR: something go wrong during file reading.";
dict.close();
std::cout<<"exiting app...";
}
//Do not forget to reset the state of the dictionary file object since it is
//in a error state due to EOF.
dict.clear();
//And let the file pointer point to the beginning as it was before all this.
dict.seekg(0, std::ios::beg);
return lns;
}
//---------------------------------------------------
unsigned choose_word(unsigned maxnum)
{
unsigned randnum;
std::srand(std::time(0));
randnum= std::rand() % maxnum + 1;
return randnum;
}
//----------------------------------------------------
std::string fetch_word(std::ifstream& dict, unsigned line)
{
std::string buffer;
while( std::getline(dict, buffer) && line != 1)
{
--line;
}
//Do not forget to reset the state of the dictionary file object since it is
//in a error state due to EOF.
dict.clear();
//And let the file pointer point to the beginning as it was before all this.
dict.seekg(0, std::ios::beg);
return buffer;
}
//-----------------------------------------------------------------------------
bool check_guess(const std::string guess, const std::string word)
{
//Did the user guess right?
if (guess == word)
{
//User Guessed right
std::cout << "Correct! You guessed the word!" << std::endl;
return true;
}
else
{
//User guessed wrong.
std::cout << "No, that\'s not the word." << std::endl;
return false;
}
}
__________________
|
|
|
08-30-2005, 05:28 PM
|
#23 (permalink)
|
|
Scott
Join Date: Aug 2005
Posts: 29
|
Valmont,
Thank you very much for all your help. I really appreciate it. I'll keep all your advice in mind for my next program.
i downloaded devc++ and ran the program and i see it flash on the screen for a split second and then go away. Any suggestions?
Thanks again
Scott
|
|
|
08-30-2005, 07:26 PM
|
#24 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
#include <iostream>
{
std::cin.get();
}
You could try Code::Blocks as well. It's very nice! And no flashing console's either...
__________________
|
|
|
08-31-2005, 11:01 AM
|
#25 (permalink)
|
|
mike
Join Date: Jan 2005
Location: Ottawa, ON
Posts: 79
|
I didnt follow this thread, I just wanted to say theres probably no point in passing bool's by reference OR by pointer. Really. Do a sizeof(bool) and a sizeof(bool*) and I guarantee they're the same size. If you want the values to stick after the function changes them, use pass by reference since you're using C++.
void change(bool& foo);
|
|
|
09-01-2005, 01:41 AM
|
#26 (permalink)
|
|
Registered User
Join Date: Aug 2005
Posts: 20
|
Quote:
|
Originally Posted by fp_unit
Really. Do a sizeof(bool) and a sizeof(bool*) and I guarantee they're the same size.
|
That depends on your compiler. As far as I know, all that is guaranteed about the size of a bool is:
1 =< sizeof(bool) =< sizeof(long)
Even then, that doesn't mean all compilers stick to that
Also, the size of a pointer isn't always 32-bit, that too depends on the platform.
It's quite possible that the size of a bool is smaller than the size of a pointer. Your point of course still stands. In fact, at least for performance reasons there's little reason to pass anything like bool, long, int, char, etc by pointer. It's probably even slower, since you need to dereference the pointer.
Related to that subject, if you don't modify strings, you generally want to pass them as
const std::string &
|
|
|
09-01-2005, 05:25 AM
|
#27 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
The number "1" I can deduce since so no adress can be smaller then sizeof(char). So
sizeof(bool) >= sizeof(char). Which is basically sizeof(bool) >= 1. But from where in the ISO standard can I deduce that sizeof(bool) <= sizeof(long)?
I realize that many systems implement sizeof(bool) = sizeof(word) to evade a performance hit. But that has nothing to do with the ISO standard.
__________________
|
|
|
09-01-2005, 06:08 AM
|
#28 (permalink)
|
|
Registered User
Join Date: Aug 2005
Posts: 20
|
Well, I haven't got a copy of the standard as such, but that's what Stroustrup writes wrt the sizes of "fundamental types" in "The C++ Programming Language", which supposedly describes the standard.
|
|
|
09-01-2005, 06:54 AM
|
#29 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Oh yes, I just read it. Thanks.
__________________
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -8. The time now is 04:29 PM.
|
Copyright © 2000-2008, Milano Interactive
Web Hosting provided by Portal 360 Web Hosting
|
 |
|