Functions not executing properly - c++11
So I'm trying to write a program that solves the "Dungeon Crawl" problem here: http://www.cplusplus.com/forum/articles/12974/. If you are too lazy to read the link (which is entirely understandable), the basic premise of the game is that a player moves on a 10x10 grid and tries to reach treasure while avoiding traps and moving enemies. Because everything is revealed to the player, it's not much of a real game, but I thought it'd be good coding practice. Sadly, I'm rusty on user input and never properly learned how to put an entire program together, which means I'm having serious problems with functions executing properly.
The main function is this:
int main()
{
int turn=0,enemyCount=0;
bool end=false;
srand (time(NULL));
node* world;
world = new node[100];
generateWorld(world);
drawWorld(world);
do {
playerMove(world);
enemiesMoves(world,enemyCount);
drawWorld(world);
end = endCheck(world);
turn++;
} while (end == false);
return 0;
}
I think this is fine as is, because it follows the simple process of gathering moves, updating the world, and then checking to see if an end condition has been reached. The problem is that numerous functions are not working as I would expect them to, and I can't figure out why they are not. This includes user input validation, updating the movement of the enemies, drawing the world, and checking if the game ended. I'll go in order.
This is the playerMove() function:
void playerMove(node* array){
int i,playerLocation,oldLocation;
bool valid=false;
char move;
for (i=0;i<100;i++){
if (array[i].player == true){
playerLocation = i;
oldLocation = playerLocation;
}
}
while(!valid){
if (cin >> move){
if (move=='w' || move=='s' || move=='a' || move=='d')
valid = true;
}
if (move=='w'){
playerLocation = oldLocation-10;
if (playerLocation < 0){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='s'){
playerLocation = oldLocation+10;
if (playerLocation > 99){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='a'){
playerLocation = oldLocation-1;
if (playerLocation % 10 == 9){
cout << "You can't swim." << endl;
valid = false;
}
}
else if (move=='d'){
playerLocation = oldLocation+1;
if (playerLocation % 10 == 0){
cout << "You can't swim." << endl;
valid = false;
}
}
}
array[oldLocation].player = false;
array[playerLocation].player = true;
}
It's supposed to gather player input, do nothing if the player enters a key that isn't WASD (they can only move in the four cardinal directions), reject an input if the player tries to move off the edge of the world, and update the player position. It does successfully do the latter, but it will not catch an invalid input, and if a move fails, it refuses to display the message it is supposed to.
This is the enemiesMoves function:
void enemiesMoves(node* array,int enemyCount){
int i,j=0,n,enemyLocations[enemyCount],oldLocations[enemyCount];
bool valid = false;
for (i=0;j<enemyCount;i++){
if (array[i].enemy==true){
enemyLocations[j] = i;
cout << enemyLocations[j] << endl;
j++;
}
}
for (j=0;j<enemyCount;j++){
oldLocations[j] = enemyLocations[j];
}
for (j=0;j<enemyCount;j++){
while (!valid){
n = rand() % 4 + 1;
if (n = 1){
enemyLocations[j] = oldLocations[j]-10;
if (enemyLocations[j] < 0)
valid = false;
}
else if (n = 2){
enemyLocations[j] = oldLocations[j]+10;
if (enemyLocations[j] > 100)
valid = false;
}
else if (n = 3){
enemyLocations[j] = oldLocations[j]-1;
if (enemyLocations[j] % 10 == 9)
valid = false;
}
else if (n = 1){
enemyLocations[j] = oldLocations[j]+1;
if (enemyLocations[j] % 10 == 0)
valid = false;
}
}
array[enemyLocations[j]].enemy = true;
array[oldLocations[j]].enemy = false;
}
}
It is supposed to move the enemies in a random direction, but reject the movement if the enemy moves off the world. Although I thought I properly copied over the playerMove() code to this, it refuses to update the position of the enemies; they stay in the same place turn after turn.
This is the drawWorld() function:
void drawWorld(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true)
cout << "P";
else if (array[i].trap==true)
cout << "T";
else if (array[i].enemy==true)
cout << "E";
else if (array[i].treasure==true)
cout << "X";
else if (array[i].player==true && array [i].treasure==true)
cout << "W";
else if ((array[i].player==true && array[i].trap==true) || (array[i].player==true && array[i].enemy==true))
cout << "L";
else {
cout << "O";
}
if ((i+1 % 10) == 0){
cout << endl;
}
}
cout << endl << endl;
}
It draws the world fine, except that it won't wrap the text every ten characters as it is plainly told to do. I can't fathom what I'm missing here.
Finally, this is the endCheck() function:
bool endCheck(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true && array[i].treasure==true){
cout << "You found the treasure and now enjoy a life of unmitigated opulence." << endl;
return true;
}
else if (array[i].player==true && array[i].trap==true){
cout << "You fell into a conspicuous trap and became tiger food." << endl;
return true;
}
else if (array[i].player==true && array[i].enemy==true){
cout << "You were captured alive by angry natives and enjoyed as part of their New Year's feast." << endl;
return true;
}
else
return false;
}
}
This is simply not executing at all. I can move the player onto a trap and nothing happens.
These problems are incredibly frustrating because I am simply unable to discern what is wrong with the code. I know the post is long, but if anyone could point out what's wrong it'd be greatly appreciated. Also it should be noted that I searched for answers before posting this, but because I think the problems are intrinsic to my code I was unable to find any usable answers.
You are returning at the end of first iteration. So it will check only first field and then return false (if there was no player and treasure/trap/enemy in first field).
Change your function to look like this:
bool endCheck(node* array){
int i;
for (i=0;i<100;i++){
if (array[i].player==true && array[i].treasure==true){
cout << "You found the treasure and now enjoy a life of unmitigated opulence." << endl;
return true;
}
else if (array[i].player==true && array[i].trap==true){
cout << "You fell into a conspicuous trap and became tiger food." << endl;
return true;
}
else if (array[i].player==true && array[i].enemy==true){
cout << "You were captured alive by angry natives and enjoyed as part of their New Year's feast." << endl;
return true;
}
}
return false;
}
You have to check all possible fields before returning false that indicates no collision.
In enemiesMoves(), you are checking if(n = 1), I'm sure you meant if(n == 1).
Do this:
....
n = rand() % 4 + 1;
if (n == 1){
.....
Also, n == 1 case is checked twice! Once in if and then in the last else if.
For the rand() function to actually generate random numbers on each run, initialize a random seed first using srand(), as follows:
/* initialize random seed: */
srand (time(NULL));
n = rand() % 4 + 1;
Related
Memory leak involving an unloaded shared object?
I am trying to understand this programming problem whereby I am supposed to guess the data structures. I am having a slight issue with my program. PROBLEM: I have no clue as to why my program always gets killed with signal 11 (segmentation fault) but it works and compiles fine. About the program: n would be number of integer sets ; it takes in an integer p (command) and integer data and pushes/pops into the following data structures. I've use a bool as flag to check the statuses. Am I right to believe the structures would be destroyed after the while loop as it goes out of scope? int main(){ int n; while (cin >> n && n != 0){ stack<int> mystack; queue<int> myqueue; priority_queue<int> maxq; bool isstack = true; bool isqueue = true; bool ispq = true; for (int i = 0; i < n; i++){ int p, data; cin >> p >> data; if (p == 1){ if (isqueue) myqueue.push(data); if (isstack) mystack.push(data); if (ispq) maxq.push(data); } else if (p == 2){ if ((mystack.empty() || mystack.top() != data) && isstack) isstack = false; else mystack.pop(); if ((myqueue.empty() || myqueue.front() != data) && isqueue) isqueue = false; else myqueue.pop(); if ((maxq.empty() || maxq.top() != data) && ispq) ispq = false; else maxq.pop(); } } if (isstack && !(isqueue || ispq)) cout << "stack" << endl; else if (isqueue && !(isstack || ispq)) cout << "queue" << endl; else if (isstack && (ispq || isqueue) || (isqueue && ispq)) cout << "not sure" << endl; else if (ispq && !(isstack || isqueue)) cout << "priority queue" << endl; else cout << "impossible" << endl; } return 0; }
Yes, the data structures you’ve used are local scope to while, so they get destructed at the end of while loop. Unless you provide for what input you’re seeing segmentation fault, it’s hard to say. Or run it in debug mode, your program should break at line where seg fault occurs.
I tried to run this code. This code threw an exception when you pop after 'isstack' was changed to false. The exception was 'Expression: deque empty before pop'. After the variable changed false, always condition statements are return false. So you tried to pop at empty stack. That is a just logical bug.
Parsing through Vectors
I am new and learning C++ using the Programming Principles ... book by Bjarne Stroustrup. I am working on one problem and can't figure out how to make my code work. I know the issue is with if (words[i]==bad[0, bad.size() - 1]) in particular bad.size() - 1]) I am trying to out put all words in the words vector except display a bleep instead of any words from the words vector that match any of the words in the bad vector. So I need to know if words[i] matches any of the values in the bad vector. #include "../std_lib_facilities.h" using namespace std; int main() { vector<string> words; //declare Vector vector<string> bad = {"idiot", "stupid"}; //Read words into Vector for(string temp; cin >> temp;) words.push_back(temp); cout << "Number of words currently entered " << words.size() << '\n'; //sort the words sort(words); //read out words for(int i = 0; i < words.size(); ++i) if (i==0 || words[i-1]!= words[i]) if (words[i]==bad[0, bad.size() - 1]) cout << "Bleep!\n"; else cout << words[i] << '\n'; return 0; }
You need to go through all of the entries in the bad vector for each entry in the words vector. Something like this: for(const string& word : words) { bool foundBadWord = false; for(const string& badWord : bad) { if(0 == word.compare(badWord)) { foundBadWord = true; break; } } if(foundBadWord) { cout << "Bleep!\n"; } else { cout << word << "\n"; } }
Efficient checking for Subset
Given two bitset objects 'B1' and 'B2' of length 'n' respectively. Whats the efficient way to say whether all the bits that are set in 'B2' are also in 'B1'? Example: B1 = 110111 B2_bad = 011001 B2_good = 100001 So, 'B1' and 'B2_good' is good but not 'B1' and 'B2_bad'?
Well, I guess these two following methods might help. You might need to benchmark them as which is faster. std::bitset<6> B1 (std::string("110111")); std::bitset<6> B2_bad (std::string("011001")); std::bitset<6> B2_good (std::string("100001")); //////////////One way///////////////////////// if ( (~B1 &= (B2_bad)).any()) std::cout << "No" << std::endl; else std::cout << "Yes" << std::endl; if ( (~B1 &= (B2_good)).any()) std::cout << "No" << std::endl; else std::cout << "Yes" << std::endl; ///////////////Second way////////////////// int i =0; for (i = 0; i < B1.size(); ++i) if (B2_bad[i] == 1 && B1[i] == 0) break; if (i == B1.size()) std::cout << "Yes" << std::endl; else std::cout << "No" << std::endl; for (i = 0; i < B1.size(); ++i) if (B2_good[i] == 1 && B1[i] == 0) break; if (i == B1.size()) std::cout << "Yes" << std::endl; else std::cout << "No" << std::endl;` Probably, someone more proficient than me can comment on their performance. But my best guess is first method leverages the library functions which should give the best performance , however if most of your queries would have 'Result NO' and B1-B2 will not agree on one of the earlier bits then second method might have better runtime. As, library functions involved have a worst runtime complexity of O(n).
Simple coding to Stack
int main() { string sentence; int length; cout << "Enter the sentence now." << endl; getline(cin, sentence); for(int i = 0; i < sentence[i]; i++) { if(sentence[i]==';') cout<<" "; else if(sentence[i] != ' ') { cout << sentence[i]; } else if(sentence[i] == ' ') { cout << endl; } } } I need help in this code to change into stack coding method. At least you can show me some clue how to change this code into simple stack code.
cin>>a>>b>>c>>d>>e>>f>>g; myStack.push(g); myStack.push(f); myStack.push(e); myStack.push(d); myStack.push(c); myStack.push(b); myStack.push(a); while(!myStack.empty()){ cout<<myStack.top()<<endl; myStack.pop(); } return 0; } This is an example, but its not flexible. User only can enter 7 words or maybe we can do it in array?
Bool must be always returning NULL(if statement ignoring true or false)
I need to know why I am always returning NULL in the following context(for example no matter if I say "Yes", or "No", for any of the questions I am getting null( I assume because the question process repeats when it runs) even though I say no in main. I'm trying to get it to do this: for all invalid answers I return null, if null start over the question process, if answer was valid I return either true or false, if true continue, if false quit program. bool question1() { string answer2; cout << "Are you 18 or older and have a valid Driver's License? Yes or No: "; getline( cin, answer2); transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower); cout << endl; if( answer2 == "yes") { cout << "Alright! " << endl << "You are set for registration. Please fill out the registration form. "; return true; } else if( answer2 == "no") { cout << "Do you know someone else who is 18 or older that can register? Yes or No "; getline( cin, answer2); transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower); if( answer2 == "yes") { cout << "Good, then please continue the process in their place. Please fill out the registration form"; return true; } else if( answer2 == "no") { cout << "Please come back later when you have the appropriate personel"; return false; } else { cout << "The answer given was invalid. Please give a valid answer. " << endl << endl ; return NULL; } } else { cout << "The answer given was invalid. Please give a valid answer. " << endl << endl; return NULL; } void registerPerson( array< string, nameSize > namesOfPeople, array< string, idSize > idlen) { string pName; string dLicense; static int i = 0; static int b = 0; static int c = 0; unsigned int x = 1; cout << endl << endl << "REGISTRATION FORM:" << endl << endl << "------------------" << endl; cout << "Please" << endl << "enter the following: \n \n"; cout << "Name: "; getline( cin, pName ); for ( int j = i; j<=800; ++ j ) { namesOfPeople[j] = pName; cout << namesOfPeople[j]; i = i + 1; break; } cout << endl; while( x = 1) { cout << "Driver\'s Licence Number( Must be 9 characters long, no dashesh ): "; cin >> dLicense; if ( dLicense.length() < 9 || dLicense.length()> 9 ) { cout << "The entered number was invalid. Please try again"; } else { for ( int a = i; c<=800; ++ a ) { idlen[a] = dLicense; cout << idlen[a]; c = c + 1; break; } } } } } { int main() array< string, nameSize > names = {}; array< string, idSize > ids = {}; carShare mycarShare1; carShare mycarShare2; mycarShare2.welcomeMessage(); mycarShare2.question1(); if( mycarShare1.question1() == NULL) { mycarShare1.question1(); } else if( mycarShare1.question1() == true) { mycarShare1.registerPerson(names, ids); } else { return 0; } system( "PAUSE" ); return 0; }
I'd probably change it to handle invalid input within question1() itself. An easy way to start the question over again is letting question1 call itself again on invalid input until it gets a valid one like here (I put comments at all the changed places.): bool question1() { string answer2; cout << "Are you 18 or older and have a valid Driver's License? Yes or No: "; getline( cin, answer2); transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower); cout << endl; if( answer2 == "yes") { cout << "Alright! " << endl << "You are set for registration. Please fill out the registration form. "; return true; } else if( answer2 == "no") { cout << "Do you know someone else who is 18 or older that can register? Yes or No "; getline( cin, answer2); transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower); if( answer2 == "yes") { cout << "Good, then please continue the process in their place. Please fill out the registration form"; return true; } else if( answer2 == "no") { cout << "Please come back later when you have the appropriate personel"; return false; } else { cout << "The answer given was invalid. Please give a valid answer. " << endl << endl ; return question1(); // call itself again on invalid input. } } else { cout << "The answer given was invalid. Please give a valid answer. " << endl << endl; return question1(); // call itself again on invalid input. } } int main() { array< string, nameSize > names = {}; array< string, idSize > ids = {}; carShare mycarShare1; carShare mycarShare2; mycarShare2.welcomeMessage(); bool answer = mycarShare2.question1(); /* if( answer == NULL) we don't need this anymore if we handle errors inside question1() { mycarShare1.question1(); } */ if( answer == true) // notice the change to if instead of else if here. { mycarShare1.registerPerson(names, ids); } else { return 0; } system( "PAUSE" ); return 0; } Another way to do the same without recursion would be a do... while loop, here's a version of only question1() with a loop: bool question1() { string answer2; // has to be declared before the loop. do { cout << "Are you 18 or older and have a valid Driver's License? Yes or No: "; getline( cin, answer2); transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower); cout << endl; if( answer2 == "yes") { cout << "Alright! " << endl << "You are set for registration. Please fill out the registration form. "; return true; } else if( answer2 == "no") { cout << "Do you know someone else who is 18 or older that can register? Yes or No "; getline( cin, answer2); transform(answer2.begin(), answer2.end(), answer2.begin(), ::tolower); if( answer2 == "yes") { cout << "Good, then please continue the process in their place. Please fill out the registration form"; return true; } else if( answer2 == "no") { cout << "Please come back later when you have the appropriate personel"; return false; } } }while(answer2 != "yes" && answer2 != "no"); // loop as long as the input is invalid. } ===================================== Edit: As clarification to it printing multiple times, here's the culprit in your original code: mycarShare2.question1(); if( mycarShare1.question1() == NULL) { mycarShare1.question1(); } else if( mycarShare1.question1() == true) { mycarShare1.registerPerson(names, ids); } else { return 0; } mycarShare2.question1() is a function call, you were calling your function 3 times in that part. What you'd want was probably saving it in a bool variable and only test in the if/else statements after that, like this: bool answer = mycarShare2.question1(); if( answer == NULL) { mycarShare1.question1(); } else if( answer == true) { mycarShare1.registerPerson(names, ids); } else { return 0; } Note: this is just to show it the way you probably expected it to be executed in your original code and not a solution. As said bool can only be true or false and the check for NULL isn't needed at all. (See my solutions above.)