C++ - Vector Segmentation Error - c++

I am currently working on a CMSC project called Blackjack for my college course. I have am trying to add a class called Card to a vector object in another class called Hand. The Hand class is stored as an object in another vector in a class called Player.
My issue is that I try to call the method OutputPlayerHand in a class called Blackjack but I get a segmentation error.
Here is my code for the Blackjack.cpp class.
#include "Blackjack.h"
#include <iostream>
Blackjack::Blackjack()
{
// Initialize the dealer
Player dealer((char *) "Dealer", 100);
m_dealer = dealer;
// Initialize a player 'Jane' with 100 funds
Player player((char *) "Jane", 100);
m_players.push_back(player);
}
Blackjack::Blackjack(char *names[], int numPlayers)
{
// Initialize the dealer
Player dealer((char *) "Dealer", 100);
m_dealer = dealer;
// Loop through all passed player names
for(int i = 0; i < numPlayers; i++)
{
// Initialize a player 'names[i]' with 100 funds
Player player(names[i], 100);
m_players.push_back(player);
}
}
int Blackjack::GetNumPlayers()
{
// Return the size of the players vector
return m_players.size();
}
char *Blackjack::GetPlayerName(int player)
{
// Return the requested player's name
return m_players[player].GetName();
}
int Blackjack::GetPlayerFunds(int player)
{
// Return the requested player's funds
return m_players[player].GetFunds();
}
void Blackjack::SetPlayerFunds(int player, int amt)
{
// Set the requested player's funds
m_players[player].SetFunds(amt);
}
bool Blackjack::SetPlayerBet(int player, int amt)
{
// If the player has insufficient funds
if(m_players[player].GetFunds() < amt)
{
// Return false
return false;
}
// Subtract the amount from the player funds
m_players[player].SetFunds(m_players[player].GetFunds() - amt);
// Add the amount to the player bet
m_players[player].SetBet(amt);
// Return true
return true;
}
void Blackjack::NewDeal()
{
// Create a new unsorted 52 card deck
Deck deck;
// Initialize m_deck to the new deck
m_deck = deck;
// Shuffle m_deck
m_deck.Shuffle();
// 2 cards for dealer, 2 cards for each player
int cardsToDeal = 2 + (2 * m_players.size());
// While we still have cards to deal
while(cardsToDeal > 0)
{
// Deal to each player
for(unsigned int i = 0; i < m_players.size(); i++)
{
std::cout << "Deal Player Card" << std::endl;
// Deal one card to the player
m_players[i].GetHand().AddCard(m_deck.DealCard());
// Decrement the number of cards to deal
cardsToDeal--;
}
std::cout << "Deal Dealer Card" << std::endl;
// Deal the dealer one card
m_dealer.GetHand().AddCard(m_deck.DealCard());
// Decrement the number of cards to deal
cardsToDeal--;
}
}
void Blackjack::OutputPlayerHand(int player)
{
std::cout << "Player Output Card." << std::endl;
m_players[player].GetHand().GetCard(0).OutputCard();
}
void Blackjack::OutputDealerHand()
{
// TODO: Code Method
}
bool Blackjack::HitPlayer(int player)
{
// TODO: Code Method
return false;
}
void Blackjack::DealerPlay()
{
// TODO: Code Method
}
int Blackjack::SettlePlayerBet(int player)
{
// TODO: Code Method
return -1;
}
Here is my code for the Player.cpp class.
#include "Player.h"
Player::Player()
{
m_name = (char *) "Jane";
m_funds = 100;
m_bet = 0;
}
Player::Player(char *name, int funds)
{
m_name = name;
m_funds = funds;
m_bet = 0;
}
char *Player::GetName()
{
return m_name;
}
void Player::SetName(char *name)
{
m_name = name;
}
int Player::GetFunds()
{
return m_funds;
}
void Player::SetFunds(int funds)
{
m_funds = funds;
}
int Player::GetBet()
{
return m_bet;
}
void Player::SetBet(int bet)
{
m_bet = bet;
}
Hand Player::GetHand()
{
return m_hand;
}
Here is my code for the Hand.cpp class.
#include "Hand.h"
void Hand::AddCard(Card card)
{
m_cards.push_back(card);
}
Card Hand::GetCard(int card)
{
return m_cards[card];
}
int Hand::Size()
{
return m_cards.size();
}
void Hand::Clear()
{
m_cards.clear();
}
Here is my code for the main class Proj2.cpp.
/*
* CHANGES TO Blackjack.h SPEC:
* added new member funcs:
* char *GetPlayerName(int)
* int GetNumPlayers()
* void OutputDealerHand()
*
* HitPlayer() should print out the card that was dealt.
*/
#include <cstdlib>
#include <iostream>
#include "Blackjack.h"
using namespace std;
Blackjack *CreateGame(int argc, char *argv[]);
int ProcessArgs(int argCnt, char *args[], char **&names, int *&funds);
void DoNewDeal(Blackjack &game);
void ProcAllBets(Blackjack &game);
void DoAllPlays(Blackjack &game);
void PlayOnePlayer(Blackjack &game, int player);
void SettleAllPlayers(Blackjack &game);
void ShowAllPlayerFunds(Blackjack &game);
bool QueryAnotherRound();
int main(int argc, char *argv[]) {
Blackjack *game;
int round;
cout << "Welcome to CMSC 202 Blackjack!\n";
game = CreateGame(argc, argv);
round = 0;
do {
cout << "\nRound " << ++round << ":\n";
ProcAllBets(*game);
DoNewDeal(*game);
DoAllPlays(*game);
SettleAllPlayers(*game);
ShowAllPlayerFunds(*game);
} while (QueryAnotherRound());
cout << "\nGoodbye!\n";
return 0;
}
Blackjack *CreateGame(int argc, char *argv[]) {
char **names;
int *funds;
int numPlayers;
Blackjack *game;
numPlayers = ProcessArgs(argc - 1, &argv[1], names, funds);
game = new Blackjack(names, numPlayers);
for (int p = 0; p < numPlayers; p++) {
game->SetPlayerFunds(p, funds[p]);
}
return game;
}
int ProcessArgs(int argCnt, char *args[], char **&names, int *&funds) {
int i, p;
int numRecs = argCnt / 2;
names = static_cast<char **>(calloc(numRecs, sizeof(char *)));
funds = static_cast<int *>(calloc(numRecs, sizeof(int)));
for (p = 0, i = 0; p < numRecs; p++) {
names[p] = args[i++];
funds[p] = atoi(args[i++]);
}
return p;
}
void ProcAllBets(Blackjack &game) {
int numPlayers = game.GetNumPlayers();
int bet;
for (int p = 0; p < numPlayers; p++) {
cout << "How much does " << game.GetPlayerName(p) << " bet? ";
cin >> bet;
cout << endl; // For neat scripting
if (!game.SetPlayerBet(p, bet)) {
cout << "Illegal bet--changing to $0\n";
game.SetPlayerBet(p, 0);
}
}
}
void DoNewDeal(Blackjack &game) {
int numPlayers = game.GetNumPlayers();
game.NewDeal();
cout << "The players' hands:\n";
for (int p = 0; p < numPlayers; p++) {
cout << game.GetPlayerName(p) << ": ";
game.OutputPlayerHand(p);
cout << endl;
}
cout << "Dealer: ";
game.OutputDealerHand(); // This hides dealer's hole card
cout << "\n\n";
}
void DoAllPlays(Blackjack &game) {
int numPlayers = game.GetNumPlayers();
int p;
for (p = 0; p < numPlayers; p++) {
PlayOnePlayer(game, p);
}
game.DealerPlay();
}
void PlayOnePlayer(Blackjack &game, int player) {
char *name = game.GetPlayerName(player);
string answer;
bool hit, busted;
cout << ">>" << name << "'s turn:\n";
busted = false;
do {
cout << "Hand: ";
game.OutputPlayerHand(player);
cout << endl;
cout << name << "'s play: ";
cin >> answer;
cout << endl; // For neat scripting
answer[0] == 'y' || answer[0] == 'Y';
hit = (answer[0] == 'h' || answer[0] == 'H');
if (hit) {
busted = game.HitPlayer(player);
}
} while (hit && !busted);
if (busted) {
cout << "Busted!\n";
}
cout << endl;
}
void SettleAllPlayers(Blackjack &game) {
int numPlayers = game.GetNumPlayers();
int p;
for (p = 0; p < numPlayers; p++) {
game.SettlePlayerBet(p);
// Above should print out:
// Joe has busted--Dealer wins", or "Sally has 15--Dealer loses"
}
cout << endl;
}
void ShowAllPlayerFunds(Blackjack &game) {
int numPlayers = game.GetNumPlayers();
int p;
for (p = 0; p < numPlayers; p++) {
cout << game.GetPlayerName(p) << " now has $"
<< game.GetPlayerFunds(p) << endl;
}
cout << endl;
}
bool QueryAnotherRound() {
string answer;
cout << "Another round? ";
cin >> answer;
cout << endl; // For neat scripting
return answer[0] == 'y' || answer[0] == 'Y';
}
Can anyone tell me what I am doing wrong? I am not allowed to edit the Proj2.cpp class in any way. If you need more information please do not hesitate to ask. If you need to see the project in it's entirety here is a link to the Github repository for the entire project so far. If you need to see my project rules and clarifications, here is a link to my courses project description website.
Any help is greatly appreciated on this matter, thank you in advance for your time.

The Hand is empty.
This line: m_players[i].GetHand().AddCard(m_deck.DealCard()) adds a card to a temporary copy only
Make GetHand() return a reference and your players will actually get cards.
Also, you should not include executables like Prog2.out in repositories.

Related

C++ Segmentation fault when trying to insert derived objects into an Object Array

I'm doing a project where we need to create a basic Zoo Tycoon game, in which we create a base class called Animal, 3 derived classes of Animal: Tiger, Penguin, Turtle. We also need to create a Zoo class that holds 3 separate arrays for each animal. I've written up my code but keep getting segmentation faults when compiling. I believe this is due to the way I create my object arrays as well as the method I use for inserting objects into them. I've uploaded my entire code. I apologize for the length. I didn't know what segment I could have uploaded to give a clear idea of what I'm doing.
This is my code
Animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
class Animal
{
private:
int age;
double cost;
int numberOfBabies;
double baseFoodCost;
double payoff;
public:
Animal();
Animal(int, double, int, double, double);
int getAge();
void setAge(int);
double getCost();
void setCost(double);
int getNumberOfBabies();
void setNumberOfBabies(int);
double getBaseFoodCost();
void setBaseFoodCost(double);
double getPayoff();
void setPayoff(double);
};
#endif
Animal.cpp
#include "Animal.h"
Animal::Animal(int a, double c, int n, double b, double p)
{
age = a;
cost = c;
numberOfBabies = n;
baseFoodCost = b;
payoff = p;
}
int Animal::getAge()
{
return age;
}
void Animal::setAge(int a)
{
age = a;
}
double Animal::getCost()
{
return cost;
}
void Animal::setCost(double c)
{
cost = c;
}
int Animal::getNumberOfBabies()
{
return numberOfBabies;
}
void Animal::setNumberOfBabies(int n)
{
numberOfBabies = n;
}
double Animal::getBaseFoodCost()
{
return baseFoodCost;
}
void Animal::setBaseFoodCost(double b)
{
baseFoodCost = b;
}
double Animal::getPayoff()
{
return payoff;
}
void Animal::setPayoff(double p)
{
payoff = p;
}
Tiger.h
#ifndef TIGER_H
#define TIGER_H
#include "Animal.h"
class Tiger: public Animal
{
public:
Tiger();
Tiger(int, double, int, double, double);
};
#endif // !TIGER_H
Tiger.cpp
#include "Tiger.h"
Tiger::Tiger(int age, double cost, int numberOfBabies, double baseFoodCost, double payoff) : Animal(age, cost, numberOfBabies, baseFoodCost, payoff)
{
}
Penguin.h
#ifndef PENGUIN_H
#define PENGUIN_H
#include "Animal.h"
class Penguin: public Animal
{
public:
Penguin();
Penguin(int, double, int, double, double);
};
#endif
Penguin.cpp
#include "Penguin.h"
Penguin::Penguin(int age, double cost, int numberOfBabies, double baseFoodCost, double payoff) : Animal(age, cost, numberOfBabies, baseFoodCost, payoff)
{
}
Turtle.h
#ifndef TURTLE_H
#define TURTLE_H
#include "Animal.h"
class Turtle: public Animal
{
public:
Turtle();
Turtle(int, double, int, double, double);
};
#endif
Turtle.cpp
#include "Turtle.h"
Turtle::Turtle(int age, double cost, int numberOfBabies, double baseFoodCost, double payoff) : Animal(age, cost, numberOfBabies, baseFoodCost, payoff)
{
}
Zoo.h
#ifndef ZOO_H
#define ZOO_H
#include "Animal.h"
#include "Tiger.h"
#include "Penguin.h"
#include "Turtle.h"
#include <cstdlib>
#include <iostream>
using namespace std;
class Zoo
{
private:
Tiger **arrayTiger;
Penguin **arrayPenguin;
Turtle **arrayTurtle;
int sizeTiger, sizePenguin, sizeTurtle;
int capacityTiger, capacityPenguin, capacityTurtle;
double amount;
double revenue;
public:
Zoo();
Zoo(double);
void insertTiger(Tiger);
void insertPenguin(Penguin);
void insertTurtle(Turtle);
void Events();
double getAmount();
void setAmount(double);
void subtractAmount(double);
Tiger** getTigerArray();
Penguin** getPenguinArray();
Turtle** getTurtleArray();
void calculateRevenue();
double getRevenue();
void incrementAge();
void resetRevenue();
};
#endif
Zoo.cpp
#include "Zoo.h"
Zoo::Zoo(double a)
{
amount = a;
capacityTiger = 10;
capacityPenguin = 10;
capacityTurtle = 10;
sizeTiger = 0;
sizePenguin = 0;
sizeTurtle = 0;
revenue = 0;
arrayTiger = new Tiger*[capacityTiger];
arrayPenguin = new Penguin*[capacityPenguin];
arrayTurtle = new Turtle*[capacityTurtle];
}
void Zoo::insertTiger(Tiger t)
{
if (sizeTiger < capacityTiger)
{
arrayTiger[sizeTiger++] = &t;
}
else
{
int oldTigerCapacity = capacityTiger;
capacityTiger *= 2;
Tiger** newArrayTiger = new Tiger* [capacityTiger];
for (int i = 0; i < oldTigerCapacity; i++)
{
newArrayTiger[i] = arrayTiger[i];
}
delete[] arrayTiger;
arrayTiger = newArrayTiger;
arrayTiger[sizeTiger++] = &t;
}
}
void Zoo::insertPenguin(Penguin p)
{
if (sizePenguin < capacityPenguin)
{
arrayPenguin[sizePenguin++] = &p;
}
else
{
int oldPenguinCapacity = capacityPenguin;
capacityPenguin *= 2;
Penguin** newArrayPenguin = new Penguin* [capacityPenguin];
for (int i = 0; i < oldPenguinCapacity; i++)
{
newArrayPenguin[i] = arrayPenguin[i];
}
delete[] arrayPenguin;
arrayPenguin = newArrayPenguin;
arrayPenguin[sizePenguin++] = &p;
}
}
void Zoo::insertTurtle(Turtle turt)
{
if (sizeTurtle < capacityTurtle)
{
arrayTurtle[sizeTurtle++] = &turt;
}
else
{
int oldTurtleCapacity = capacityTurtle;
capacityTurtle *= 2;
Turtle** newArrayTurtle = new Turtle* [capacityTurtle];
for (int i = 0; i < oldTurtleCapacity; i++)
{
newArrayTurtle[i] = arrayTurtle[i];
}
delete[] arrayTurtle;
arrayTurtle = newArrayTurtle;
arrayTurtle[sizeTurtle++] = &turt;
}
}
void Zoo::subtractAmount(double a)
{
amount -= a;
}
double Zoo::getAmount()
{
return amount;
}
void Zoo::setAmount(double a)
{
amount += a;
}
void Zoo::Events()
{
int option = 0;
option = rand() % 4 + 1;
switch(option)
{
case 1: cout << "\n\nA sickness has occurred at the zoo." << endl << endl;
break;
case 2: cout << "\n\nThere has been a boom in zoo attendance." << endl << endl;
break;
case 3: cout << "\n\nA baby animal is born." << endl << endl;
break;
case 4: cout << "\n\nNothing happens." << endl << endl;
break;
}
}
Tiger** Zoo::getTigerArray()
{
return arrayTiger;
}
Penguin** Zoo::getPenguinArray()
{
return arrayPenguin;
}
Turtle** Zoo::getTurtleArray()
{
return arrayTurtle;
}
void Zoo::incrementAge()
{
for(int i = 0; i < sizeTiger; i++)
{
if((arrayTiger[i]->getCost()) == 10000)
{
arrayTiger[i]->setAge((arrayTiger[i]->getAge()) + 1);
}
}
for(int i = 0; i < sizePenguin; i++)
{
if((arrayPenguin[i]->getCost()) == 1000)
{
arrayPenguin[i]->setAge((arrayPenguin[i]->getAge()) + 1);
}
}
for(int i = 0; i < sizeTurtle; i++)
{
if((arrayTurtle[i]->getCost()) == 100)
{
arrayTurtle[i]->setAge((arrayTurtle[i]->getAge()) + 1);
}
}
}
void Zoo::calculateRevenue()
{
for (int i = 0; i < sizeTiger; i++)
{
revenue += (arrayTiger[i]->getPayoff());
}
for (int i = 0; i < sizePenguin; i++)
{
revenue += (arrayPenguin[i]->getPayoff());
}
for (int i = 0; i < sizeTurtle; i++)
{
revenue += (arrayPenguin[i]->getPayoff());
}
}
double Zoo::getRevenue()
{
return revenue;
}
void Zoo::resetRevenue()
{
revenue = 0;
}
main.cpp
#include "Animal.h"
#include "Penguin.h"
#include "Tiger.h"
#include "Turtle.h"
#include "Zoo.h"
#include <iostream>
using namespace std;
int main()
{
const int baseFeedingCost = 10;
Zoo z1(100000);
bool playGame = false;
bool menuExit = false;
char userStart, continueGame, loopPurchase, loopChoice = ' ';
int day = 0;
int initializer = 0;
cout << "\nWelcome to Zoo Tycoon!\n\nIn this game you will manage a zoo business." << endl;
while(!menuExit)
{
cout << "\nA: Play Game" << endl;
cout << "B: Exit" << endl;
cout << "\n\nPlease Select an option: ";
cin.get(userStart);
cin.ignore(INT_MAX, '\n');
if(userStart == 'A' || userStart == 'a') //user selected to start game
{
playGame = true;
menuExit = true;
cout << "\n\nYou will start with $" << z1.getAmount() << " in the bank." << endl;
cout << "\n\nTo begin your Zoo, you must purchase three types of animals (tigers, penguins, turtles)";
cout <<"\nin quantities of either 1 or 2." << endl << endl;
cout << "Please enter you desired number of tigers (1 or 2): ";
cin >> initializer;
if (initializer == 2)
{
Tiger t1(0, 10000, 1, 50, 2000);
z1.insertTiger(t1);
z1.subtractAmount(10000);
Tiger t2(0, 10000, 1, 50, 2000);
z1.insertTiger(t2);
z1.subtractAmount(10000);
cout << "\n\nYou will start with 2 tigers." << endl;
}
else if (initializer == 1)
{
Tiger t1(0, 10000, 1, 50, 2000);
z1.insertTiger(t1);
z1.subtractAmount(10000);
cout << "\nYou will start with 1 tiger." << endl;
}
cout << "\n\nPlease enter you desired number of penguins (1 or 2): ";
cin >> initializer;
if (initializer == 2)
{
Penguin p1(0, 1000, 5, 10, 100);
z1.insertPenguin(p1);
z1.subtractAmount(1000);
Penguin p2(0, 1000, 5, 10, 100);
z1.insertPenguin(p2);
z1.subtractAmount(1000);
cout << "\n\nYou will start with 2 penguins." << endl;
}
else if (initializer == 1)
{
Penguin p1(0, 1000, 5, 10, 100);
z1.insertPenguin(p1);
z1.subtractAmount(1000);
cout << "\n\nYou will start with 1 penguin." << endl;
}
cout << "\n\nPlease enter you desired number of turtles (1 or 2): ";
cin >> initializer;
if (initializer == 2)
{
Turtle tr1(0, 100, 10, 5, 5);
z1.insertTurtle(tr1);
z1.subtractAmount(100);
Turtle tr2(0, 100, 10, 5, 5);
z1.insertTurtle(tr2);
z1.subtractAmount(100);
cout << "\n\nYou will start with 2 turtles." << endl << endl;
}
else if (initializer == 1)
{
Turtle tr1(0, 100, 10, 5, 5);
z1.insertTurtle(tr1);
z1.subtractAmount(100);
cout << "\n\nYou will start with 1 turtle." << endl << endl;
}
cin.ignore(255, '\n');
cin.clear();
}
else if(userStart == 'B' || userStart == 'b')
{
cout << "\nThis game will now exit." << endl << endl;
menuExit = true;
}
else //user inputted invalid response
{
cout << "\n\nI'm sorry but your response is invalid. Please try again." << endl;
cin.ignore(255, '\n');
cin.clear();
}
}
while(playGame) //daily turns that ends when user enters false for playGame
{
loopChoice = loopPurchase = ' ';
z1.incrementAge();
cout << "\n\nDay: " << ++day << endl;
cout << "\nYou have $" << z1.getAmount() << " in the bank";
z1.Events();
cout << "\n\nWould you like to purchase an adult animal? ";
cin.get(loopPurchase);
cin.ignore(INT_MAX, '\n');
if(loopPurchase == 'Y' || loopPurchase == 'y')
{
cout << "\n\nA: Tiger" << endl;
cout << "B: Penguin" << endl;
cout << "C: Turtle" << endl;
cout << "\nPlease choose from the animals listed above: ";
cin.get(loopChoice);
cin.ignore(INT_MAX, '\n');
if(loopChoice == 'A' || loopChoice == 'a')
{
cout << "\n\nYou have chosen to purchase a Tiger" << endl;
Tiger tLoop(3, 10000, 1, 50, 2000);
z1.insertTiger(tLoop);
z1.subtractAmount(10000);
}
else if(loopChoice == 'B' || loopChoice == 'b')
{
cout << "\n\nYou have chosen to purchase a Penguin" << endl;
Penguin pLoop(3, 1000, 5, 10, 100);
z1.insertPenguin(pLoop);
z1.subtractAmount(1000);
}
else if(loopChoice == 'C' || loopChoice == 'c')
{
cout << "\n\nYou have chosen to purchase a Turtle" << endl;
Turtle trLoop(3, 100, 10, 5, 5);
z1.insertTurtle(trLoop);
z1.subtractAmount(100);
}
}
z1.calculateRevenue();
cout << "\n\nYour daily revenue is $" << z1.getRevenue();
//z1.setAmount((z1.getAmount()) + (z1.getProfit()));
z1.resetRevenue();
cout << "\n\nEnd of Day: " << day << ". Would you like to continue? (Enter yes or no): ";
cin.get(continueGame);
cin.ignore(INT_MAX, '\n');
if (continueGame == 'y' || continueGame == 'Y')
{
cout << "\nGame will continue. Proceeding to next day." << endl << endl;
}
else
{
cout << "\n\nYou have chosen to quit the game. Game will now exit." << endl << endl;
playGame = false;
}
}
return 0;
}
The code is huge. I have not reviewed everything.
In Zoo, you define your Animal arrays as:
Tiger **arrayTiger;
Penguin **arrayPenguin;
Turtle **arrayTurtle;
I don't know why a double pointer. Just *arrayTiger, etc. would work. You must also change the Insert method. Instead of assigning &t, just use t.
There are other improvements to make.
In Zoo, the insertTiger (etc), should also subtract amount. You always subtract the amount after calling insert, and you already know the price.
Your wrote almost the same code 3 times for the three animals when initializing arrays of animals. You could check if the input is 1 or 2 (to validate) and then insert animals in a for loop.
Finally. You are not reusing almost anything. You have a lot of repeated code for tigers, turtles and penguins.
Your code is too big as mentioned in the previous answer because of which I couldn't go through the entire code, but the segmentation fault you encounter could be because of the following piece of code :
void Zoo::calculateRevenue()
{
for (int i = 0; i < sizeTiger; i++)
{
revenue += (arrayTiger[i]->getPayoff());
}
for (int i = 0; i < sizePenguin; i++)
{
revenue += (arrayPenguin[i]->getPayoff());
}
for (int i = 0; i < sizeTurtle; i++)
{
revenue += (arrayPenguin[i]->getPayoff());
}
}
If you see here, in the third "for loop", you run the loop till sizeTurtle but are using the arrayPenguin for it. I think this is a mistake and what you wanted to do was something of this sort :
for (int i = 0; i < sizeTurtle; i++)
{
revenue += (arrayTurtle[i]->getPayoff());
}
That being said, they're could be other problems in the code that i am not aware of, but this certainly seems like a candidate to cause a crash in the program.

Deleting an element from a vector

I am new to C++ and I am writing a program that is supposed to simulate a colony of bunnies. The program will be able to add them, give them names, ages, colors, etc. Right now I have a working program that will add bunnies after each pass and age them by 1. How could I make the program delete a bunny once the bunny reaches age 10.
The code:
enter code here
#include <iostream>
#include <ctime>
#include <vector>
#include <cstdlib>
#include <limits>
using namespace std;
const int POSSIBLE_NAMES = 18;
const int POSSIBLE_COLORS = 4;
static std::string possibleNames[] ={
"Jen",
"Alex",
"Janice",
"Tom",
"Bob",
"Cassie",
"Louis",
"Frank",
"Bugs",
"Daffy",
"Mickey",
"Minnie",
"Pluto",
"Venus",
"Topanga",
"Corey",
"Francis",
"London",
};
static std::string possibleColors[] ={
"White",
"Brown",
"Black",
"Spotted"
};
struct Bunny
{
public:
string name;
int age;
string color;
char sex;
Bunny(){
setSex();
setColor();
setAge(0);
setName();
}
int randomGeneration(int x){
return rand() % x;
srand (time(NULL));
}
void setSex()
{
int randomNumber = randomGeneration(2);
( randomNumber == 1 ) ? sex = 'm' : sex = 'f';
}
char getSex()
{
return sex;
}
void setColor()
{
int randomNumber = randomGeneration(POSSIBLE_COLORS);
color = possibleColors[randomNumber];
}
string getColor()
{
return color;
}
void setAge(int age)
{
this->age = age;
}
int getAge()
{
age++;
return age;
}
void setName()
{
int i = randomGeneration(POSSIBLE_NAMES);
name = possibleNames[i];
}
string getName()
{
return name;
}
void deleteBunny(){
if (age > 10){
cout << getName() << " has died" << endl;
}
}
void printBunny()
{
cout << "Name: " << getName() << endl;
cout << "Sex: " << getSex() << endl;
cout << "Color: " << getColor() << endl;
cout << "Age: " << getAge() << endl;
}
};
int main()
{
vector< Bunny > colony;
char quit = '\0';
do
{
// Add more bunny
for (int i = 0; i < 5; i++)
{
colony.push_back(Bunny());
}
// Print all the bunny
for (int i =0; i < colony.size(); i++)
{
colony[i].printBunny();
colony[i].deleteBunny();
cout << endl;
}
cout << "You have a total of " << colony.size() << " bunnies\n";
cout << "Press a key to add more bunny, q to quit\n";
quit = cin.get();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// repeat
} while (quit != 'q' && quit != 'Q');
return 0;
}
You have to use erase remove idiom:
std::erase(colony.remove_if( colony.begin(), colony.end(),
[] (bunny& oldBunny){ return oldBunny.age > 10; } ), colony.end());
Each pass you need to check if been is over ten and delete them from the vector.
vector< Bunny > colony;
do
{
for(int i = 0; i < colony.size(); i++){
if(colony[i].getAge() > 10) {
// Call your delete function
colony[i].deleteBunny();
// Delete from vector
colony.erase(colony.begin() + i);
// Shift vector back down
i--;
}
}
// Add more bunny
// Rest of code
}

Hash Tables seg fault

So I'm really not sure what is causing the seg fault but I have a feeling that it has something to do with hashTables since the debugger shows it seg faults right at this line its involved with.
Here is the code that is causing the seg fault
//Constructor for hashtable
HashTable::HashTable()
{
for(int i = 0; i < 10; i++)
{
hashTable[i] = new Movie;
hashTable[i]->title = "empty";
hashTable[i]->year = 0;
hashTable[i]->next = NULL;
}
}
//destructor for hashtable
HashTable::~HashTable()
{
}
// this will take a string and convert the letters to hash numbers then add them all together and divide by the hash table size to get a index
int HashTable::initHash(std::string in_title)
{
int hashT = 0;
int index = 0;
for(int i = 0; i < in_title.length(); i++)
{
hashT = hashT + (int)in_title[i];
std::cout << "hash = " << hashT << std::endl;
}
index = hashT % 10;
std::cout << "index = " << index << std::endl;
return index;
}
//This is where we will be inserting a new Movie into the hashtable,
//it will first use initHash to find the number of where it should go in the hash and then from there add it to the hashtable
void HashTable::insertMovie(std::string in_title, int year)
{
int index = initHash(in_title);
std::cout << "index = " << index << std::endl;
if (hashTable[index]->title == "empty") // *** seg faults right here ***
{
hashTable[index]->title = in_title;
hashTable[index]->year = year;
}
else
{
Movie* Ptr = hashTable[index];
Movie* n = new Movie;
n->title = in_title;
n->year = year;
n->next = NULL;
while(Ptr->next != NULL)
{
Ptr = Ptr->next;
}
Ptr->next = n;
}
}
in each of my functions containing hashTables[index] it seg faults but I'm not exactly sure why, the index comes back with a number that should work. does anyone know why this would happen?
edit: Ok here is the two classes that matter from my header file
struct Movie{
std::string title;
int year;
Movie *next;
Movie(){};
Movie(std::string in_title, int in_year)
{
title = in_title;
year = in_year;
}
};
class HashTable
{
public:
HashTable();
~HashTable();
void insertMovie(std::string in_title, int year);
int initHash(std::string in_title);
int NumberofItemsInIndex(int index);
Movie* findMovie(std::string in_title/*, int *index*/);
void deleteMovie(std::string in_title);
void printInventory();
void PrintItemsInIndex(int index);
protected:
private:
Movie **hashTable;
};
edit 2: Here is the main() function
int main(int argc, char * argv[])
{
// Declarations
int input; // Declaring an input for the menu
bool quit = false; // Bool for the menu
//string title; // input value for certain actions
//int year; // input value for certain actions
HashTable *ht;
//int index;
//readFileIntoHash(ht, argv[1]);
while(quit != true)
{
displayMenu(); // Displays the main menu
cin >> input;
//clear out cin
cin.clear();
cin.ignore(10000, '\n');
switch (input)
{
// Insert a movie
case 1:
{
string in_title;
int year;
cout << "Enter Title:" << endl;
cin >> in_title;
cout << "Enter Year:" << endl;
cin >> year;
ht -> insertMovie(in_title, year);
break;
}
// Delete a movie
case 2:
{
string in_title2;
cout << "Enter Title:" << endl;
cin >> in_title2;
ht -> deleteMovie(in_title2);
break;
}
// Find a movie
case 3:
{
string in_title3;
cout << "Enter Title:" << endl;
cin >> in_title3;
ht -> findMovie(in_title3);
break;
}
// Print table contents
case 4:
ht -> printInventory();
break;
case 5:
cout << "Goodbye!" << endl;
quit = true;
break;
// invalid input
default:
cout << "Invalid Input" << endl;
cin.clear();
cin.ignore(10000,'\n');
break;
}
}
return 0;
}
void displayMenu()
{
cout << "======Main Menu=====" << endl;
cout << "1. Insert movie" << endl;
cout << "2. Delete movie" << endl;
cout << "3. Find movie" << endl;
cout << "4. Print table contents" << endl;
cout << "5. Quit" << endl;
return;
}
I added displayMenu() for clarity's sake.
Modify the class definition:
class HashTable
{
public:
HashTable();
~HashTable();
void insertMovie(std::string in_title, int year);
int initHash(std::string in_title);
int NumberofItemsInIndex(int index);
Movie* findMovie(std::string in_title/*, int *index*/);
void deleteMovie(std::string in_title);
void printInventory();
void PrintItemsInIndex(int index);
protected:
private:
Movie *hashTable[10]; /*<<-- since your size is fixed use an array*/
};
Also.. since you allocated Movies in the constructor, remember to deallocate them on destructor:
//destructor for hashtable
HashTable::~HashTable()
{
for(int i = 0; i < 10; i++)
{
delete hashTable[i];
}
}
Alternative, use dynamically allocated memory (with your same class definition)
HashTable::HashTable()
{
hashTable = new (Movie*) [10];
for(int i = 0; i < 10; i++)
{
hashTable[i] = new Movie;
hashTable[i]->title = "empty";
hashTable[i]->year = 0;
hashTable[i]->next = NULL;
}
}
and
HashTable::~HashTable()
{
for(int i = 0; i < 10; i++)
{
delete hashTable[i];
}
delete[] hashTable;
}
Additional fix:
modify main function:
int main(int argc, char * argv[])
{
// Declarations
int input; // Declaring an input for the menu
bool quit = false; // Bool for the menu
//string title; // input value for certain actions
//int year; // input value for certain actions
HashTable ht; // <<==== local variable, not a pointer!
... and then replace ht->xxxx(...) for ht.xxxx(...) elsewhere.
hashTable[i] = new Movie; there you allocate memory for Movie
but memory for Movie **hashTable; was not alllocated
try to add hashTable = new Movie *[100]; to constructor
This constructor perhaps:
HashTable::HashTable()
{
hashTable = new (Movie*) [10]; // Allocate memory on the heap for the array
for(int i = 0; i < 10; i++)
{
hashTable[i] = new Movie;
hashTable[i]->title = "empty";
hashTable[i]->year = 0;
hashTable[i]->next = NULL;
}
}
However, there is actually no need have an array of Movie pointers in your hashmap, you could simply have an array of Movie objects instead. Actually, you want a linked list so my bad. Also, I would not write 10 everywhere, rather use a constant so you could change the size later.
When you get this to work, you should write a destructor to avoid memory leaks. Hint: couple each call to new with a call to delete (and new[] with delete[]).

I keep getting the error "The variable 'b' is being used without being initialized, and I'm not sure how to fix it

//Benjamin McKinney
//CSCI 2010-10
//Spring 2015
//PASS 3
//Programmed on Windows 8.1 using Visual C++ 2010 Express
//This program plays the game MasterMind
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
struct Player
{
string Name;
int HighScores[6];
bool CheatOn;
};
struct Board
{
int NumHoles;
int Holes[6];
};
struct Guess
{
int Count;
int NumHoles;
int Holes;
};
void printHighScores(string);
void readHighScore(string);
void updateHighScore(string, int);
string getPlayer();
int getBoard();
void playGame(string);
void menu(string);
int main()
{
Player p;
srand((unsigned int)time(0));
cout << "!!! Benjamin McKinney's Master-MasterMind!!!\n";
cout << "--------------------------------------------\n";
getPlayer();
menu(p.Name);
cout << "Goodbye, " << p.Name << endl;
printHighScores(p.Name);
cout << "----------------------------------------------\n";
cout << "!!! Benjamin McKinney's Master-MasterMind!!!\n";
system("PAUSE");
return 0;
}
void printHighScores(string name)
{
return;
}
void readHighScore(string)
{
return;
}
void updateHighScore(string, int)
{
return;
}
string getPlayer()
{
Player p;
cout << "What is your name?\n";
cin >> p.Name;
cout << "Welcome, " << p.Name << endl;
p.CheatOn = false;
readHighScore(p.Name);
return p.Name;
}
int getBoard()
{
Board b;
cout << "Enter the number of holes you would like: ";
cin >> b.NumHoles;
if(b.NumHoles > 6 || b.NumHoles < 1)
{
cout << "Error! You must pick a number between 1 and 6! Try again!\n";
}
for(int i=0;i<b.NumHoles;i++)
{
b.Holes[i] = rand() % 2 + 1;
}
return b.NumHoles;
}
void playGame(string)
{
Player p;
Board b;
Guess g;
getBoard();
g.Count=0;
for(int i=0;i<b.NumHoles;i++)
{
cout << "Enter your guess for the row\n";
if(p.CheatOn == true)
{
for(int a=0;a<(sizeof(b.Holes)-1);a++)
{
cout << b.Holes[a];
}
}
cout << "Enter your guess for hole " << i << ": ";
cin >> g.Holes;
g.Count++;
}
return;
}
void menu(string)
{
Player p;
char choice;
cout << "Please choose an option below:\n";
cout << "\t P)lay\n\t Q)uit\n\tChoice: ";
cin >> choice;
if(choice == 'P')
playGame(p.Name);
else
if(choice == 'Q')
return;
else`enter code here`
if(choice == 'C')
{
p.CheatOn = true;
playGame(p.Name);
}
}
Ignore the three HighScore functions, but otherwise I can't get this to work... "Run-Time Check Failure #3 - The variable 'b' is being used without being initialized." is the main issue that I'm having. If anyone can help me I would really appreciate it. Thanks!
In the playGame function:
void playGame(string)
{
Player p;
Board b; // <----- uninitialized
// ...
for(int i=0;i<b.NumHoles;i++)
// ^^^^^^^^^^
you use b.NumHoles when you have never initialized b.
I guess you intended that getBoard() would magically have some effect on b but it doesn't. The getBoard function updates a local board but never does anything with it.
To fix this you could change getBoard to return the whole board:
Board getBoard()
{
Board b;
// set up b...
return b;
}
and then inside playGame:
Board b = getBoard();
There's another error just below:
for(int a=0;a<(sizeof(b.Holes)-1);a++)
The sizeof operator gives the size in bytes. You actually want the size in elements, so you need to divide by the element size:
a < (sizeof b.Holes / sizeof b.Holes[0])
I'm not sure what the -1 was meant to be doing either, this would just cause you to not output the last hole.

C++ error LNK2019 and error LNK1120

Hello i am making a tic tac toe game in console.
What's wrong with my code?
I Got linker settings set as console.
code:
// Tic tac Toe
// Plays a tic tac toe game against a npc
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// global constants
const char X = 'X';
const char O = '0';
const char EMPTY = ' ';
const char TIE = 'T';
const char NO_ONE = 'N';
//function prototypes
void instructions();
char askYesNo(string question);
int askNumber(string question, int high, int low =0);
char humanPiece();
char opponent(char piece);
void displayBoard(const vector<char>& board);
char winner(const vector<char>& board);
bool isLegal(const vector<char>& board, int move);
int humanMove(const vector<char>& board, char human);
int computerMove(const vector<char>& board, char computer);
void announceWinner(char winner, char computer, char human);
int main()
{
int move;
const int NUM_SQUARES = 9;
vector<char> board(NUM_SQUARES, EMPTY);
instructions();
char human = humanPiece();
char computer = opponent(human);
char turn = X;
displayBoard(board);
while (winner(board) == NO_ONE)
{
if (turn == human)
{
move = humanMove(board, human);
board[move] = human;
}
else
{
move = computerMove(board, computer);
board[move] = computer;
}
displayBoard(board);
turn = opponent(turn);
}
announceWinner(winner(board), computer, human);
return 0;
}
void instructions()
{
cout << "Welcome to the ultimate man-machine showdown: Tic Tac Toe.\n";
cout << "--I'm gonna cut you in half like a knife and butter like a lightsaber and steel!!!\n\n";
cout << "make your move now by entering a number, 0-8. The number\n";
cout << "corresponds to the desired board position , as illustrated: \n\n";
cout << " 0|1|2 \n";
cout << " ------- \n";
cout << " 3|4|5 \n";
cout << " ------- \n";
cout << " 6|7|8 \n\n";
cout << "Prepare yourself human, the battle is about to begin.\n\n";
}
char askYesNo(string question)
{
char response;
do
{
cout << question << "(y\n): ";
cin >> response;
}while (response != 'y' && response != 'n');
return response;
}
int askNumber(string question, int high, int low)
{
int number;
do
{
cout << question << "(" << low << "-" << high << "): ";
cin >> number;
}while (number > high || number < low);
return number;
}
char humanPiece()
{
char go_first = askYesNo("Do you require the first move?");
if (go_first == 'y')
{
cout << "\n Then take the first move. You will need it.\n";
return X;
}
else
{
cout << "Then I will make the first move.\n";
return 0;
}
}
char opponent(char piece)
{
if (piece == 'X')
{
return X;
}
else
{
return 0;
}
}
void displayBoard(const vector<char>& board)
{
cout << "\n\t" << board[0] << "|" << board[1] << "|" << board[3];
cout << "\n\t" << "-------";
cout << "\n\t" << board[3] << "|" << board[4] << "|" << board[5];
cout << "\n\t" << "-------";
cout << "\n\t" << board[6] << "|" << board[7] << "|" << board[8];
cout << "\n\n";
}
char winner(const vector<char>& board)
{
// all possible winning rows
const int WINNING_ROWS[8][3] = {{0,1,2},
{3,4,5},
{6,7,8},
{0,3,6},
{1,4,7},
{2,5,8},
{0,4,8},
{2,4,6}};
const int TOTAL_ROWS = 8;
// if any winning row has three values wich are the same(and not EMPTY)
// then we have a winner
for (int row = 0; row < TOTAL_ROWS; ++row)
{
if ((board[WINNING_ROWS[row][0]] != EMPTY) && (board[WINNING_ROWS[row][0]] == board[WINNING_ROWS[row][1]]) && (board[WINNING_ROWS[row][1]] == board[WINNING_ROWS[row][2]]))
{
return board[WINNING_ROWS[row][0]];
}
}
//since nobody has won check for a tie (no empty squares left)
if (count(board.begin(), board.end(), EMPTY) == 0)
{
return TIE;
}
//since nobody has won and it isn't a tie, the game ain't over
return NO_ONE;
}
inline bool isLegal(int move, const vector<char>& board)
{
return (board[move] == EMPTY);
}
int humanMove(const vector<char>& board, char human)
{
int move = askNumber("Where will you move?", (board.size() - 1));
while (!isLegal(move, board))
{
cout << "\n That square is already occupied, foolish human.\n" << endl;
int move = askNumber("Where will you move?", (board.size() - 1));
}
cout << "Fine....\n";
return move;
}
int computerMove(vector<char> board, char computer)
{
unsigned int move = 0;
bool found = false;
//if the pc can win on next move I will take that move
while (!found && move < board.size())
{
if (isLegal (move, board))
{
board[move] = computer;
found = winner(board) == computer;
board[move] = EMPTY;
}
if (!found)
{
++move;
}
}
// otherwise if the human can win with the next move that's the move I will make
if (!found)
{
move = 0;
char human = opponent(computer);
while (!found && move < board.size())
{
if (isLegal(move, board))
{
board[move] = human;
found = winner(board) == human;
board[move] = human;
}
if (!found)
{
++move;
}
}
}
// otherwise i'll be moving to the next best square
if (!found)
{
move = 0;
unsigned int i = 0;
const int BEST_MOVES[] = {4,0,2,6,8,1.3,5,7};
// pick best open square
while (!found && i < board.size())
{
move = BEST_MOVES[i];
if (isLegal(move, board))
{
found = true;
}
++i;
}
}
cout << "I shall take square number" << move << endl;
return move;
}
void announceWinner(char winner, char computer, char human)
{
if (winner == computer)
{
cout << winner << "has won!\n";
cout << "As I predicted human, I am triumphant once more!\n";
}
else if (winner == human)
{
cout << winner << "has won" << endl;
cout << "no, no it cannot be! Somehow you tricked me Human!\n";
}
else
{
cout << "It's just a tie, I'll beat you next time! \n";
cout << "You cannot beat me though!";
}
}
The forward declaration of -
int computerMove(const vector<char>& board, char computer);
is different from the actual implementation. ( Misses the const part )
int computerMove(vector<char> board, char computer)