Problem with getting the correct player output - c++

i was creating a tictactoe game and for the player vs player feature of the game I cant seem to wrap my head around getting the player symbols the correct way around.
I'm not really able to provide the minimum amount of code, as it would be my entire program, so I have grabbed the function. I belive it is something to do with the conditional operator but cant figure out what.
but some guy provided a compilable example for me :)
#include <iostream>
#include <string>
/* MOCK */
void print() {};
bool win() { return false; };
bool tie() { return false; };
void player_move() {};
void player_move2() {};
char player, player2;
std::string playerName, player2Name;
/********/
void pvp() {
while (true) {
std::cout << "Player 1 Name: ";
std::cin >> playerName;
std::cout << "Player 2 Name: ";
std::cin >> player2Name;
std::cout << "Which symbol (Player 1: X or player 2: O) goes first? ";
std::cin >> player;
if (player == 'X' || player == 'O') {
break;
}
}
player2 = player == 'O' ? 'X' : 'O';
if (player == 'O') {
player_move2();
}
print();
while (true) {
std::cout << playerName << "'s turn to make a move\n";
player_move();
print();
if (win()) {
std::cout << playerName << " wins!\n";
return;
} else if (tie()) {
std::cout << "Tie!\n";
return;
}
std::cout << player2Name << "'s turn to make a move\n";
player_move2();
print();
if (win()) {
std::cout << player2Name << " wins!\n";
return;
} else if (tie()) {
std::cout << "Tie!\n";
return;
}
}
}
int main() {
pvp();
}

EXPLANATION
There are some patterns in your code, e.g. "making a move":
std::cout << playerName << "'s turn to make a move\n";
player_move();
print();
if (win()) {
std::cout << playerName << " wins!\n";
return;
} else if (tie()) {
std::cout << "Tie!\n";
return;
}
Which is the same for player 1 and player 2, except that you call player2_move(), and display the name of player 2.
Your second loop can then be simplified as
while(true) {
// do_player1_move
// do_player2_move
}
You now come about the problem that the loop will always begin with player 1. To solve this, you're trying to do_player2_move before the loop, if player 2 shall start.
if (player == 'O') {
// do_player2_move
}
while(true) {
// do_player1_move
// do_player2_move
}
However, in your code you only call player2_move(), instead of the entire pattern "making a move" for player 2.
SOLUTION
Therefore, adjusting
if (player == 'O') {
player_move2();
}
to
if (player == 'O') {
std::cout << player2Name << "'s turn to make a move\n";
player_move2();
print();
if (win()) {
std::cout << player2Name << " wins!\n";
return;
} else if (tie()) {
std::cout << "Tie!\n";
return;
}
}
should solve your problem

Related

Calling a function multiple times but it prints only once

I'm running the following code:
#include <iostream>
using namespace std;
string response(bool isMale, bool isTall)
{
if (isMale && isTall) {
cout << "MALE AND TALL" << endl;
}
else if (isMale || isTall) {
cout << "MALE OR NOT TALL" << endl;
}
else {
cout << "ELSE" << endl;
}
}
int main()
{
response(true, true);
response(false, true);
response(false, false);
return 0;
}
the output is the following:
MALE AND TALL
Process returned -1073740940 (0xC0000374) execution time : 1.460 s
Press any key to continue.
Why isn't the output?:
MALE AND TALL
MALE OR NOT TALL
ELSE
A different forum post hinted at a global value not being reset. I don't really know what to make of that.
I would appreciate any help
void response(bool isMale, bool isTall){
if (isMale && isTall) {
cout << "MALE AND TALL" << endl;
}
else if (isMale || isTall ){
cout << "MALE OR NOT TALL" << endl;
}
else {
cout << "ELSE" << endl;
}
}
You need to change function return type "string" to "void".

How to return a value from a class to main

I am trying to build a simple dungeon crawl and am stuck at the battle. The damage taking is working but I cannot return the new health value so that it decreases past the initialized value. Every time the l;oop repeats it returns to the initial value. The same with treasure. What gives? How can I return a value from a member function to main?
#include <iostream>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
class monster
{
public:
int fight()
{
}
};
class chest
{
int loot()
{
}
};
class movement
{
public:
char wasd()
{
char mv;
char up = 'w';
char left = 'a';
char right = 'd';
char down = 's';
cout << "\nMove using w for (up), a for (left), d for (right), and s for (down).\n\n";
mv = _getch();
if (mv == up)
{
cout << "You have moved up 1 space.\n";
}
else if (mv == left)
{
cout << "You have moved left 1 space.\n";
}
else if (mv == right)
{
cout << "You have moved right 1 space.\n";
}
else if (mv == down)
{
cout << "You have moved down 1 space.\n";
}
else
{
cout << "it didn't work.";
}
return 0;
}
};
class random_enc
{ public:
int treasure;
int health = 12;
public:
int encounter(int)
{
int randnumber = rand() % 5 + 1;
treasure = 0;
if (randnumber == 1)
{
cout << "You have been attacked!!! You lose 1 hitpoint." << endl;
health = --health;
cout << "Hitpoints remaining: " << health << endl;
return health;
}
else if (randnumber == 2)
{
cout << "You found treasure!" << endl;
treasure = ++treasure;
cout << "Treasure collected: " << treasure << endl;;
return random_enc::treasure;
}
else if (randnumber == 3)
{
return health;
}
else if (randnumber == 4)
{
cout << "You step on a trap and take damage!! You lose 1 hit point.\n" << "Good bye." << endl;
health = --health;
cout << "Hitpoints remaining: " << health << endl;
}
return health;
}
};
int main()
{
string name;
cout << "Welcome to the dungeon, enter your name:\n";
cin >> name;
cout << "\nGood luck in the dungeon " << name << "\n";
int health = 12;
while (health != 0)
{
movement mvmt;
random_enc random;
mvmt.wasd();
random.encounter(health);
}
cout << "You have been killed. Goodbye.\n";
return 0;
}
I replaced the argument health on the encounter function in random_enc. I replaced it with a pointer: void encounter (int& health)
This passes the reference rather than the value. Then health is defined in the member function.
#include <iostream>
using namespace std;
void encounter(int& health) // note the ampersand
{
--health; // this will change health in main
}
int main()
{
int health = 12;
encounter(health);
cout << health << '\n'; // prints 11
}

Boost multi_array BOOST_ASSERT has thrown a breakpoint

I'm writing a texbased dungeoncrawler style game for my C++ class and I'm encountering a runtime error stating that boost assert has triggered a breakpoint. I've made a very similar project in C# using the same logic, so I think it's something to do with a specific of C++ that's causing my issue.
Here's my code:
ArtoriaClasses.h
#pragma once
//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17
#include <iostream>
#include <sstream>
#include <memory>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include <ctime>
#include <vector>
#include <fstream>
#include "boost/multi_array.hpp"
#include <cassert>
using namespace std;
//Class representing one tile of the map
class MapTile
{
private:
int X;
int Y;
string message;
int eventID;
public:
//Default Constructor
MapTile()
{
}
//Constructor with minimum arguments
MapTile(int x, int y)
{
X = x;
Y = y;
message = "You are unable to go that way.";
eventID = -1;
}
//Constructor with all arguments
MapTile(int x, int y, string message, int eventID)
{
X = x;
Y = y;
this->message = message;
this->eventID = eventID;
}
//function to return coords as a vector with 2 elements
vector<int> getCoords()
{
vector<int> coords;
coords.push_back(X);
coords.push_back(Y);
return coords;
}
//function to get the message;
string getMessage()
{
return message;
}
//function to get the eventID
int getEventID()
{
return eventID;
}
};
//Class that is the game object itself, is implemented in the main "runner"
class Artoria
{
private:
int tempCoordinates[2];
int coordinates[2];
Player player;
Enemy currentEnemy;
bool activeEnemy;
//This is what I tried originally but it throws a bad_alloc at runtime
//when I first try to assign it a value in populateMap()
//MapTile map[10][10];
//Trying something for map
boost::multi_array<MapTile, 2> map2 { boost::extents[10][10] };
vector<Item> looseItems;
vector<Weapon> weapons;
vector<Armor> armors;
Random randomGen;
bool playerDied;
public:
//Default Constructor
Artoria()
{
populateItems();
populateMap();
activeEnemy = false;
startGame();
}
//Function that creates the entire map by populating the multidimensional array of MapTile objects
void populateMap()
{
map2[0][0] = MapTile(0, 0, "You cannot go this way.", -1);
//Omitted additional assignments to save character space
map2[9][9] = MapTile(9, 9, "You are in the Alchemists' Lab!", 3);
}
//Function to evaluate user's input
string evaluateInput(string userInput)
{
boost::algorithm::to_lower(userInput);
if (userInput == "north")
{
if (!activeEnemy)
{
//moving south so add one to Y coordinate
coordinates[1] = (coordinates[1] + 1);
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "south")
{
if (!activeEnemy)
{
//moving south so subract one from Y coordinate
coordinates[1] = (coordinates[1] - 1);
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "east")
{
if (!activeEnemy)
{
//moving east so add 1 to X coordinate
coordinates[0] = (coordinates[0] + 1);
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "west")
{
if (!activeEnemy)
{
//moving west so subract 1 from X coordinate
coordinates[0] = (coordinates[0] - 1);
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "attack")
{
if (activeEnemy)
{
battleEnemy();
}
else
{
cout << "There is no enemy attacking you, move around to find enemies." << endl << "Type 'help_me' for detailed instructions." << endl;
}
}
else if (userInput == "stopplayingartoria")
{
string ret = quitGame();
return ret;
}
else if (userInput == "help_me")
{
stringstream ret;
ret << "You can move around the map typing the following commands: 'north', 'south', 'east', and 'west'" << endl << "If you encounter an enemy, attack them by typing 'attack' If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
}
else
{
return "false";
}
return "true";
}
//Function to generate the message output to the console.
string genMessage()
{
if (!activeEnemy)
{
//get the current map tile from the map container
MapTile currentTile = map2[coordinates[0]][coordinates[1]];
string message = currentTile.getMessage();
int eventID = currentTile.getEventID();
//string variable to fill with return value;
string retStr;
//3 different areas each with event id(1-3), event ids are added for additional custom events
switch (eventID)
{
case 1:
//Dungeon Hallway
retStr = genDungeonHallway();
cout << message << endl << retStr;
break;
case 2:
//Crypt
retStr = genCrypt();
cout << message << endl << retStr;
break;
case 3:
//Alchemist's Lab
retStr = genAlchemistsLab();
cout << message << endl << retStr;
break;
case 4:
retStr = "This appears to be a safe place, nothing can surprise you here, but you will also find nothing here.";
cout << message << retStr << endl;
break;
case -1:
//player cannot go here so reset his coordinates
coordinates[0] = tempCoordinates[0];
coordinates[1] = tempCoordinates[1];
return message;
default:
// Case 0 is just print message(currently unused)
retStr = message;
break;
}
//set tempCoords to keep track of last tile.
tempCoordinates[0] = coordinates[0];
tempCoordinates[1] = coordinates[1];
return retStr;
}
}
};
Runner.cpp
//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17
#include <iostream>
#include <string>
#include <memory>
#include <boost/algorithm/string.hpp>
#include "ArtoriaClasses.h";
using namespace std;
int main()
{
string userInput;
cout << "Welcome to the game 'Artoria'. You can start a new game by typing 'new' " << endl << " load an existing save by typing 'load' or view instructions on how to play the game by typing 'help_me'" << endl;
getline(cin, userInput);
boost::algorithm::to_lower(userInput);
if (userInput == "new")
{
Artoria artoriaGame = Artoria();
while (userInput != "QUIT")
{
getline(cin, userInput);
string ret = artoriaGame.evaluateInput(userInput);
if (ret == "true")
{
cout << artoriaGame.genMessage();
}
else if (ret == "false")
{
cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
}
else if (ret == "QUIT")
{
}
}
}
else if (userInput == "load")
{
cout << "What is the name you used?" << endl;
getline(cin, userInput);
Artoria artoriaGame = Artoria(userInput);
while (userInput != "QUIT")
{
getline(cin, userInput);
string ret = artoriaGame.evaluateInput(userInput);
if (ret == "true")
{
cout << artoriaGame.genMessage();
}
else if (ret == "false")
{
cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
}
else if (ret == "QUIT")
{
}
}
}
else if (userInput == "help_me")
{
cout << "Artoria is a text-based dungeon crawler created by Jake Farley. The goal of the game is to get the highest score." << endl;
cout << "You score points by defeating monsters and picking up items, as you walk around the map you will encounter various enemies and find various items." << endl;
cout << "As you fight enemies, you will take damage; be warned, there is no way to regain your health. Once your health reaches zero, the game will end." << endl;
cout << "You can move around the map by typing the four compass directions 'north', 'south', 'east', and 'west'" << endl;
cout << "If you encounter an enemy, attack them by typing 'attack' you cannot run away from an enemy encounter." << endl;
cout << "If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
}
else
{
cout << "Error: Invalid response, closing program." << endl;
}
system("pause");
}
What are the "omitted assignments"? If they address illegal indices, that would do it.
I don't see you initialize the coordinates anywhere, either. You probably think you get that for free, like in C#?
int tempCoordinates[2] = {0,0};
int coordinates[2] = {0,0};
It doesn't look like you do any range validation on the movements (west, east etc.), also look at the copy-paste comments ... :)
//moving south so add one to Y coordinate
coordinates[1] = (coordinates[1] + 1);
//moving south so subract one from Y coordinate
coordinates[1] = (coordinates[1] - 1);
//moving east so add 1 to X coordinate
coordinates[0] = (coordinates[0] + 1);
//moving west so subract 1 from X coordinate
coordinates[0] = (coordinates[0] - 1);
Suggestion
It would be better to abstract a little bit:
enum { Rows = 10, Columns = 10 };
struct Coords {
int x = 0, y = 0;
bool west() { if (x>0) { --x; return true; } return false; }
bool south() { if (y>0) { --y; return true; } return false; }
bool east() { if (x+1<Columns) { ++x; return true; } return false; }
bool north() { if (y+1<Rows) { ++y; return true; } return false; }
};
Coords lastCoordinates;
Coords coordinates;
Now you can use those constants:
boost::multi_array<MapTile, 2> map2 { boost::extents[Columns][Rows] };
And use them safe actions:
if (userInput == "north")
{
if (!activeEnemy)
{
coordinates.north();
}
// ...
No more need for comments, let alone wrong comments :)
Using it:
MapTile currentTile = map2[coordinates.x][coordinates.y];
Or:
case -1:
//player cannot go here so reset his coordinates
coordinates = lastCoordinates;
return message;
And:
//set lastCoordinates to keep track of last tile.
lastCoordinates = coordinates;
Live Demo
Managed to make navigation "playable". It reaches Alchemist Lab, just fine:
Live On Coliru
//#pragma once
//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17
struct Player {
};
struct Enemy {
};
struct Item {
};
struct Weapon {
};
struct Armor {
};
#include <iostream>
#include <sstream>
#include <memory>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include <ctime>
#include <vector>
#include <fstream>
#include "boost/multi_array.hpp"
#include <cassert>
using Random = boost::random::mt19937;
using namespace std;
//Class representing one tile of the map
class MapTile
{
private:
int X;
int Y;
string message;
int eventID;
public:
//Default Constructor
MapTile()
{
}
//Constructor with minimum arguments
MapTile(int x, int y)
{
X = x;
Y = y;
message = "You are unable to go that way.";
eventID = -1;
}
//Constructor with all arguments
MapTile(int x, int y, string message, int eventID)
{
X = x;
Y = y;
this->message = message;
this->eventID = eventID;
}
//function to return coords as a vector with 2 elements
vector<int> getCoords()
{
vector<int> coords;
coords.push_back(X);
coords.push_back(Y);
return coords;
}
//function to get the message;
string getMessage()
{
return message;
}
//function to get the eventID
int getEventID()
{
return eventID;
}
};
//Class that is the game object itself, is implemented in the main "runner"
class Artoria
{
private:
enum { Rows = 10, Columns = 10 };
struct Coords {
int x = 0, y = 0;
bool west() { if (x>0) { --x; return true; } return false; }
bool south() { if (y>0) { --y; return true; } return false; }
bool east() { if (x+1<Columns) { ++x; return true; } return false; }
bool north() { if (y+1<Rows) { ++y; return true; } return false; }
};
Coords lastCoordinates;
Coords coordinates;
Player player;
Enemy currentEnemy;
bool activeEnemy;
boost::multi_array<MapTile, 2> map2 { boost::extents[Columns][Rows] };
vector<Item> looseItems;
vector<Weapon> weapons;
vector<Armor> armors;
Random randomGen;
bool playerDied;
public:
//Default Constructor
Artoria(std::string const& /*s*/ = {})
{
//populateItems();
populateMap();
activeEnemy = false;
//startGame();
}
//Function that creates the entire map by populating the multidimensional array of MapTile objects
void populateMap()
{
map2[0][0] = MapTile(0, 0, "You cannot go this way.", -1);
//Omitted additional assignments to save character space
map2[9][9] = MapTile(9, 9, "You are in the Alchemists' Lab!", 3);
}
//Function to evaluate user's input
string evaluateInput(string userInput)
{
boost::algorithm::to_lower(userInput);
if (userInput == "north")
{
if (!activeEnemy)
{
coordinates.north();
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "south")
{
if (!activeEnemy)
{
coordinates.south();
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "east")
{
if (!activeEnemy)
{
coordinates.east();
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "west")
{
if (!activeEnemy)
{
coordinates.west();
}
else
{
cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
return "false";
}
}
else if (userInput == "attack")
{
if (activeEnemy)
{
//battleEnemy();
}
else
{
cout << "There is no enemy attacking you, move around to find enemies." << endl << "Type 'help_me' for detailed instructions." << endl;
}
}
else if (userInput == "stopplayingartoria")
{
//string ret = quitGame();
return "quit";
}
else if (userInput == "help_me")
{
stringstream ret;
ret << "You can move around the map typing the following commands: 'north', 'south', 'east', and 'west'" << endl << "If you encounter an enemy, attack them by typing 'attack' If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
}
else
{
return "false";
}
return "true";
}
//Function to generate the message output to the console.
string genMessage()
{
if (!activeEnemy)
{
//get the current map tile from the map container
MapTile currentTile = map2[coordinates.x][coordinates.y];
string message = currentTile.getMessage();
int eventID = currentTile.getEventID();
//string variable to fill with return value;
string retStr;
//3 different areas each with event id(1-3), event ids are added for additional custom events
switch (eventID)
{
case 1:
//Dungeon Hallway
retStr = "genDungeonHallway()";
cout << message << endl << retStr;
break;
case 2:
//Crypt
retStr = "genCrypt()";
cout << message << endl << retStr;
break;
case 3:
//Alchemist's Lab
retStr = "genAlchemistsLab()";
cout << message << endl << retStr;
break;
case 4:
retStr = "This appears to be a safe place, nothing can surprise you here, but you will also find nothing here.";
cout << message << retStr << endl;
break;
case -1:
//player cannot go here so reset his coordinates
coordinates = lastCoordinates;
return message;
default:
// Case 0 is just print message(currently unused)
retStr = message;
break;
}
//set lastCoordinates to keep track of last tile.
lastCoordinates = coordinates;
return retStr;
}
}
};
//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17
#include <iostream>
#include <string>
#include <memory>
#include <boost/algorithm/string.hpp>
//#include "ArtoriaClasses.h";
using namespace std;
int main()
{
string userInput;
cout << "Welcome to the game 'Artoria'. You can start a new game by typing 'new' " << endl << " load an existing save by typing 'load' or view instructions on how to play the game by typing 'help_me'" << endl;
getline(cin, userInput);
boost::algorithm::to_lower(userInput);
if (userInput == "new")
{
Artoria artoriaGame = Artoria();
while (userInput != "QUIT")
{
getline(cin, userInput);
string ret = artoriaGame.evaluateInput(userInput);
if (ret == "true")
{
cout << artoriaGame.genMessage();
}
else if (ret == "false")
{
cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
}
else if (ret == "QUIT")
{
}
}
}
else if (userInput == "load")
{
cout << "What is the name you used?" << endl;
getline(cin, userInput);
Artoria artoriaGame = Artoria(userInput);
while (userInput != "QUIT")
{
getline(cin, userInput);
string ret = artoriaGame.evaluateInput(userInput);
if (ret == "true")
{
cout << artoriaGame.genMessage();
}
else if (ret == "false")
{
cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
}
else if (ret == "QUIT")
{
}
}
}
else if (userInput == "help_me")
{
cout << "Artoria is a text-based dungeon crawler created by Jake Farley. The goal of the game is to get the highest score." << endl;
cout << "You score points by defeating monsters and picking up items, as you walk around the map you will encounter various enemies and find various items." << endl;
cout << "As you fight enemies, you will take damage; be warned, there is no way to regain your health. Once your health reaches zero, the game will end." << endl;
cout << "You can move around the map by typing the four compass directions 'north', 'south', 'east', and 'west'" << endl;
cout << "If you encounter an enemy, attack them by typing 'attack' you cannot run away from an enemy encounter." << endl;
cout << "If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
}
else
{
cout << "Error: Invalid response, closing program." << endl;
}
}
Prints
Welcome to the game 'Artoria'. You can start a new game by typing 'new'
load an existing save by typing 'load' or view instructions on how to play the game by typing 'help_me'
You cannot go this way.
You are in the Alchemists' Lab!
genAlchemistsLab()
genAlchemistsLab()
You have entered an invalid command.
You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
...
As you can see you need to work on the input loop and detecting end-of-file :)

c++ (Compare all spaces with Pawns )

I have a board game that has spaces (has numeral values 1,2,3, etc.) starting from 1 and 16 pieces of pawns; four for each player.
I want to show the result of my board game at some point. I tried the method below but that will make my code extremely long.
i have 16 pieces and 100 spaces that i have to repeat that code with 100 space that would take forever. the code below is just for one space (the first space)
Any idea how to show my result in a short way? Thanks in advance!
Here is my old-fashioned way:
//space 1
if (bpiece1->value == 1)
{
cout << " bpiece1";
}
else if (bpiece2->value == 1)
{
cout << " bpiece2";
}
else if (bpiece3->value == 1)
{
cout << " bpiece3";
}
else if (bpiece4->value == 1)
{
cout << " bpiece4";
}
else if (gpiece1->value == 1)
{
cout << " gpiece1";
}
else if (gpiece2->value == 1)
{
cout << " gpiece2";
}
else if (gpiece3->value == 1)
{
cout << " gpiece3";
}
else if (gpiece4->value == 1)
{
cout << " gpiece4";
}
else if (ypiece1->value == 1)
{
cout << " ypiece1";
}
else if (ypiece2->value == 1)
{
cout << " ypiece2";
}
else if (ypiece3->value == 1)
{
cout << " ypiece3";
}
else if (y4->value == 1)
{
cout << " y4";
}
else if (rpiece1->value == 1)
{
cout << " rpiece1";
}
else if (rpiece2->value == 1)
{
cout << " rpiece2";
}
else if (rpiece3->value == 1)
{
cout << " rpiece3";
}
else if (rpiece4->value == 1)
{
cout << " rpiece4";
}
else
{
cout << " 01";
}
C++ is an object-oriented language. Therefore, we start by creating a class that stores your board and implements all functions on it. Like
//Board.h
#include <array>
using std::array;
enum class Figure { None, Pawn };
class Board {
private:
array<array<Figure, 8>, 8> fields; //8x8 if it was a chess board
public:
void print() const;
};
//Board.cpp
#include "Board.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
inline string to_string(const Figure figure){
switch(figure){
case Figure::None:
return " ";
case Figure::Pawn:
return "p";
}
//throw error here
return "";
}
void Board::print() const {
for(size_t i = 0; i < fields.size(); i++){
for(size_t j = 0; j < fields[i].size(); j++){
cout << to_string(fields[i][j]);
}
cout << endl;
}
cout << endl;
}
If this is new to you, you should really read the basic tutorials first and make sure that you understand each line I wrote in the end.
Important here is: Representation, represenation, representation. Don't think in "1 is a pawn", think in "a pawn is a pawn". Everything that has a function which you can think of should probably be a class, a structure or an enum.

C++ compile error with functions

I was wondering if someone could lend me some advice as to why my code wont compile. I have a simple tic tac toe game here split up into 3 files. Yet, main.cpp is unable to create an objects from my ticTacToe.h file and I just don't understand why. I feel like I'm a step away from getting this to run. ticTacToe.cpp and ticTacToe.h compile just fine. It's the main.cpp file that produces an error when it gets to line 14 "ttt.create_board();". The error message is "unidentified reference to 'ticTacToe: :create_board(char)'" Any help would be greatly appreciated. Thanks guys.
main.cpp
#include "ticTacToe.h"
#include <iostream>
#include <limits> //This is required to catch invalid user input
void run_game()
{
char letter_o = 'O';
char letter_x = 'X';
ticTacToe ttt; //creates an object "ttt" to be used later
ttt.player1Piece = letter_x;
ttt.player2Piece = letter_o;
std::cout << "Welcome to tic tac toe!" << std::endl;
std::cout << "Here is a blank board: " << std::endl;
ttt.create_board();
while (true){
std::cout << "\nPlayer X, it is your turn\n" << std::endl;
ttt.update_board(letter_x);
if (ttt.determine_winner(letter_x) == true){
break;
}
std::cout << "\nPlayer O, it is your turn\n" << std::endl;
ttt.update_board(letter_o);
if (ttt.determine_winner(letter_o) == true){
break;
}
}
}
int main() //main kicks things off by calling "run_game()"
{
run_game();
}
ticTacToe.h
#ifndef TICTACTOE_H
#define TICTACTOE_H
class ticTacToe
{
public: //Allow us to use the functions anywhere
char board[3][3]; //Creates an 2d array for the board
char player1Piece; //variable used in multiple functions
char player2Piece; //varibable used in multiple
void create_board();
void print_board(char playerPiece, int pos1 = 0, int pos2 = 0);
int check_for_overlap(int pos1, int pos2, char playerPiece);
void update_board(char playerPiece);
int determine_winner(char playerPiece);
};
#endif // TICTACTOE_H
ticTacToe.cpp
#include "ticTacToe.h"
#include <iostream>
#include <limits>
ticTacToe::ticTacToe()
{
void ticTacToe::create_board()
{
//initializes a blank board
for(int a = 0; a < 3; a++){
std::cout << "\n";
for (int b = 0; b < 3; b++){
board[a][b] = '-';
std::cout << board[a][b];
}
}
}
void ticTacToe::print_board(char playerPiece, int pos1 = 0, int pos2 = 0)
{
//prints out the updated board when called upon to do so
for(int a = 0; a < 3; a++){
std::cout << "\n";
for (int b = 0; b < 3; b++){
board[pos1][pos2] = playerPiece;
std::cout << board[a][b];
}
}
}
int ticTacToe::check_for_overlap(int pos1, int pos2, char playerPiece)
{
if (board[pos1-1][pos2-1] != '-'){
std::cout << "\nOVERLAP DETECTED!!!!!!" << std::endl;
return true;
}
return false;
}
void ticTacToe::update_board(char playerPiece)
{
//updates the board based on user input
int x, y;
std::cout << "Enter a position to place the " << playerPiece << " on the board" << std::endl;
while (true){
std::cout << "Enter row: " << std::endl;
std::cin >> x;
if (x < 1 || x > 3 || std::cin.fail()){
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cout << "Your number is invalid. Try again. " << std::endl;
} else {
break;
}
}
while (true)
{
std::cout << "Enter col: " << std::endl;
std::cin >> y;
if (y < 1 || y > 3 || std::cin.fail()){
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cout << "Your number is invalid. Try again. " << std::endl;
} else {
break;
}
}
if (check_for_overlap(x, y, player1Piece) == true){
x--;y--;print_board(player2Piece, x, y);
std::cout << "\nThe board has been re-set. Try again!" << std::endl;
} else if (check_for_overlap(x, y, player2Piece) == true){
x--;y--;print_board(player1Piece, x, y);
std::cout << "\nThe board has been re-set. Try again." << std::endl;
} else {
x--;y--;print_board(playerPiece, x, y);
}
}
int ticTacToe::determine_winner(char playerPiece)
{
/*slices the board and checks if playerPiece occupies that slot.
If the player makes a line, print that playerPiece has won
and exit the game.*/
if (board[0][0] == playerPiece && board[0][1] == playerPiece && board[0][2] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
}
else if(board[1][0] == playerPiece && board[1][1] == playerPiece && board[1][2] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
}
else if(board[2][0] == playerPiece && board[2][1] == playerPiece && board[2][2] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
}
else if(board[0][0] == playerPiece && board[1][0] == playerPiece && board[2][0] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
}
else if(board[0][1] == playerPiece && board[1][1] == playerPiece && board[2][1] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
}
else if(board[0][2] == playerPiece && board[1][2] == playerPiece && board[2][2] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
}
else if(board[0][0] == playerPiece && board[1][1] == playerPiece && board[2][2] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
}
else if(board[0][2] == playerPiece && board[1][1] == playerPiece && board[2][0] == playerPiece){
std::cout << "\nPlayer " << playerPiece << " wins!" << std::endl;
return true;
} else {
return false;
}
}
}
}
Simply remove both } at the very end of ticTacToe.cpp and
ticTacToe::ticTacToe()
{
You didn't declare any constructor in the header file.
Then there is another Problem with the function print_board.
It's declared as void print_board(char playerPiece, int pos1 = 0, int pos2 = 0) but you're using default arguments in definition, too.
Change both int pos1=0, int pos2=0 to int pos1, int pos2 in ticTacToe.cpp.
Try to overthink your code formatting to know which bracet belong to which. :)
Change this
ticTacToe::ticTacToe()
{
void ticTacToe::create_board()
{
//initializes a blank board
for(int a = 0; a < 3; a++){
std::cout << "\n";
for (int b = 0; b < 3; b++){
board[a][b] = '-';
std::cout << board[a][b];
}
}
}
to this
void ticTacToe::create_board()
{
//initializes a blank board
for(int a = 0; a < 3; a++){
std::cout << "\n";
for (int b = 0; b < 3; b++){
board[a][b] = '-';
std::cout << board[a][b];
}
}
}
Then remove from ticTacToe.cpp file the last two curly brackets in the file.
If you want to have a constructor, then you should define it inside the class, like the other functions (and then of course implement it inside .cpp).
class ticTacToe {
...
char player2Piece; //varibable used in multiple
ticTacToe(); <--- HERE
void create_board();
void print_board(char playerPiece, int pos1, int pos2); <-- Change the default arguments here
...
};
Also, in
void print_board(char playerPiece, int pos1, int pos2);
you should not pass the default arguments in the .h file (or the other way around).
The problem is here
ticTacToe::ticTacToe()
{
void ticTacToe::create_board()
{
}
// more functions
}
You have wrapped all your member functions inside your tictacToe constructor. As you are not actually doing anything in your constructor you can remove it.
Remove
ticTacToe::ticTacToe()
{
and
}
}
At the end of your cpp file.
Also do not specify default parameters to a method in the method definition (cpp file) and the method declaration (h file).
if you do
class ticTacToe
{
public: //Allow us to use the functions anywhere
...
void print_board(char playerPiece, int pos1 = 0, int pos2 = 0);
...
};
Don't then redeclare the defaults.
void ticTacToe::print_board(char playerPiece, int pos1 = 0, int pos2 = 0)
Instead declare the method
void ticTacToe::print_board(char playerPiece, int pos1, int pos2)
A final comment
check_for_overlap returns int. As you internally use bool and check for bool when you call it, you should change the method signature to
bool ticTacToe::check_for_overlap(int pos1, int pos2, char playerPiece)