Related
I'm currently just starting off coding in c++, the current project I'm working on is making an in-console chess engine type thing. The function below is supposed to check if a particular square has a piece on it, and if so, if the piece is white. Board.grid is a 2D array of strings where " " would be an empty square, "wR1" one of the white rooks, "bQ1" the black queen, etcetera. I got the error expected primary-expression before '.' token on both if statements inside the functions and think it's got to do with the .at() function called on the 'square string', but have no clue why this would give an error or what could be done to resolve it.
I would appreciate it greatly if anyone could help me with this. Thanks in advance!
#include <iostream>
using namespace std;
struct Board {
string Grid[8][8] =
{
{"bR1", "bN1", "bB1", "bQ1", "bK1", "bB2", "bN2", "bR2"},
{"bp1", "bp2", "bp3", "bp4", "bp5", "bp6", "bp7", "bp8"},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{"wp1", "wp2", "wp3", "wp4", "wp5", "wp6", "wp7", "wp8"},
{"wR1", "wN1", "wB1", "wQ1", "wK1", "wB2", "wN2", "wR2"},
};
};
class Piece
{
public:
bool getSquare (int square[2])
{
bool isOccupied = false;
bool isWhite = false;
if (Board.grid[square[1]][square[0]].at(0) != ' '){isOccupied = true;};
if (Board.grid[square[1]][square[0]].at(0) == 'w'){isWhite = true;};
bool arr[2] = {isOccupied, isWhite};
return arr;
};
};
The symbol Board is a type not an instance. In C++ you can't use the . operator to access type members, only members of objects.
The simple solution is to create a Board objects:
struct /* Anonymous structure */ {
string Grid[8][8] =
{
{"bR1", "bN1", "bB1", "bQ1", "bK1", "bB2", "bN2", "bR2"},
{"bp1", "bp2", "bp3", "bp4", "bp5", "bp6", "bp7", "bp8"},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{"wp1", "wp2", "wp3", "wp4", "wp5", "wp6", "wp7", "wp8"},
{"wR1", "wN1", "wB1", "wQ1", "wK1", "wB2", "wN2", "wR2"},
};
} Board; // Define the Board structure object instance
Or possibly define Board as a namespace, and use the scope operator:
namespace Board {
string Grid[8][8] =
{
{"bR1", "bN1", "bB1", "bQ1", "bK1", "bB2", "bN2", "bR2"},
{"bp1", "bp2", "bp3", "bp4", "bp5", "bp6", "bp7", "bp8"},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " "},
{"wp1", "wp2", "wp3", "wp4", "wp5", "wp6", "wp7", "wp8"},
{"wR1", "wN1", "wB1", "wQ1", "wK1", "wB2", "wN2", "wR2"},
};
}
// ...
Board::grid[square[1]][square[0]].at(0)
// ^^
// Note use of scope operator :: here
So, I have some variables declared as follows:
int rect1Color;
int rect2Color;
int rect3Color;
...
int rect63Color;
int rect64Color;
I need to change each of these variables based on a loop that looks like this:
for (int i = 0; i < sizeof(playPos) / sizeof(char*); ++i) {
const char* TEMP = playPos[i];
if (TEMP != " x" && TEMP != " o" && TEMP != "xx" && TEMP != "oo") {
if (TEMP == " p") {
rect[i+1]Color = 1;
}
else {
rect[i+1]Color = 2;
}
}
else if (TEMP == " o" || TEMP == "oo") {
rect[i+1]Color = 3;
}
else if (TEMP == " x" || TEMP == "xx") {
rect[i+1]Color = 4;
}
}
That draws from this data set:
const char *playPos[64] {
" ", " o", " ", " o", " ", " o", " ", " o",
" o", " ", " o", " ", " o", " ", " o", " ",
" ", " o", " ", " o", " ", " o", " ", " o",
" ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ",
" x", " ", " x", " ", " x", " ", " x", " ",
" ", " x", " ", " x", " ", " x", " ", " x",
" x", " ", " x", " ", " x", " ", " x", " "
};
The data set and logic all work, I just can't find a simple way to set the values of the variables.
The solution to my problem was turning my long list of ints into one vector/array.
So instead of:
int rect1Color;
int rect2Color;
int rect3Color;
...
int rect63Color;
int rect64Color;
I now have:
int rectColor1[64];
User "cigien":
Just use a vector<int> rectColors;. Then the index i corresponds to the ith colour.
User "user4581301":
Side note: if you have a fixed number of variables known at compile time, consider using std::array as well. Because the size is fixed there is less overhead than what's needed by the dynamically sized std::vector
I have been trying to get this to work correctly; however it seems I can not figure this out. I am trying to get a game board to initialize correctly but it keeps saying that <error reading characters of string>.
using namespace std;
int main()
{
board show;
show.init();
show.printing();
}
class board {
public:
void init(){
string Board[8][9] = {
{ "C56", "C15", "C21", "C62", "C11", "C62", "C21", "C15", "C56" },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ "C56", "C15", "C21", "C62", "C11", "C62", "C21", "C15", "C56" },
};
}
void printing(){
string character = "*";
int position[2] = { 2, 2 };
// Draw the grid once
for (int i = 0; i < 8; i++){
for (int j = 0; j < 9; j++){
if (i == position[0] && j == position[1])
cout << character;
else
cout << Board[8][9];
cout << " ";
}
cout << endl;
}
}
private:
string Board[8][9];
};
it's so easy: you have the half solution:
just use for loop to copy values
void A::init()
{
string Board[8][9] = {
{ "C56", "C15", "C21", "C62", "C11", "C62", "C21", "C15", "C56" },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 ", " 0 " },
{ "C56", "C15", "C21", "C62", "C11", "C62", "C21", "C15", "C56" },
};
for(int i(0); i < 8; i++)
{
for(int j(0); j < 9; j++)
this->Board[i][j] = Board[i][j];
}
}
In the init method you created a new, local variable. You are not referring to your instance variable, therefore in printing method the variable is not initialized.
Instead of
string Board[8][9] = // ... initialization code
you should write
this->Board = // ... initialization code
or just
Board = // ... initialization code
You can read more about variable types here.
I have used stackoverflow for a long time and never had to post a question before, but this one has me EXTREMELY frustrated.
I have this piece of code
array<array<string, 10>, 10> cShots =
{
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }
};
outside of any methods at a global level. What I'm trying to do is create a 2d array 10 by 10 full of blank space strings. What happens instead is that I get an error on the first bracket of the third line saying "too many initializer values". Every solution I have found to this error says that what I am doing is correct. I have tried doing it multiple other ways.
string** cShots =
{
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "}
};
string cShots[10][10] =
{
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "},
{" ", " ", " ", " ", " ", " ", " ", " ", " ", " "}
};
but everything I try has the same result.
PLEASE HELP!
EDIT: well...I figured out that I just needed more brackets...and the error went away...but now when I run my code visual studio says that it was a successful build, but then freezes forever...
Things are a little easier to understand when you see that there is a special case for the syntax here. std::array is an aggregate, it's a struct that contains a single data member which is the underlying raw array. To initialize one of these you need to uniform-initialize the array (first braces) then initialize the underlying raw array member stored in the std::array (second braces);
So when you have something such as:
array<string, 3> test = {{"a", "b", "c"}};
The outermost braces initialize the array itself then the inner part initializes the underlying array. In this case it's clear that this is the way it is working and a special case was made (See the standard: section 8.5 for more) that allows the compiler to accept the other syntax of:
array<string, 3> test = {"a", "b", "c"} ;
However in the case of the question it's not of the special-case-form specified in the standard so you need the extra braces (this too caused me confusion when I first encountered it). There is a defect report about this actually http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3367.html#1270
In more recent c++ standards (see Can we omit the double-braces for std::array in C++14?) this requirement is relaxed.
Because the code in the question does not benefit for the special case of the syntax we need both braces. In this case your initializer is however not of length one:
array<array<string, 10>, 10> cShots =
{
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }, //extra initializer elements but only one underlying raw array
//snip
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }
};
To the compiler it looks like you are trying to initialize multiple members of the std::array class but the problem is that there is only one underlying storage array. Hence the compiler error message you get here. To get this to work you need to be more explicit and add the extra pair of braces to get an initializer of length one passed to the outer std::array. You then initialize the underlying raw array which contains the other arrays:
array<array<string, 10>, 10> cShots =
{{
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
//snip
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }
}};
For a proof of concept see this: http://coliru.stacked-crooked.com/a/4c57a7193629931f
(Note the nested arrays here do benefit from the syntatical special case)
When I print my field it works but when I change a value the array seems to get reset. I think I'm declaring my string veld[10][11] on the wrong place but I'm not shure.
Also got veld as an attribute of my class speelveld.h
thanks
#include "speelveld.h"
#include "Schip.h"
void spelbord::printVeld(){
//spelbord::zetBoot();
string veld[10][11]= {
{ "A", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "B", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "C", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "D", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "E", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "F", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "G", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "H", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "I", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
{ "J", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }
};
cout << " 1 2 3 4 5 6 7 8 9 10" << endl;
for (int i = 0; i < 10; i++){
cout << " +-+-+-+-+-+-+-+-+-+-+" << endl;
for (int j = 0; j < 11; j++){
cout << veld[i][j] << "|" << flush;
}
cout << endl;
}
cout << " +-+-+-+-+-+-+-+-+-+-+" << endl;
}
void spelbord::zetBoot(){
string veld[10][11];
cout << "Wat is de eerste coordinaat van je vliegdekschip? (bv: a1) " << flush;
cin >> vliegdekschip1;
y = vliegdekschip1[0];
x = vliegdekschip1[1];
cout << y << endl;
cout << x << endl;
spelbord::checkpos();
}
void spelbord::checkpos(){
if (y == 97){
if (x == 49){
veld[0][1] = "O";
spelbord::printVeld();
}
{
{
For the rest of my answer, I assume that your class spelbord has an attribute veld of type string.
The problem
The problem is that you use a local variable in your spelbord::printVeld function:
void spelbord::printVeld()
{
/* Initialize a 'new' local variable each time you pass here. */
string veld[10][11] = {
/* Initialization value. */
}
/* Print header. */
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 11; ++j)
/* Refers to the variable just initialized. */
cout << veld[i][j] << "|" << flush;
cout << endl;
}
/* Print footer. */
}
void spelbord::checkpos()
{
if (y == 97)
if (x == 49)
{
/* Refers to the attribute 'veld' of the 'spelbord' object */
veld[0][1] = "O";
spelbord::printVeld();
}
}
To sum-up You are always displaying a variable newly initialized. Not the one you are modifying in spelbord::checkpos.
A possible solution
/* Constructor. Used to initialize members. */
spelbord::spelbord()
{
/* I don't use the constructor's prefered way of initialization because your
initialization value is huge. */
veld = { /* Initialization. */ };
}
/* No local variable this time. */
void spelbord::printVeld()
{
/* Print header. */
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 11; ++j)
/* Refers to the member of the object. */
cout << veld[i][j] << "|" << flush;
cout << endl;
}
/* Print footer. */
}
void spelbord::checkpos()
{
/* Same as before. */
}
This time the member is initialized only once, when the object is built, and you modify and display this member.