I have an assignment to create a small game
Build a Text Adventure Game which takes user input and performs certain actions.
// At the start of the game the user is given the choice to choose a type of player (1, 2, 3)
// Each type of player starts with below attributes -
// Player 1 - max health = 50, damage = 10, heal = 20
// Player 2 - max health = 75, damage = 25, heal = 10
// Player 3 - max health = 100, damage = 75, heal = 20
problem is when I try to redeclare the object it doesnt change
Player player(0,0,0);
int player_no;
bool gameover=false;
std::cout<<"choose your player !!!";
std::cin>>player_no;
if(player_no==1){
Player player1(50,20,10); //value is not reflected inside while
std::cout<<player.heal; //50
std::cout<<player.health; //20
goto start;
}else if(player_no==2){
Player player(75,10,25); //value is not reflcted inside while
goto start;
}
char command;
start:
while(!gameover){
std::cout<<"what do you want ??? ";
std::cin>>command;
if(command=='D'){
std::cout<<player.health<<"\n"; //uses the default value 0
std::cout<<player.damage<<"\n"; //uses the default value 0
player.TakeDamage(player.damage); //0 is passed
}else if(command=='H') {
player.Heal(player.heal); // 0 is passed
}
How to pass the changed value inside the while ???
Tiny example to illustrate your problem:
int a = 2;
if (a == 2)
{
std::cout << "a is " << a << std::endl;
int a = 3;
std::cout << "a set to " << a << std::endl;
}
std::cout << "a is " << a << std::endl;
This prints:
a is 2
a set to 3
a is 2
Why is a not 3 in the second line? That is because the braces { ... } declare a new scope and the line int a = 3 declares a new a variable that is local to that scope only. The second we leave the if-scope the second a variable dies, and we are left with only the original which still is set to 2.
If we change it to:
int a = 2;
if (a == 2)
{
std::cout << "a is " << a << std::endl;
a = 3;
std::cout << "a set to " << a << std::endl;
}
std::cout << "a is " << a << std::endl;
Then no new a is declared, and the assignment refers to the variable in the outer scope. Now the output is:
a is 2
a set to 3
a is 3
The fix to your code is to do something like this:
Player player(0, 0, 0);
...
if (player_no == 1) {
player = Player(50, 20, 10);
...
}
There are many problem :
1) The name of the variable :
You call player on 1st line and player1 after if (player_no==1){...
2) The scope is not respected :
when you created anew Player player(75,10,25); it doesnt replace the first created Player.
I will prefer use pointer like that (there are infinite way to do it !) :
Player* pPlayer = NULL;
...
if(player_no==1){
pPlayer = new Player(50, 20, 10);
...
if(player_no==2){
pPlayer = new Player(75, 10, 25);
...
if (pPlayer != NULL) {
while(!gameover) {
if (command == 'D') {
pPlayer->Damage();
}
}
delete pPlayer;
}
Hope it helps you !
Related
I am receiving an error that says "core dumped" when running my program. I'm a beginner, and I'm not sure how to fix it. It prints out correctly up until part 1-4
int main() {
string unshuffledDeck = "AAAA222233334444555566667777888899990000JJJJQQQQKKKK";
string shuffledDeck = "";
srand(time(0));
for ( ; unshuffledDeck.length() != 0 ; ){
// (1-2a) Generate a random number between 0 and the current unshuffled deck size
minus 1 to select the card we are going to move
int randomIndex = rand() % (unshuffledDeck.length() - 1);
shuffledDeck = shuffledDeck + unshuffledDeck[randomIndex];
unshuffledDeck.erase(randomIndex, 1);
} // end for
string playerHand = "";
string dealerHand = "";
// (1-4b) Deal the cards by moving them from the deck to the player and dealer hands
do {
playerHand += shuffledDeck[0];
shuffledDeck.erase(0,1);
} while((playerHand.length() - 1) < 2);
do {
dealerHand += shuffledDeck[0];
shuffledDeck.erase(0,1);
} while((dealerHand.length() - 1) < 2);
// (1-4c) Print out the deck and hands to verify cards moved in the appropriate order
cout << shuffledDeck << endl;
cout << "player: " << playerHand << endl;
cout << "dealer: " << dealerHand << endl;
}
int randomIndex = rand() % (unshuffledDeck.length() - 1); this cuses this core dump when unshuffledDeck.length() equals to 1 division by zero is hapening. So you should cange it to int randomIndex = rand() % unshuffledDeck.length(); because modulo operator a % b returns value from -b exclusive to b exclusive e.g. (-b,b) in your case all numbers are positive so it returns value from zero inclusive to b exclusive e.g. [0,b)
Below is the first part of a function meant to analyze a Tic-Tac-Toe board.
The aboutToWin() function returns true if a player is "about to win," ie has two in a row. The board is represented such that if player 1 has made a move in that square, the value in the 3x3 matrix will be 1. Player 2 will be -1. If no one has made a move, it will be 0.
The part that I put in this question is the first part, which checks the negative diagonal (ie positions 1, 5, and 9 on the board).
bool aboutToWin(int squares[3][3], int& position, bool p1)
{
// The value you are looking for is 2 for p1 and -2 for p2
int check = 2;
if (!p1)
{
check = -2;
}
// Check negative diagonal
int sum = 0;
// Go through negative diagonal
for (int i = 0; i < 3; i++)
{
sum += squares[i][i];
// Saves the position of the last checked 0 square
// If check passes, this will be the winning square
// If not, it will get handled and overwritten
if (squares[i][i] == 0)
{
// Calculates position from i
position = 1 + (4 * i);
std::cout << "\nPosition: " << position << "\n";
}
}
// If this diagonal added to check, stop the function and return now
if (sum == check)
return true;
...
}
This is the code that I'm running from the main() function to test this functionality:
int p;
std::cout << p;
int a3[3][3] = {{1, 0, 1},
{0, 0, 0},
{0, 0, 1}};
std::cout << "\nShould be 1, 5: " << aboutToWin(a3, p, true) << ", " << p;
The output is the following:
0
Position: 5
Should be true, 5: 1, 0
Why is this? I can see that the value gets changed during the function, but it doesn't transfer out of the function.
The problem with using:
std::cout << "\nShould be 1, 5: " << aboutToWin(a3, p, true) << ", " << p;
is that the order of the evaluation of the arguments is not defined unless you use C++17.
It looks like p is evaluated first in your setup before the call to aboutToWin.
Separate the calls.
auto ret = aboutToWin(a3, p, true);
std::cout << "\nShould be 1, 5: " << ret << ", " << p;
int gas;
// Input Code
int user_code;
std::cout << std::endl;
std::cout << "Please enter the Code: ";
std::cin >> user_code;
std::cout << "The value you entered is " << user_code;
std::cout << std::endl;
int array1[16] = { 42011, 42017, 42029, 42045,
42091, 42101, 34001, 34005,
34007, 34009, 34011, 34015,
34033, 10001, 10003, 24015 }; // 0.2387 (23.87%)
int array2[45] = { 11001, 24003, 24510, 24005, 24009,
24013, 24017, 24019, 24021, 24025,
24027, 24029, 24031, 24033, 24035,
24037, 24041, 24043, 51510, 51013,
51043, 51047, 51600, 51059, 51610,
51061, 51069, 51630, 51099, 51107,
51683, 51685, 51153, 51157, 51177,
51179, 51187, 51840, 54003, 54027,
54037, 54065, 42001, 42055, 42133 }; //0.2710 (27.10%)
int * array1_search;
array1_search = std::find(array1, array1+ 16, user_code);
int * array2_search;
array2_search = std::find(array2, array2 + 45, user_code);
if (array1_search != array1+ 16) {
std::cout << "Codefound in Array1: " << *array1_search << '\n';
gas= 0.2387;
}
else if (array2_search != array2_search + 45) {
std::cout << "Code found in Array2: " << *array2_search << '\n';
gas= 0.2710;
}
else {
std::cout << "Not found \n";
gas= 0.1506;
}
Above is my current code. I am trying to have the user input a variable user_code value and then iterate over the two arrays array1[16] and array2[45]. If the user input value is on the first array1 I want to assign gas 0.2387 and if the input value is on the other array2 I want to assign gas 0.2710, and if it is not within any array gas should be 0.1506.
So basically I want to assign a value depending on which array the user's input is contained in. I am very new to c++, what is the best way to go about this?
It seems to work fine if I enter a number that is within array1 or array2 and it correctly identifies that is found in array1 or array2. The problem is when I enter a number I know is not within either array to trigger the else statement it identifies it as being in array2. For example, when I enter 12345 as a user_code it says "Code found in Array2: 0". I know 12345 is not contained in array2 and I do not understand why *array2_search is assigned 0. What can I do to fix this so if a user_code is entered that is not contained within array1 or array2 it goes to the else statement?
else if (array2_search != array2_search + 45) {
Should be
else if (array2_search != array2 + 45) {
or better using std::end of C++11:
if (array1_search != std::end(array1)) {
else if (array2_search != std::end(array2)) {
And int gas; => double gas; if you want to be able to store floating point values, not just integers (0.2387 and 0.2710 would give integer 0).
Using standard containers and newer c++ features if you have C++11 minimum you can then do something like this:
int main() {
// Use Constants Instead of "Hard Coded Values"
// If you noticed these are not even needed.
// const unsigned code1 = 16;
// const unsigned code2 = 45;
// Made gas a float instead of an int due to the decimal values
// I also initialized it with the default value if the code is
// not found in either container.
float gas = 0.1506f; // Default Price If Not Found
// created your first array as a const std::vector<int> and
// used its initializer list to populate its contents: this vector
// can not be modified: remove the const if this container
// will need to have entries added in the future.
const std::vector<int> arr1 { 42011, 42017, 42029, 42045,
42091, 42101, 34001, 34005,
34007, 34009, 34011, 34015,
34033, 10001, 10003, 24015 }; // 0.2387 (23.87%)
// did the same for the second array
const std::vector<int> arr2 { 11001, 24003, 24510, 24005, 24009,
24013, 24017, 24019, 24021, 24025,
24027, 24029, 24031, 24033, 24035,
24037, 24041, 24043, 51510, 51013,
51043, 51047, 51600, 51059, 51610,
51061, 51069, 51630, 51099, 51107,
51683, 51685, 51153, 51157, 51177,
51179, 51187, 51840, 54003, 54027,
54037, 54065, 42001, 42055, 42133 }; //0.2710 (27.10%)
// No changes made here same basic user I/O.
int user_code = 0;
std::cout << "Please enter the Code: ";
std::cin >> user_code;
std::cout << "The value you entered is " << user_code;
std::cout << "\n";
// Created 2 flags for later.
bool b1found = false;
bool b2found = false;
// auto for loop ranged based.
for ( auto code : arr1 ) {
if ( code == user_code ) {
b1found = true; // Set flag
gas = 0.2387f; // Set new gas
// Output code & gas
std::cout << "Code found in Arr1: " << code << '\n';
std::cout << "gas = " << gas << '\n';
}
}
for ( auto code : arr2 ) {
if ( code == user_code ) {
b2found = true; // set flag
gas = 0.2710f; // set gas
// output code & gas
std::cout << "Code found in Arr2: " << code << '\n';
std::cout << "gas = " << gas << '\n';
}
}
// If code not found in either output "not found" and display default gas
if ( !b1found && !b2found ) {
std::cout << "Not found\n";
std::cout << "gas = " << gas << '\n';
}
std::cout << "\nPress any key and enter to quit." << std::endl;
char c;
std::cin >> c;
return 0;
}
You can even simplify this a little more by removing the two bool flags. We know that if a value is found in arr1 or arr2 that the gas value will be changed, So all we really have to do is check to see if it has been changed.
// auto for loop ranged based.
for ( auto code : arr1 ) {
if ( code == user_code ) {
gas = 0.2387f; // Set new gas
// Output code & gas
std::cout << "Code found in Arr1: " << code << '\n';
std::cout << "gas = " << gas << '\n';
}
}
for ( auto code : arr2 ) {
if ( code == user_code ) {
gas = 0.2710f; // set gas
// output code & gas
std::cout << "Code found in Arr2: " << code << '\n';
std::cout << "gas = " << gas << '\n';
}
}
const float defaultGas = 0.1506;
// If code not found in either output "not found" and display default gas
if ( gas == defaultGas ) {
std::cout << "Not found\n";
std::cout << "gas = " << gas << '\n';
}
I'm fairly new to coding in c++, and I'm working on a menu system for a text RPG I'm working on. You can view your stats, view your inventory, view item stats, and discard items. However, after the item is discarded, which ever slot the discarded item was in remains empty, and in a game it doesn't make sense to have object 2 be discarded, and then what was object number 3 remain object 3. Object 3 should become 2. So I was wondering how I could do this with my current code.
#include <iostream>
#include <string>
using namespace std;
bool running = 1;
void titleFunc();
void newGameFunc();
void menuFuncNav();
void menuFuncInfo();
void menuFuncItems();
string itemNames[] = {"Iron Short Sword", "Iron Long Sword", "Iron Two-Handed Sword", "Iron War Hammer", "Iron Mace", "Iron Dagger", "Wooden Staff", "Wooden Shield", "Oak Shortbow", "Oak Longbow", "Oak Crossbow", "Hard Leather Chest-Piece", "Hard Leather Leggings", "Soft Leather Chest-Piece", "Soft Leather Leggings", "Cloak"};
short playerItemCount = 0;
int userInput = 0;
int talkInput = 0;
int playerInfo[3];
int playerLocation = 0;
const int MAX_ITEMS = 100;
int playerItems[MAX_ITEMS][11];
void menuFuncItems()
{
int i = 0;
for( int i = 0; i < playerItemCount; i++ )
{
cout << i+1 << ": ";
cout << itemNames[playerItems[i][0]];
cout << endl;
}
cin >> i;
if( playerItems[i - 1][1] == 1 )
{
cout << "Press 1 to view stats." << endl;
cout << "Press 2 to equip." << endl;
cout << "Press 3 to discard." << endl;
cin >> userInput;
cout << endl;
if( userInput == 1 )
{
cout << "Name: " << itemNames[playerItems[i - 1][0]] << endl;
cout << "Physical Attack:" << playerItems[i - 1][2] << endl;
}
else if( userInput == 2 )
{
}
else
{
playerItems[i - 1][0]--;
playerItems[i - 1][0]--;
cout << "Item discarded." << endl;
}
}
So in this code, the player discards the item in the first inventory slot.
Iron Longsword
Wooden shield
Hard Leather Chest-Piece
Hard Leather Leggings
Should become, after item 1 is discarded:
Wooden Shield
Hard Leather Chest-Piece
Hard Leather Leggings
Sorry if I did something wrong in the post. This is my first post on this site. :) Thank you.
For example you can do the following
for ( int ( *p )[11] = playerItems + i; p != playerItems + playerItemCount; ++p )
{
std::copy( *p, *p + 11, *( p - 1 ) );
}
--playerItemCount;
If you replace
int playerItems[MAX_ITEMS][11];
with
std::vector<int> playerItems; // assuming you store all the items for a given player here
or
std::vector<std::vector<int>> playerItems; // if you want the 2D array for whatever implementation you have
Then erasing an element is as simple as calling playerItems.erase(it); (where it is an iterator "pointing" to the element you want to remove.
Alternatively, if you want a faster insertion/removal (but slower random access), you can use std::list. If you really want to have fun, you can store them in a std::map with the name of the item as the key (instead of using an index to make to the item name string in another array).
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
This is the driver code provided by my instructor, It isn't meant to be edited by me.
PlayingCardTest.cpp:
#include <iostream>
#include "PlayingCard.h"
PlayingCard makeValidCard(int value, int suit);
int main()
{
// Create a playing card
PlayingCard card1;
// Test the default constructor and GetCardCode
std::cout << "Testing default constructor. Expect card code to be 00\n card code is :";
std::cout << card1.getCardCode() << std::endl << std::endl;
// Test the setter and getter
std::cout << "Seting card to 'AH' using SetValue and SetSuit" << std::endl;
card1.setCard('A', 'H');
std::cout << "GetValue returns :" << card1.getValue() << std::endl;
std::cout << "GetSuit returns :" << card1.getSuit() << std::endl << std::endl;
// Test overloaded constructor
PlayingCard tenOfSpades('T', 'S');
std::cout << "Testing overloaded constructor. Expect card code to be TS\n card code is :";
std::cout << tenOfSpades.getCardCode() << std::endl << std::endl;
// Test IsValid with valid cards
std::cout << "Testing valid card codes.\n"
<< "Expect isValid to return true for all (except perhaps Jokers.)"
<< std::endl;
// Create and test valid cards
int validCards = 0; // cards that return true for IsValid
int invalidCards = 0; // cards that return false for IsValid
// Create and test four suits plus the jokers
for(int suit = 1; suit <= 5; suit++)
{
// Create and test ace, 2 - 9, Jack, Queen, and King
for(int value = 1; value <= 13; value++)
{
PlayingCard aCard = makeValidCard(value, suit);
std::cout << "Card Code: " << aCard.getCardCode() << " IsValid :";
if (aCard.isValid())
{
validCards++;
std::cout << "true" << std::endl;
}
else
{
invalidCards++;
std::cout << "false" << std::endl;
}
// suit 5 is just for creating the two Jokers
if (suit == 5 && value >= 2)
break;
}
}
std::cout << "IsValid returned false for " << invalidCards << " card codes" << std::endl;
std::cout << "IsValid returned true for " << validCards << " card codes" << std::endl;
std::cout << std::endl;
// Test IsValid with invalid cards
// Create and test invalid cards
std::cout << "Testing invalid card codes; isValid should return false for all." << std::endl;
validCards = 0;
invalidCards = 0;
// Loop through all possible ASCII character codes for card codes
for(int suit = 0; suit <= 255; suit++)
for(int value = 0; value <= 255; value++)
{
// Only check card codes that are not valid
PlayingCard aCard = makeValidCard(value, suit);
if (aCard.getCardCode() == "00")
{
if (aCard.isValid())
{
std::cout << "value :" << value << " suit :" <<suit << " IsValid :";
std::cout << "true" << std::endl;
validCards++;
}
else
{
invalidCards++;
}
}
}
std::cout << "IsValid returned false for " << invalidCards << " card codes" << std::endl;
std::cout << "IsValid returned true for " << validCards << " card codes" << std::endl;
return 0;
}
/******************************************************/
/* Test Functions */
/******************************************************/
PlayingCard makeValidCard(int iValue, int iSuit)
{
char value = '0';
char suit = '0';
switch (iValue)
{
case 1:
value = 'A';
break;
case 10:
value = 'T';
break;
case 11:
value = 'J';
break;
case 12:
value = 'Q';
break;
case 13:
value = 'K';
break;
default:
if ((iValue >= 2) && (iValue <= 9))
value = '0' + iValue;
break;
}
switch (iSuit)
{
case 1:
suit = 'D';
break;
case 2:
suit = 'S';
break;
case 3:
suit = 'C';
break;
case 4:
suit = 'H';
break;
// Special case for the Joker
case 5:
if(iValue == 1)
{
value = 'Z';
suit = 'B';
}
else if(iValue == 2)
{
value = 'Z';
suit = 'R';
}
else
{
value = '0';
suit = '0';
}
break;
}
PlayingCard testCard(value, suit);
return testCard;
}
This is my header file, PlayingCard.h:
#ifndef PLAYINGCARD_H_INCLUDED
#define PLAYINGCARD_H_INCLUDED
class PlayingCard
{
private:
char suit, value;
public:
PlayingCard(){suit = '0'; value = '0';}
PlayingCard(char myValue, char mySuit);
char getValue() {return value;}
char getSuit() {return suit;}
std::string getCardCode();
bool setCard(char myValue, char mySuit);
bool isValid();
#endif // PLAYINGCARD_H_INCLUDED
And this is my class implementation file, PlayingCard.cpp:
#include "PlayingCard.h"
PlayingCard::PlayingCard (char myValue, char mySuit)
{
char aValue[13] ('2','3','4','5','6','7','8','9','T','J','Q','K','A'))
char aSuit[4] {'D','H','C','S']
for(count = 0; count <= 12; count++)
{
if (myValue = aValue[count])
{
for (count2 = 0; count2 <= 3; count2++)
{
if (mySuit = aSuit[count2++])
{
suit = mySuit;
value = myValue;
}
}
}
}
}
bool PlayingCard::setCard(char myValue, char mySuit)
{
char aValue[13] ('2','3','4','5','6','7','8','9','T','J','Q','K','A'))
char aSuit[4] {'D','H','C','S']
for(count = 0; count <= 12; count++)
{
if (myValue = aValue[count])
{
for (count2 = 0; count2 <= 3; count2++)
{
if (mySuit = aSuit[count2++])
{
suit = mySuit;
value = myValue;
}
else
{
return false;
}
}
}
}
}
string PlayingCard::getCardCode()
{
return suit + value;
}
bool PlayingCard::isValid()
{
char aValue[13] ('2','3','4','5','6','7','8','9','T','J','Q','K','A'))
char aSuit[4] {'D','H','C','S']
for(count = 0; count <= 12; count++)
{
if (myValue = aValue[count])
{
for (count2 = 0; count2 <= 3; count2++)
{
if (mySuit = aSuit[count2++])
{
return true;
}
else
{
return false;
}
}
}
}
}
And this is the compiler errors I'm getting. I'm not sure what to do, it looks like they are in the file I shouldn't edit. I would really appreciate help you can give.
PlayingCardTest.cpp|103|error: 'PlayingCard PlayingCard::makeValidCard(int, int)' cannot be overloaded|
PlayingCardTest.cpp|5|error: with 'PlayingCard PlayingCard::makeValidCard(int, int)'|
PlayingCardTest.cpp|169|error: expected '}' at end of input|
PlayingCardTest.cpp|169|error: expected unqualified-id at end of input|
||=== Build finished: 4 errors, 0 warnings ===|
You are missing }; at the end of your header file.
First round of comments:
Style nit: order sections "public", "protected", then "private". Private section should not go before public. This is not technically required, but is fairly standard practice.
Style nit: declare each variable using a separate statement, each on its own line. Using commas is a good way to get in trouble (e.g. when declaring pointer types) and is poor style.
Use an initialization list in the constructor rather than using the assignment operator.
You should include "<string>" in your header to use std::string.
Second round of comments:
You are initializing your arrays weirdly; you should use {} as the brackets.
You do not need to specify the size of the arrays in the initialization.
Style nit: do not use magic constants like "12" in your code. Instead, assign them to a variable such as value_length or value_count, and use the named variable.
Did you mean to do an equals comparison ("==") or an assignment ("=") in your if-statement? If you meant to do an assignment, you should probably move it outside of the if.
Third round of comments:
You unnecessarily duplicate code between your non-default constructor and your setCard function. You should be able to share code between those two functions. Since setCard is not a virtual function, you should be able to simply call it from your constructor.
Your setCard logic seems fairly complicated. Most "set" functions are much more trivial than that. You should consider adding documentation explaining the logic of what it is trying to do.
The "getValue()", "getCardCode()", "getSuit()", and "isValid()" functions should be declared "const".
Fourth round of comments:
Since your professor does "PlayingCard card = makeValidCard(....)", it is clear that he wants your card class to support assignment. Since your "setCard()" function and your non-default constructor do something other than simply set the attributes, it would make sense to provide a "PlayingCard& operator=(const PlayingCard&);" assignment operator as well as a "PlayingCard::PlayingCard(const PlayingCard&)" copy constructor. If you do not provide these, it is good practice to add a comment to the effect that copying using the default assignment / copy has been intentionally allowed.