Error 139 Segmentation Fault - c++

I wrote the following code, but can not figure out why I am getting a segmentation fault.
EXTRA CODE:
// A game keeps track of a Pack, and whether it should be shuffled, the score
// and how many points it takes to win, and the Players in the game
struct Game {
Pack pack; // Pack of cards
bool shuffle; // Shuffle the pack after each hand
int score[NUM_PARTNERSHIPS]; // Score for each partnership
int points_to_win; // Number of points to win the game
Player players[NUM_PLAYERS]; // Players in this game, in order around table
};
Player* Player_to_left(int playerindex, Game *game_ptr){
int index = (playerindex + 1)%4;
Player *player_ptr = &(game_ptr->players[index]);
return player_ptr;
}
static int Get_player_index(Player *player_ptr, Game *game_ptr){
Player *one_player = &(game_ptr->players[0]);
if(strcmp(player_ptr->name,one_player->name) == 0)
return 0;
Player *two_player = &(game_ptr->players[1]);
if(strcmp(player_ptr->name,two_player->name) == 0)
return 1;
Player *three_player = &(game_ptr->players[2]);
if(strcmp(player_ptr->name,three_player->name) == 0)
return 2;
Player *four_player = &(game_ptr->players[3]);
if(strcmp(player_ptr->name,four_player->name) == 0)
return 3;
return 0;
}
THE MAIN PROBLEM:
Player* Play_trick(Game *game_ptr, int leadindex, Player *lead_ptr, Suit trump){
Card cards[4] = {Player_lead_card(lead_ptr, trump)};
Card_print(cards); cout << " led by " << lead_ptr->name << endl;
int second = (leadindex + 1)%4;
Player *two_player = Player_to_left(leadindex, game_ptr);
cards[1] = Player_lead_card(two_player, trump);
if(second >= 0 && second <= 4)
Card_print(cards+1); cout << " led by " << two_player->name << endl;
int third = (second + 1)%4;
Player *third_player = Player_to_left(second, game_ptr);
cards[2] = Player_lead_card(third_player, trump);
if(third >= 0 && third <= 4)
Card_print(cards+2); cout << " led by " << third_player->name << endl;
int fourth = (third + 1)%4;
Player *fourth_player = Player_to_left(third, game_ptr);
cards[3] = Player_lead_card(fourth_player, trump);
if(fourth >= 0 && fourth <=4)
Card_print(cards+3); cout << " led by " << fourth_player->name << endl;
Card *highest = cards;
int itemp = 0;
for(int i = 1; i < 4; ++i){
if(Card_compare(cards, (cards + i), trump) < 0){
highest = (cards + i);
itemp = i;
}
}
if(itemp == 0){
cout << lead_ptr->name << " takes the trick" << endl;
return lead_ptr;
}
if(itemp == 1){
cout << two_player->name << " takes the trick" << endl;
return two_player;
}
if(itemp == 2){
cout << third_player->name << " takes the trick" << endl;
return third_player;
}
if(itemp == 3){
cout << fourth_player->name << " takes the trick" << endl;
return fourth_player;
}
return fourth_player;
}

Related

Game exp and level up

I've been making my C++ text game. Gone fairly well so far. I had a few delays with some mistakes I have made. Got most of that fixed up. Now I am working on the level up and experience points system. And IDK how to keep that number updated so it's knowns that it reaches level 55. Here's the code:
(first program ever)
//#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string.h>
using namespace std;
bool gameRunning = true;
char Yarra = 'P';
char Dragon = 'D';
char map[28];
class Player;
class Enemy {
private:
int lvl;
public:
int health;
Enemy() {
int randomNumber = rand();
int enemy_life = (randomNumber % 7) + 2;
health = enemy_life;
lvl = 1;
}
void attack(Player& p);
friend class Player;
};
class Final_dragon {
public:
int lvl;
int health;
Final_dragon() {
health = 10;
lvl = 2;
}
void attack(Player& p);
friend class Player;
};
class Player {
private:
public:
int health;
int exp;
int lvl;
Player(bool hero) {
if(hero) {
health = 100;
lvl = 1;
exp = 0;
} else {
health = 1;
}
}
void attack(Enemy& e);
void lvlUp(Player& p);
friend class Enemy;
friend class Final_boss;
};
void Player::attack(Enemy& e) {
int randomNumber = rand();
int dmg = (randomNumber % 2) + 0;
cout << "\nYou've done " << dmg << " damage!" << endl;
e.health -= dmg;
}
void Enemy::attack(Player& p) {
// int randomNumber = rand();
// int dmg = (randomNumber % 20) + 0;
int dmg = 2;
cout << "\nThe Enemy does " << dmg << " damage to you!\n" << endl;
p.health -= dmg;
}
void Player::lvlUp(Player& p) {}
int main() {
int display;
char playerInput{};
char move;
char action;
map[0] = Yarra;
map[27] = Dragon;
cout << "Map: " << map[0];
for(display = 1; display < 27; display++) {
map[display] = '*';
cout << map[display];
}
cout << map[27];
cout << endl
<< endl
<< "Press '1' Travel to another space on the board \n"
<< "Press '2' Dismount and explore the current space " << endl;
display = 0; // Start at map[0]
while(gameRunning == true) {
Player p(true);
do {
cin >> move; // Get user input
if(move == '1') // If input is '1'
{
srand(time(0));
int dice = (int)(1 + rand() % 6);
cout << "You moved: " << dice << " steps" << endl;
map[display] = '*'; // Remove old location of player
display = display + dice; // Increase display location
map[display] = 'P'; // Insert player in new map array location
cout << "Your current location: " << display
<< endl; // Player current location
}
if(move == '2') // If input is '2'
{
cout << "Your current location: " << display
<< endl; // Player current location
srand(time(0));
int monster_dice = (int)(1 + rand() % 14); // Random monster
cout << "Monster location: " << monster_dice << endl
<< endl; // monster location
if(display == monster_dice) {
cout << "You've encountered a Enemy! Press \"a\" to attack"
<< endl
<< endl;
Enemy e;
cout << "HP of the monster you encounter: " << e.health << endl;
cin >> action;
if(action == 'a' || action == 'A') {
do {
p.attack(e);
cin.ignore(1);
if(p.health <= 0) {
system("CLS");
cout << "\t\n\nYou have died..." << endl;
cout << "\t\nGAME OVER!" << endl << endl;
return 0;
}
if(e.health >= 1) {
e.attack(p);
cin.ignore(1);
}
} while(e.health >= 0);
if(e.health <= 0) {
cout << "\n\nYou defeat the Enemy! *Vistory Music*\n"
<< endl;
cout << "You gained " << 100
<< " experience from the Boar." << endl;
p.exp += 100;
}
if(p.exp >= 200 && p.exp <= 300) {
cout << "\nYou've gone up to level 2!" << endl;
p.lvl++;
p.health += 50;
}
if(p.exp >= 300 && p.exp <= 400) {
cout << "\nYou've gone up to level 3!" << endl;
p.lvl++;
p.health += 40;
}
if(p.exp >= 400 && p.exp <= 500) {
cout << "\nYou've gone up to level 4!" << endl;
p.lvl++;
p.health += 50;
}
if(p.exp >= 600 && p.exp <= 700) {
cout << "\nYou've gone up to level 5!" << endl;
p.lvl++;
p.health += 50;
}
}
}
}
} while(move != '1');
for(int x = 0; x <= 28; x++) {
cout << map[x];
}
if(display == 27 || display > 27) // If player at end of map array, end game
{
Final_dragon d;
if(p.lvl == 2) {
cout << "Ready for the fight" << endl;
} else {
system("CLS");
cout << "\nAlas, the dragons eyes stare at you and places you "
"under his spell. You try to move but fail to do so and "
"find yourself torched by the dragons fire.If only you had "
"more experience, you could have seen it coming."
<< endl;
cout << "\t\nGAME OVER!" << endl
<< endl; // Show text explaining why game ended
}
}
}
}
while(gameRunning == true) {
Player p(true);
You create a new hero player in each iteration. All experience and levels gained will be reset back to a newly created Player.
Create the Player before the loop:
Player p(true);
while(gameRunning == true) {
If you want the player to be able to fight the dragon if he/she is at least at the same level as the dragon, change the condition from if(p.lvl == 2) to if(p.lvl >= d.lvl).
You should seed the pseudo random number generator, i.e., call srand(), only once during the programs execution. Call it once when the program starts and never again.
If you are using C++11 or newer, you should use the <random> library instead of srand() and rand(). The same rule applies for those modern generators. Only seed them once.
A function to create a random number could look like this:
#include <random>
// A function to return a random number generator.
inline std::mt19937& generator() {
// the generator will only be seeded once since it's static
static std::mt19937 gen(std::random_device{}());
return gen;
}
// A function to generate int:s in the range [min, max]
int my_rand(int min, int max) {
std::uniform_int_distribution<int> dist(min, max);
return dist(generator());
}

C++ Putting a character into a cin for a while loop causes the loop to execute outside of it [duplicate]

This question already has answers here:
Why do I get an infinite loop if I enter a letter rather than a number? [duplicate]
(4 answers)
Closed 5 years ago.
I decided to try to make a little game. It's a simple survival game. Part of it has people try to survive as long as they can by choosing options. I've scaled down the game as much as possible from 1000 lines to this for the minimum case.
At one part of the game it asks, "You were visited by a gifting clown. On a scale of 0-10, how badly do you want a gift?"
If they answer 0-10, the loop works fine. If they answer with a character, like y or n, the loop basically forces the game to execute where it no longer asks players for input on any other choices.
A previous while loop works, one where it will continue so long as the player is alive. This clown while loop is nested inside of it. I have broken up the while loop with the clown section to where I think the problem is... And also included the full code just in case it's not inside there.
My goal is simply if a character is put into it, that it doesn't break this game.
main.cpp - clown section
encounterHurt = 0;
randomEncounter = rand() % 8;
cin.ignore(1, '\n');
if (randomEncounter == 1 && clown == true){
encounterChoice = 1;
cout << "\n\nYou were visited by a gifting clown. \nOn a scale of 0-10, how badly do you want a gift? ";
while (encounterChoice >= 0 && encounterChoice <= 10){
cin >> encounterChoice;
encounterFood = (rand() % 3) + encounterChoice / 2;
encounterWood = (rand() % 3) + encounterChoice / 2;
encounterMedicine = (rand() % 2);
encounterBullets = (rand() % 2);
if (encounterChoice > 0){
encounterHurt = (rand() % 10) - encounterChoice;
if (encounterHurt <= 1){
health--;
cout << "The crazy clown stabs you, but still provides gifts.";
}
}
if (encounterFood > 0) {
cout << "\nYou were provided with " << encounterFood << " food." << endl;
food += encounterFood;
}
if (encounterWood > 0) {
cout << "\nYou were provided with " << encounterWood << " wood." << endl;
wood += encounterWood;
}
if (encounterMedicine > 0) {
cout << "\nYou were provided with " << encounterMedicine << " medicine." << endl;
medicine += encounterMedicine;
}
if (encounterBullets > 0) {
cout << "\nYou were provided with " << encounterBullets << " bullets." << endl;
bullets += encounterBullets;
}
encounterChoice = 11;
}
main.cpp - Condensed code
#include <iostream>
#include <iomanip>
#include <random>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main() {
srand (time(NULL));
int randNumber = 0;
int food = 4;
int wood = 4;
int medicine = 2;
int bullets = 8;
int money = 25;
int randomEncounter = 0;
int hunt = 0;
bool axe = false;
int axeTemp = 0;
int axeBonus = 0;
int lumberTemp = 0;
int lumber = 0;
int findStore = 0;
int storeChoice = 0;
bool gun = false;
int gunSearch;
int gunTemp;
int gunBonus = 0;
int gunFind = 0;
// int searches;
// int searchesBonus;
int farmFind = 0;
int farmFood = 0;
int farmSearch = 0;
bool farm = false;
string description;
int foodTemp = 0;
int woodTemp = 0;
int medicineTemp = 0;
int bulletsTemp = 0;
int moneyTemp = 0;
int huntTemp = 0;
int huntSuccess = 0;
char huntChoice;
int encounterFood = 0;
int encounterWood = 0;
int encounterBullets = 0;
int encounterMedicine = 0;
int encounterHurt = 0;
unsigned int encounterChoice = 0;
int hurt = 0;
int health = 3;
int healthMax = 3;
int days = 1;
char action = '0';
char pause = '1';
char classChoice;
char mainChoice;
bool clown = true;
int clownHealth = 5;
char clownChoice;
int yourShot = 0;
int clownShot = 0;
string place;
//Food 1 per day per person. Can expand to include more people.
//Fuel 1 per day, takes that much to stay warm even if fewer people
//Medicine used one per wound
//Bullets 1 to hunt, though can spend more to increase chance of success.
//Days how many days that they have survied.
//Health, everyone starts with three health. Good, okay, bad, dead.
cout << "\nFood: " << food << " Wood: " << wood << " Medicine: " << medicine << " Bullets: " << bullets << " Health: " << health << endl;
while (health > 0){
cout << "\nDay: " << days;
cout << "\nFood: " << food
<< "\nWood: " << wood
<< "\nMedicine: " << medicine
<< "\nBullets: " << bullets
<< "\nHealth: " << health
<< "\nMoney: " << money << endl;
if (food >= 1){
food--;
}
if (wood >= 1){
wood--;
}
if (food <= 0){
health--;
cout << "Health lost due to lack of food" << endl;
}
if (health < healthMax && medicine > 0){
health++;
medicine--;
cout << "Health pack used to heal your character\nHealth : " << health << endl;
}
action = '0';
cout << "\n1: Find food" << endl;
cout << "What's your action? ";
cin >> action;
cout << endl;
if (action == '1'){
//
//Section for random sites to search.
//
//
randNumber = rand() % 4;
description = "";
//Maybe + days at the end, and subtract some, so that they eventually run out of places to check.
if (randNumber >= 0 && randNumber < 2) {
place = "supermarket";
foodTemp = (rand() % 4) + 1;
woodTemp = (rand() % 2) + 0;
bulletsTemp = (rand() % 2) + 0;
medicineTemp = (rand() % 2) + 1;
moneyTemp = (rand() % 5) + 5;
}
if (randNumber >= 2 && randNumber < 4) {
place = "boat house";
foodTemp = (rand() % 2) + 1;
woodTemp = (rand() % 4) + 1;
bulletsTemp = (rand() % 2) + 0;
medicineTemp = (rand() % 2) + 0;
moneyTemp = (rand() % 3) + 0;
}
cout << "You have come to the " << place << "." << endl;
cout << description << endl;
food += foodTemp;
wood += woodTemp;
bullets += bulletsTemp;
medicine += medicineTemp;
money += moneyTemp;
if (foodTemp > 0)
cout << "You have found " << foodTemp << " food." << endl;
if (woodTemp > 0)
cout << "You have found " << woodTemp << " wood." << endl;
if (medicineTemp > 0)
cout << "You have found " << medicineTemp << " medicine." << endl;
if (bulletsTemp > 0)
cout << "You have found " << bulletsTemp << " bullets." << endl;
if (moneyTemp > 0)
cout << "You have found " << moneyTemp << " money." << endl;
cout << "\nFood: " << food << " Wood: " << wood << " Medicine: " << medicine << " Bullets: " << bullets
<< " Health: " << health << " Money: " << money << endl;
//End of search rooms.
}
//Random encounter chance to see if they can gain additional items.
encounterHurt = 0;
randomEncounter = rand() % 8;
cin.ignore(1, '\n');
if (randomEncounter == 1 && clown == true){
encounterChoice = 1;
cout << "\n\nYou were visited by a gifting clown. \nOn a scale of 0-10, how badly do you want a gift? ";
while (encounterChoice >= 0 && encounterChoice <= 10){
cin >> encounterChoice;
encounterFood = (rand() % 3) + encounterChoice / 2;
encounterWood = (rand() % 3) + encounterChoice / 2;
encounterMedicine = (rand() % 2);
encounterBullets = (rand() % 2);
if (encounterChoice > 0){
encounterHurt = (rand() % 10) - encounterChoice;
if (encounterHurt <= 1){
health--;
cout << "The crazy clown stabs you, but still provides gifts.";
}
}
if (encounterFood > 0) {
cout << "\nYou were provided with " << encounterFood << " food." << endl;
food += encounterFood;
}
if (encounterWood > 0) {
cout << "\nYou were provided with " << encounterWood << " wood." << endl;
wood += encounterWood;
}
if (encounterMedicine > 0) {
cout << "\nYou were provided with " << encounterMedicine << " medicine." << endl;
medicine += encounterMedicine;
}
if (encounterBullets > 0) {
cout << "\nYou were provided with " << encounterBullets << " bullets." << endl;
bullets += encounterBullets;
}
encounterChoice = 11;
}
//Option to attack clown
//
//
}
//End of random encounter from the clown.
//Pause mechanic to prevent the game from cycling.
// pause = 'b';
// while (pause != 'a'){
// cout << "\nEnter a to continue: ";
// cin >> pause;
// }
//End of game message
cout << endl;
if (days == 100){
cout << "You have made it to 100 days. You have beaten this game. You can quit now, or try to see how long you'll last." << endl;
}
//Add day at end of while loop.
days++;
}
cout << "You have died after " << days << " days" << endl;
}
From another Stack Overflow question...
When an error occurs when reading from a stream, an error flag gets
set and no more reading is possible until you clear the error flags.
That's why you get an infinite loop.
cin.clear(); // clears the error flags
// this line discards all the input waiting in the stream
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

I cannot figure out why my code won't get past the cin on line 60. Help?? c++

This program should be accepting a bet, generating a set of cards for each player, and adding the bet to the winner's pool. This is a class project. I cannot figure out what the problem is on line 60.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
struct cards {
int value;
string face;
string suit;
bool facebool;
};
struct hand {
cards card[4];
int antiduplicate[52];
};
struct player {
string name;
int sum;
int money;
hand hand;
int bet;
};
struct points {
int player1;
int player2;
};
hand drawhand(int [52]);
points calcvalue(player, player);
int winner(player, player);
int main() {
points store = {};
player house = {"The House"};
player player1 = {};
srand (time(0));
cout << "Enter player 1's name:";
getline(cin,player1.name);
cout << "Enter player 1's money:";
cin >> player1.money;
cout << endl;
house.money = (player1.money + 1);
do{
int deckarray[52] = {0};
//do{
cout << "What do you want to bet?\n";
/* line 60 */ cin >> player1.bet;
cout << "check";
if (player1.bet < player1.money){
}
else if (player1.bet > player1.money){
cout << "\nYou cannot go into debt!!\n";
}
else if (player1.bet == 0){
cout << "\nYou ended the game!";
return 0;
}
//}while (bet > player1.money);
house.hand = drawhand(deckarray);
for (int i = 0; i < 52; i++) {
if (house.hand.antiduplicate[i] == 1)
deckarray[i] = 1;
}
player1.hand = drawhand(deckarray);
for (int i = 0; i < 52; i++) {
if (player1.hand.antiduplicate[i] == 1)
deckarray[i] = 1;
}
cout << "\nCheck check\n";
store = calcvalue(player1, house);
player1.sum = store.player1;
house.sum = store.player2;
cout << player1.name << "'s hand:\n" << player1.hand.card[1].face << " of " <<player1.hand.card[1].suit << endl
<< player1.hand.card[2].face << " of " <<player1.hand.card[2].suit << endl <<player1.hand.card[3].face << " of " <<player1.hand.card[3].suit << endl;
cout << ">> " <<player1.name << " scored " << player1.sum << " points!\n\n";
cout << house.name << "'s hand:\n" << house.hand.card[1].face << " of " <<house.hand.card[1].suit << endl
<< house.hand.card[2].face << " of " <<house.hand.card[2].suit << endl <<house.hand.card[3].face << " of " <<house.hand.card[3].suit << endl;
cout << ">> " << house.name << " scored " << house.sum << " points!\n";
int win;
win = winner(player1, house);
if (win == 1){
cout << "\n" << player1.name << " wins the round!!" << endl;
player1.money = (player1.money + player1.bet); house.money = (house.money - player1.bet);
}
else if (win == -1){
cout << "\n\n" << house.name << " wins the round!!";
house.money = (house.money + player1.bet);
player1.money = (player1.money - player1.bet);
}
else if (win == 0){
cout << "\n\n" << house.name << " wins the round!!";
house.money = (house.money + player1.bet);
player1.money = (player1.money - player1.bet);
}
cout << endl << "House money: " << house.money << endl << "Player money: " << player1.money << endl << endl;
}while (player1.money > 0 && house.money > 0 && player1.bet != 0);
cout << "Game over!";
return 0;
}
hand drawhand(int deckarray[52])
{
string tsuit, tface;
int tvalue;
int suitvalue, facevalue;
bool tfacebool;
hand thand;
for (int i = 0; i < 4; i++) {
for (int i = 0; i < 52; i++) {
if (deckarray[i] == 1)
thand.antiduplicate[i] = 1;
}
int index;
do {
index = rand()%52;
} while (thand.antiduplicate[i] == 1);
thand.antiduplicate[i] = 1;
facevalue = (index%13 + 1);
suitvalue = (index / 13);
switch (suitvalue)
{
case 0: tsuit = "Hearts";
break;
case 1: tsuit = "Diamonds";
break;
case 2: tsuit = "Clubs";
break;
case 3: tsuit = "Spades";
break;
}
switch (facevalue)
{
case 1: tface = "Ace";
tvalue = 1;
break;
case 11: tface = "Jack";
tvalue = 10;
tfacebool = true;
break;
case 12: tface = "Queen";
tvalue = 10;
tfacebool = true;
break;
case 13: tface = "King";
tvalue = 10;
tfacebool = true;
break;
}
if ((facevalue > 1) && (facevalue < 11))
tface = to_string(facevalue);
if (facevalue < 11) tvalue = facevalue;
thand.card[i].suit = tsuit;
thand.card[i].face = tface;
thand.card[i].value = tvalue;
thand.card[i].facebool = tfacebool;
}
return thand;
}
points calcvalue(player player1, player house)
{
points tpoints;
player1.sum = ((player1.hand.card[1].value + player1.hand.card[2].value + player1.hand.card[3].value) % 10);
if (player1.hand.card[1].facebool == true && player1.hand.card[2].facebool == true && player1.hand.card[3].facebool == true)
player1.sum = 10;
house.sum = ((house.hand.card[1].value + house.hand.card[2].value + house.hand.card[3].value) % 10);
if (house.hand.card[1].facebool == true && house.hand.card[2].facebool == true && house.hand.card[3].facebool == true)
house.sum = 10;
tpoints.player1 = player1.sum;
tpoints.player2 = house.sum;
return tpoints;
}
int winner(player player1, player house){
int winorlose;
if (player1.sum > house.sum)
{winorlose = 1;}
else if (player1.sum < house.sum)
{winorlose = -1;;}
else if (player1.sum == house.sum)
{winorlose = 0;}
return winorlose;
}
I see a lot of problems at first glance actually. eg: You've called a hand object 'hand' (thus redefining it), if you're going to call your object names the same as their class/struct, at least differentiate them with capitalization. eg: call your hand struct "Hand" instead of "hand"
cout << "What do you want to bet? ";
cin >> player1.bet; // <==== problem
cout << "check";
if (player1.bet < player1.money){
}
else if (player1.bet > player1.money){
cout << "\nYou cannot go into debt!!\n";
}
else if (player1.bet == 0){
cout << "\nYou ended the game!";
return 0;
}
That being said the issue you are having specifically relating to this section of code probably has something to do with a "\n" staying in the buffer and not getting cleared. Try using cin.ignore(numeric_limits::max(),'\n'); to solve this problem (don't forget to #include limits as well).
Similar problem here: c++ cin input not working?
Unfortunately I'm pressed for time and don't have time for a thorough look. :(

vector iterator + offset out of range, at the end of while loop it gives the error

while (deckSize > 2)
{
one_Card = card_deck.back();
card_deck.pop_back();
two_Card = card_deck.back();
card_deck.pop_back();
three_Card = card_deck.back();
card_deck.pop_back();
oneCard_Name = card_name(one_Card);
twoCard_Name = card_name(two_Card);
threeCard_Name = card_name(three_Card);
oneCard_Suit = card_suit(one_Card);
twoCard_Suit = card_suit(two_Card);
threeCard_Suit = card_suit(three_Card);
oneCard_Rank = card_rank(one_Card);
twoCard_Rank = card_rank(two_Card);
threeCard_Rank = card_rank(three_Card);
bool between1 = (oneCard_Rank < threeCard_Rank && threeCard_Rank < twoCard_Rank);
bool between2 = (twoCard_Rank < threeCard_Rank && threeCard_Rank < oneCard_Rank);
cout << "Here are your two cards: " << endl;
cout << setw(10) << oneCard_Name << " of " << oneCard_Suit << setw(20) << twoCard_Name << " of " << twoCard_Suit << endl;
cout << "Do you think the next card will lie between these? (y/n): ";
cin >> user_input;
cout << endl << endl;
cout << "Here is your next card: " << endl;
cout << setw(10) << threeCard_Name << " of " << threeCard_Suit << endl << endl << endl;
count++;
if(user_input == "y" || user_input == "yes" || user_input == "Yes" || user_input == "Y")
{
if(between1 || between2)
{
cout << "You win!" << endl;
win++;
}
else
{
cout << "You lose!" << endl;
lose++;
}
}
else
{
if(between1 || between2)
{
cout << "You lose!" << endl;
lose++;
}
else
{
cout << "You win!" << endl;
win++;
}
}
}
cout << "You have played this game " << count << " times and you have won: " << win << " and lost " << lose << endl;
return 0;
}
These are the two subprograms that shuffle and initialize the deck
void initDeck(vector<int> &card_deck)
{
int i;
for(i = 0; i <= 51; i++)
{
card_deck[i] = i;
}
}
void shuffleDeck(vector<int> & card_deck)
{
int n;
for(n = 51; n >= 0; n--)
{
int i = randomize();
int temp = card_deck[i];
int temp2= card_deck[n];
card_deck[n] = temp;
card_deck[i] = temp2;
}
}
After when I run the program it allows me to run it, but when I reach to the number less than the condition in the while loop it just gives me an error, and does not finish the program. I had this error earlier and fixed it, so I have a basic understanding of what the error means. From my knowledge it is trying to collect numbers past the vector length. However this time I don't see my error at all.
deckSize is not being set/updated anywhere. It should rather be card_deck.size()
You should use push_back and emplace for the type vector like this:
void initDeck(vector<int> &card_deck){
int i;
for(i = 0; i <= 51; i++)
{
card_deck.push_back(i);
}
}
Take a see to this link
Try this:
void initDeck(vector<int> &card_deck)
{
int i;
for(i = 0; i <= 51; i++)
{
card_deck.push_back(i);
}
}
void shuffleDeck(vector<int> & card_deck)
{
int n;
for(n = 51; n >= 0; n--)
{
int i = randomize();
int temp = card_deck[i];
int temp2= card_deck[n];
card_deck[n] = temp;
card_deck[i] = temp2;
}
}
For generating random number see this and this. Or you can find other solution that is more reliable.

Seg fault from attempting to access out of range array, unknown to why

I am working on a school project (I was allowed to do a simulation in C++ for my Science Fair project) and everything is going pretty ok (besides another bug that I had an issue with) until now. In order to fully understand what I am doing, I suggest that you take a quick glance at this page.
Okay. Below is my code. When you try to run it, you can clearly see that some bots' x and y cordinates are in the negatives, which shouldn't be happening. I have triple checked all the operations and everything looks fine to me. I used this to help me understand X and Y locations relative in arrays. Is there any clear issue of my mistake? I am still getting used to multidimensional arrays, so please take that into consideration. Also, I am aware that most of it is highly inefficient; cleaning it up will be a project itself. Thank you and Happy Holidays!
*My issues are coming from the moveBot functions, which are towards the bottom. It didn't seem right to have you read over unnecessary parts.
Updated Code:
// NANORG SIMULATION
// CREATED BY JACOB HARTMANN FOR THE SCIENCE FAIR (2013)
// CODED IN C++
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstdlib>
#include "bot.h"
using namespace std;
signed int map [40][70]; //2D array x first, then y
int mapBot [40][70]; //If bot is there, 1. If not, 0 This array keeps track if there is a bot in a location
signed int currentTick = 0; //Signed just in case something goes wrong and goes into the -s
int maxTick = 1000000; //Should always stay at 1mil
signed int totalEnergy = 0; //For some reason, when I add this here, everything breaks.
Bot bots[50];
void setupMap();
void tick();
void updateTickOutput();
void outputMapValue(int x, int y);
void assignBotID();
void setupBot();
void moveBot();
void manualMoveBot(int botID);
void mutateBot(int botID, int level, int sT);
void ckLoc(int botIdent);
void reassignLoc(int botID);
void gatherEnergy(int botID);
int main() {
cout << " ----------------------" << endl;
cout << " NANORG Simulation V1.3.1" << endl;
cout << "Created in C++ by Jacob Hartmann" << endl;
cout << " ----------------------" << endl << endl;
srand (time(NULL));
cout << "Setting up map.. (Step 1)" <<endl;
setupMap();
cout << "Assigning botIDs.. (Step 2)" << endl;
assignBotID();
cout << "Setting up bots.. (Step 3)" << endl;
setupBot();
cout << "Starting ticks.. (Step 4)" << endl;
tick();
// outputMapValue(5,5);
// mutateBot(5, 2); //Just to test
/* cout << endl << "X before: " << bots[5].x_cord << " Y before: " << bots[5].y_cord << endl;
moveBot(5);
cout << "X after: " << bots[5].x_cord << " Y after: " << bots[5].y_cord << endl;
cout << "Energy before: " << bots[5].energy <<endl;
gatherEnergy(5);
cout << "Energy after: " << bots[5].energy << endl; */ //DEBUG
return 0;
}
void setupMap(){
// srand (time(NULL)); //Not a good idea to put it here
for(int i = 0; i < 40; i++){
for(int j = 0; j < 70; j++){ // We add one extra (70) so it fills the entire array. Same for above
map[i][j] = rand() % 2 + 1; // 1==normal 2==toxic
}
}
// outputMapValue(5,4); //Debugging purposes
// outputMapValue(7,9);
cout << "Map setup - \033[0;32mSuccessful" << "\033[0m" << endl;
}
void outputMapValue(int x, int y){
cout << "The chunk value at (" << x+1 << ", " << y+1 << ") is: ";
cout << map[x][y]; //Outputting the value of (x,y)
if(map[x][y]==1){ //If (x,y) is == 1, the chunk is fine to eat
cout << " | Chunk is not toxic." << endl;
}
if(map[x][y]==2){
cout << " | Chunk is toxic." << endl;
}
}
void updateTickOutput() {
//cout << "Map Size (x,y): " << " " << mapsizeX << "," << mapsizeY << endl; This function used to just refresh everything, including map size, which really isn't needed. cout << "Current Tick: " << currentTick << " " << "Max Tick: " << maxTick << endl; //Just outputting currentTick and maxTick
cout << "Score: " << totalEnergy << endl;
}
void tick() {
while(true){
if(currentTick <= maxTick){
currentTick += 1;
moveBot();
/* if(currentTick >= 900000){ //If currentTick is over 900,000: we will begin to output individual ticks. Anything less and we get a seg fault.
updateTickOutput(); //See above
}*/
// cout << "tick!"; This was for debugging, before I made the updateTickOutput() function to make sure that the program actually ticked
}
else if(currentTick == maxTick){
cout << endl << "Done!" << endl; //Report that we are finished with the simulation.
// assignBotID(); //Make sure every bot has the proper ID. Moved to main()
break; //Kill the loop
}
// updateTickOutput(); //No real need for this, anymore.
}
}
void setupBot(){
srand(time(NULL));
for(int botNumber=0;botNumber <= 50; botNumber++){
// cout << "debug (botNumber): " << botNumber << endl; //Debug feature
bots[botNumber].x_cord = rand() % 39 + 1;
// cout << "debug (bot x cord): " << bots[botNumber].x_cord << endl; //Debug feature
int bufferX = bots[botNumber].x_cord;
bots[botNumber].y_cord = rand() % 69 + 1;
// cout << "debug (bot y cord): " << bots[botNumber].y_cord << endl; //Debug feature
int bufferY = bots[botNumber].y_cord;
if(mapBot[bufferX][bufferY] == 1){
cout << endl <<"A bot already is here!" << endl;
reassignLoc(botNumber);
}
else{
mapBot[bufferX][bufferY] = 1; //Take the bot's cords and make sure everyone knows that a bot is there.
// cout<< "debug (map location):"<<mapBot[bufferX][bufferY] << endl ; Just a nice debug feature
}
// if(botNumber==5){
// cout << "bot 5 assigned"; //I broke this entire function a while back and I used this to test if I was assigning bots correctly.
// }
}
/* cout << endl << "X: " << bots[5].x_cord+1 << endl; //Just some debugging stuff below
cout << "Y: " << bots[5].y_cord+1 << endl;
// cout << "The value at " << mapBot[bots[5].x_cord]<<","<< mapBot[bots[5].y_cord]<<" is: " << mapBot[bots[5].x_cord][bots[5].y_cord]; //This is a very messed up debug feature, but it still works.
cout << endl << "X: " << bots[6].x_cord+1 << endl;
cout << "Y: " << bots[6].y_cord+1 << endl;
cout << mapBot[6][6];
*/
cout << "Bot setup - \033[0;32mSuccessful" << "\033[0m" << endl;
}
void assignBotID(){
for(int i = 0; i < 50; ++i){
bots[i].id = i + 1;
}
/* int botNumber = 0;
string botName = "Bot";
string finalName;
string buffer;
while(botNumber <50){
if(botNumber < 50){
botNumber = botNumber + 1;
buffer = to_string(botNumber);
finalName = botName + buffer;
//finalName.id = botNumber; A very very broken line.
bots[botNumber].id = botNumber;
// cout << finalName << ":"<< bots[botNumber].id << endl; A super awesome debugging output to make sure the bot's id is correct
}
else if((botNumber = 51)){ //Redundancy :)
break;
}
}*/
}
void mutateBot(int botID, int level, int sT){
if((sT=2)){
bots[botID].mutationLevel = bots[botID].mutationLevel + level;
}
else if((sT=1)){
bots[botID].mutationLevel = bots[botID].mutationLevel - level;
}
// cout << botID << ":" << bots[botID].mutationLevel << endl; //Just a quick debugging feature to make sure it worked
}
void ckLoc(int botIdent){
int bufferX;
int bufferY;
bufferX = bots[botIdent].x_cord; //Just set the buffers. Uses a bit more memory, but that is okay.
bufferY = bots[botIdent].y_cord;
// cout << bufferX << endl << bufferY;
if(mapBot[bufferX][bufferY] ==1){
cout << "Bot lives here!";
reassignLoc(botIdent);
}
}
void reassignLoc(int botID){
bots[botID].x_cord = rand() % 39 + 1;
bots[botID].y_cord = rand() % 69 + 1;
ckLoc(botID);
}
void moveBot(){
for(int botID=1;botID<=50;botID++){
int direction = 0;
// int bufX = bots[botID].x_cord;
// int bufY = bots[botID].y_cord;
direction = rand() % 4 + 1;
if(direction == 1){ //NORTH
if(bots[botID].y_cord==0 || mapBot[bots[botID].x_cord][bots[botID].y_cord=-1] == 1){
//cout << "error moving bot - N ";
manualMoveBot(botID);
}
else{
//cout << "BufferY: " << bufferY;
bots[botID].y_cord -= 1;
gatherEnergy(botID);
}
}
else if(direction == 2){ //EAST
if(bots[botID].x_cord == 39 || mapBot[bots[botID].x_cord+=1][bots[botID].y_cord] == 1){
//cout << "error moving bot - E";
manualMoveBot(botID);
}
else{
bots[botID].x_cord += 1;
gatherEnergy(botID);
}
}
else if(direction == 3){ //SOUTH
if(bots[botID].y_cord == 69 || mapBot[bots[botID].x_cord][bots[botID].y_cord+=1] == 1){
//cout << "error moving bot - S ";
manualMoveBot(botID);
}
else{
bots[botID].y_cord += 1;
gatherEnergy(botID);
}
}
else if(direction == 4){ //WEST
if(bots[botID].x_cord == 0 or mapBot[bots[botID].x_cord=-1][bots[botID].y_cord] == 1){
//cout << "error moving bot - W";
manualMoveBot(botID);
}
else{
bots[botID].x_cord -= 1;
gatherEnergy(botID);
}
}
// gatherEnergy(botID); //Moved this to indivdual (spelling) stuff above. Just in case :)
// cout << endl << "Direction: " << direction << endl; //Debug
}
}
void manualMoveBot(int botID){
int direction = 0;
// int bufX = bots[botID].x_cord;
// int bufY = bots[botID].y_cord;
direction = rand() % 4 + 1;
if(direction == 1){ //NORTH
if(bots[botID].y_cord==0 || mapBot[bots[botID].x_cord][bots[botID].y_cord-1] == 1){
//cout << "error moving bot - N ";
manualMoveBot(botID);
}
else{
//cout << "BufferY: " << bufferY;
bots[botID].y_cord -= 1;
gatherEnergy(botID);
}
}
else if(direction == 2){ //EAST
if(bots[botID].x_cord == 39 || mapBot[bots[botID].x_cord+1][bots[botID].y_cord] == 1){
//cout << "error moving bot - E";
manualMoveBot(botID);
}
else{
bots[botID].x_cord += 1;
gatherEnergy(botID);
}
}
else if(direction == 3){ //SOUTH
if(bots[botID].y_cord == 69 || mapBot[bots[botID].x_cord][bots[botID].y_cord+1] == 1){
//cout << "error moving bot - S ";
manualMoveBot(botID);
}
else{
bots[botID].y_cord -= 1;
gatherEnergy(botID);
}
}
else if(direction == 4){ //WEST
if(bots[botID].x_cord == 0 or mapBot[bots[botID].x_cord-1][bots[botID].y_cord] == 1){
//cout << "error moving bot - W";
manualMoveBot(botID);
}
else{
bots[botID].x_cord += 1;
gatherEnergy(botID);
}
}
}
void gatherEnergy(int botID){
// int mV = map[bufferX][bufferY]; //Eeeeh, doesn't work here
int x = bots[botID].x_cord;
int y = bots[botID].y_cord;
// cout << "id: " << botID << endl;
// cout << "x: " << x;
// cout << endl << "y: " << y << endl;
if(1==map[x][y]){ //Good chunk
bots[botID].energy += 2000;
totalEnergy += 2000;
// cout << totalEnergy << endl; //Debug
}
else if(2==map[x][y]){ //Bad chunk (toxic)
mutateBot(botID, 1, 2);
}
}
You have several problems.
The main one is that indices of array:
so for Bot bots[50]; valid indices are [0; 49].
For map, according to contest it should be int mapBot [40][70];
so you may access element starting from mapBot[0][0] to mapBot[39][69].
You confound = and == in some comparison.
= does an assignment when == do a comparison.
I see you add extra parenthesis to remove a warning.
You have to read/understand more carefully warning messages.
so else if((currentTick = maxTick)){ in tick for example, should be else if (currentTick == maxTick) {.
Same in mutateBot...
In AssigningBotID, you increment index before accessing the array
and do redundant checks. following is enough:
void assignBotID() {
for (int i = 0; i < 50; ++i) {
bots[i].id = i /* + 1 */; // uncomment if id should be [1; 50]
// A super awesome debugging output to make sure the bot's id is correct
//std::cout << "Bot" << i << ":"<< bots[i].id << endl;
}
}
in manualMoveBot your test may change the position, since you use +=:
mapBot[bots[botID].x_cord += 1][bots[botID].y_cord] == 1
should be mapBot[bots[botID].x_cord + 1][bots[botID].y_cord] == 1
Your logic forget to update mapBot: the old place should be set to 0,
the new place should be set to 1.
Note that during initialization, it is not always set neither...
EDIT:
You should only call srand (time(NULL)); once (the one in main())
setupBot() should be something like (and so reassignLoc and ckLoc may be removed):
void setupBot() {
for (int i = 0; i < 50; ++i) {
int x, y;
do {
x = rand() % 40; // [0; 39]
y = rand() % 70; // [0; 69]
while (mapBot[x][y] == 1);
bots[i].x_cord = x;
bots[i].y_cord = y;
mapBot[x][y] = 1;
}
cout << "Bot setup - \033[0;32mSuccessful" << "\033[0m" << endl;
}
mutateBot has not be fixed: replace = by == for comparison.
void moveBot() {
for (int i = 0; i < 50; ++i) {
manualMoveBot(botID);
}
}
void manualMoveBot(int botID) {
const int oldX = bots[botID].x_cord;
const int oldY = bots[botID].y_cord;
int newX = oldX;
int newY = oldY;
int direction = rand() % 4 + 1;
if (direction == 1) { // NORTH
newY = oldY - 1;
} else if (direction == 2) { // EAST
newX = oldX + 1;
} else if (direction == 3) { // SOUTH
newY = oldY + 1;
} else if (direction == 4) { // WEST
newX = oldX - 1;
}
if (newX < 0 || 40 <= newX
|| newY < 0 || 70 <= newY
|| mapBot[newX][newY] == 1) {
cout << "error moving bot";
#if 0
// if this code is active, we may have infinite loop
// when bot is completely surrounded.
manualMoveBot(int botID);
#endif
return;
}
bots[botID].x_cord = newX;
bots[botID].y_cord = newY;
mapBot[newX][newY] = 1;
mapBot[oldX][oldY] = 0;
gatherEnergy(botID);
}