Why does the second variable not change in the field? - c++

I'm testing some programms for my lectures. I'm creating classes and use a paramterlist to initalize a field but the second variable doesn't change.
#include <iostream>
using namespace std;
class Punkt {
int x;
int y;
public:
Punkt(int a = 0, int b = 0)
{
x = a;
y = b;
}
void printXY()
{
cout << "x= " << x << " y= " << y << endl;
}
};
int main() {
Punkt pFeld[] = { (1, 1), (2, 2), (3, 3) };
for (int i = 0; i < 3; i++)
pFeld[i].printXY();
cin.get();
};
No error messages. Expected result was that x and y change, while actual result is that only x changes and y stays 0.

This
(1, 1)
is an expression with the comma operator.
In fact this initialization
Punkt pFeld[] = { (1, 1), (2, 2), (3, 3) };
is equivalent to
Punkt pFeld[] = { 1, 2, 3 };
So the constructor with the second default argument equal to 0 is called three times.
Use instead
{ 1, 1 }
Here is your updated code
#include <iostream>
using namespace std;
class Punkt {
int x;
int y;
public:
Punkt(int a = 0, int b = 0)
{
x = a;
y = b;
}
void printXY()
{
cout << "x= " << x << " y= " << y << endl;
}
};
int main() {
Punkt pFeld[] = { {1, 1}, {2, 2}, {3, 3} };
for (int i = 0; i < 3; i++)
pFeld[i].printXY();
cin.get();
}
Its output is
x= 1 y= 1
x= 2 y= 2
x= 3 y= 3
Pay attention to that the semicolon after the function main is redundant.

Passing (1, 1) to the constructor of Punkt, the comma operator will return the 2nd operand as the result (the 1st operand is discarded), so you're only passing one int with value 1 to the constructor. That's why y is always initialized as 0.
What you want should be
Punkt pFeld[] = { {1, 1}, {2, 2}, {3, 3} }; // list initialization since C++11
or
Punkt pFeld[] = { Punkt(1, 1), Punkt(2, 2), Punkt(3, 3) };

Related

Accessing Class Member Variables with [] operator

I'm going through a book and I saw something interesting that I don't quite understand how it works.
What is happening under the hood of C++? Are the member variables laid out in an array like fashion. Does it only work for member variables of the same type?
I added a string type as the fourth variable just to see what happens and the output for [3] is 1.75518e-317.
Vector3D b{1, 2, 3, "56"};
cout << b[3] << "\n";
Here is the code:
vector.h
public Vector3D {
public:
double x;
double y;
double z;
Vector3D(double a = 0.0, double b = 0.0, double c = 0.0)
{
x = a;
y = b;
z = c;
}
double &operator[](int i)
{
return ((&x)[i]);
}
}
main.cpp
int main(int argc, char const *argv[])
{
Vector3D a{1, 2, 3};
Vector3D b{1, 2, 3};
cout << b[0] << "\n";
cout << b[1] << "\n";
cout << b[2] << "\n";
return 0;
}
Output:
1
2
3
Note: This code is a learning exercise only and I am not using it for anything.

C++ std::vector with values from multiple classes

I'm using std::vector for storing my values into MyValues from my classes A and B. Inserted elements/values depends on the type of class. If it's A, inserts {x, y}, if B, inserts {x, y, z}. And I loop it, so i can try to add multiple values of it, to just test it. But when I loop A.ases 5 times and then B.bses 7 times, looped MyValues has 31 single elements for some reason. Is possible to add elements and "preserve forms" (If it's A -> {x, y}, if B, -> {x, y, z}), so I can get same values, like the ones I inserted and work with it?
classes:
std::vector<int> MyValues;
class A {
public:
short int x, y;
A() {
this->x = this->y = 0;
}
};
class B : public A{
public:
short int z;
B() {
this->z = 0;
}
};
main:
int main() {
A ases[5];
B bses[7];
for (short int a = 0; a < 5; a++) {
ases[a].x = 5 + a;
ases[a].y = 4 + a;
MyValues.insert(MyValues.end(), { ases[a].x, ases[a].y });
}
for (short int b = 0; b < 7; b++) {
bses[b].x = 2 + b;
bses[b].y = 3 + b;
bses[b].z = 1 + b;
MyValues.insert(MyValues.end(), { bses[b].x, bses[b].y, bses[b].z });
}
for (int v : MyValues) std::cout << "x y z = " << v << std::endl;
return 0;
}
output:
x y z = 5
x y z = 4
x y z = 6
x y z = 5
x y z = 7
x y z = 6
x y z = 8
x y z = 7
x y z = 9
x y z = 8
x y z = 2
x y z = 3
x y z = 1
x y z = 3
x y z = 4
x y z = 2
x y z = 4
x y z = 5
x y z = 3
x y z = 5
x y z = 6
x y z = 4
x y z = 6
x y z = 7
x y z = 5
x y z = 7
x y z = 8
x y z = 6
x y z = 8
x y z = 9
x y z = 7
If you are using visual studio 2019 then you should be able to turn on C++17. This demo uses std::optional. Not sure how efficient it is, but it's convenient.
#include <iostream>
#include <vector>
#include <optional>
struct Base
{
int x, y;
std::optional<int> z;
Base(int _x, int _y) :
x(_x),
y(_y)
{}
Base(int _x, int _y, int _z) :
x(_x),
y(_y),
z(_z)
{}
};
int main()
{
Base b1 {1, 2, 3};
Base b2 {4, 5};
Base b3 {9, 9, 9};
std::vector V {b1, b2, b3};
for (auto& item : V)
{
std::cout << item.x << " " << item.y << " ";
if (item.z.has_value())
std::cout << item.z.value();
std::cout << std::endl;
}
}
And for demo: https://godbolt.org/z/nbedjb
You could make your MyValues a vector of vectors, like this:
std::vector<std::vector<int>> MyValues;
Then, without changing the definitions of your A and B classes, you can insert 2- or 3-element vectors, using much the same code as you already have in your main function. You would only need to change the way you display the data; I have shown one way, in the code below, but there are many others, depending on how 'pretty' you want your output to be.
int main()
{
A ases[5];
B bses[7];
for (short int a = 0; a < 5; a++) {
ases[a].x = 5 + a;
ases[a].y = 4 + a;
MyValues.insert(MyValues.end(), { ases[a].x, ases[a].y });
}
for (short int b = 0; b < 7; b++) {
bses[b].x = 2 + b;
bses[b].y = 3 + b;
bses[b].z = 1 + b;
MyValues.insert(MyValues.end(), { bses[b].x, bses[b].y, bses[b].z });
}
// No change required up to here; just change the code for output...
for (auto v : MyValues) {
std::cout << "{ ";
bool first = true;
for (auto i : v) {
if (!first) std::cout << ", ";
std::cout << i;
first = false;
}
std::cout << " }" << std::endl;
}
return 0;
}
Output from above:
{ 5, 4 }
{ 6, 5 }
{ 7, 6 }
{ 8, 7 }
{ 9, 8 }
{ 2, 3, 1 }
{ 3, 4, 2 }
{ 4, 5, 3 }
{ 5, 6, 4 }
{ 6, 7, 5 }
{ 7, 8, 6 }
{ 8, 9, 7 }

Undefined symbols for architecture x86_64 c++ visual studio code. game snakes and ladders

this error appears to me in two classes specifically and referenced in the main. Honestly, I don't know what happened.
"Boxes::fillLadder(char**, int**, int, int, int)", referenced from:
Boxes::fill(char**, int**, int, int) in SnakesAndLadders2-455af6.o
Board::draw(char**, int**, int, int) in SnakesAndLadders2-455af6.o
"Boxes::fillSnake(char**, int**, int, int, int)", referenced from:
Boxes::fill(char**, int**, int, int) in SnakesAndLadders2-455af6.o
Board::draw(char**, int**, int, int) in SnakesAndLadders2-455af6.o
"Boxes::Boxes()", referenced from:
Board::draw(char**, int**, int, int) in SnakesAndLadders2-455af6.o
_main in SnakesAndLadders2-455af6.o
ld: symbol(s) not found for architecture x86_64
This is class Boxes
#include <iostream>
#include <string>
using namespace std;
class Boxes{
public:
Boxes();
void fill(char **board, int **positions, int y, int x);
void fillLadder(char **board, int **positions, int y, int x, int lenght);
void fillSnake(char **board, int **positions, int y, int x, int lenght);
};
void Boxes::fill(char **board, int **positions, int y, int x)
{
for (int i = 0; i < y; i++)
{
for (int w = 0; w < x; w++)
{
board[i][w] = 'N';
positions[i][w] = 0;
}
}
if (y % 2 != 0)
{
board[0][x - 1] = 'O';
}
else
{
board[0][0] = 'O';
}
board[y - 1][0] = 'O';
if (y < 8)
{
fillLadder(board, positions, y - 1, 2, y / 2);
fillLadder(board, positions, y / 2, 4, 2);
fillSnake(board, positions, 0, 1, -1 * y / 2 + 1);
}
if (y >= 8 && y <= 12)
{
fillLadder(board, positions, y - 1, 3, 3);
fillLadder(board, positions, 4, x - 3, 2);
fillLadder(board, positions, 2, x - 2, 2);
fillSnake(board, positions, 0, 4, -4);
fillSnake(board, positions, 4, x - 4, -4);
fillSnake(board, positions, 4, 0, -3);
}
if (y > 12)
{
fillLadder(board, positions, y - 1, 3, 6);
fillLadder(board, positions, 6, x - 3, 5);
fillLadder(board, positions, 7, x - 2, 6);
fillLadder(board, positions, 9, 3, 3);
fillSnake(board, positions, 0, 4, -7);
fillSnake(board, positions, 4, x - 4, -6);
fillSnake(board, positions, 7, 0, -3);
fillSnake(board, positions, 5, 2, -2);
}
}
This is class Board
#include <iostream>
#include <string>
#include <ctime>
#include "Player.h"
#include "Boxes.h"
using namespace std;
class Board{
public:
void loop(char **board, int **positions, int y, int x);
void draw(char **board, int **positions, int y, int x);
};
void Board::loop(char **board, int **positions, int x, int y)
{
player1.location = 0;
player2.location = 0;
player1.level = y - 1;
player2.level = y - 1;
bool game = true;
Player p;
bool playerFlag;
int &movement = movement;
void Movement(int &movement, bool playerFlag);
{
Dice dice;
int status = 0;
if (playerFlag == true)
{
std::cout << "Player 1: Press 1 to roll the dice." << std::endl;
cin >> status;
if (status == 1)
{
dice.roll();
movement = dice.roll();
std::cout << "Player 1 rolled a: " << dice.roll() << std::endl;
}
}
if (playerFlag == false)
{
std::cout << "Player 2: Press 2 to roll the dice." << std::endl;
cin >> status;
if (status == 2)
{
dice.roll();
movement = dice.roll();
std::cout << "Player 2 rolled a: " << dice.roll() << std::endl;
}
}
}
while (game == true)
{
p.Movement(player1.movement, true);
p.logic(board, positions, y, x, player1.movement, player1.location, player1.level, player1.movestatus);
if (p.checkWin(y, x, player1.location, player1.level) == true)
{
std::cout << "Player 1 HAS WON THE GAME !!!!!!" << std::endl;
game = false;
}
else
{
p.updatePlayerLevel(positions, y, x, player1.location, player1.level, player1.movestatus);
board[player1.level][player1.location] = player1.symbol;
draw(board, positions, y, x);
}
if (player2.on == true)
{
p.Movement(player2.movement, false);
p.logic(board, positions, y, x, player2.movement, player2.location, player2.level, player2.movestatus);
if (p.checkWin(y, x, player2.location, player2.level) == true)
{
std::cout << "Player 2 HAS WON THE GAME !!!!!!" << std::endl;
game = false;
}
else
{
p.updatePlayerLevel(positions, y, x, player2.location, player2.level, player2.movestatus);
board[player2.level][player2.location] = player2.symbol;
draw(board, positions, y, x);
}
}
}
}
void Board::draw(char **board, int **positions, int y, int x)
{
Boxes bx;
if (y % 2 != 0)
{
board[0][x - 1] = 'O';
}
else
{
board[0][0] = 'O';
}
board[y - 1][0] = 'O';
for (int i = 0; i < y; i++)
{
if ((y - 1) > 9)
{
std::cout << y - 1 << " ⎪" << std::endl;
}
else
{
std::cout << y - 1 << " ⎪" << std::endl;
}
for (int y = 0; y < x; y++)
{
std::cout << board[i][y] << " " << std::endl;
}
std::cout << " " << std::endl;
}
if (y < 8)
{
bx.fillLadder(board, positions, y - 1, 2, y / 2);
bx.fillLadder(board, positions, y / 2, 4, 2);
bx.fillLadder(board, positions, 0, 1, -1 * y / 2 + 1);
}
if (y >= 8 && y <= 12)
{
bx.fillLadder(board, positions, y - 1, 3, 3);
bx.fillLadder(board, positions, 4, x - 3, 2);
bx.fillLadder(board, positions, 2, x - 2, 2);
bx.fillSnake(board, positions, 0, 4, -4);
bx.fillSnake(board, positions, 4, x - 4, -4);
bx.fillSnake(board, positions, 4, 0, -3);
}
if (y > 12)
{
bx.fillLadder(board, positions, y - 1, 3, 6);
bx.fillLadder(board, positions, 6, x - 3, 5);
bx.fillLadder(board, positions, 7, x - 2, 6);
bx.fillLadder(board, positions, 9, 3, 3);
bx.fillSnake(board, positions, 0, 4, -7);
bx.fillSnake(board, positions, 4, x - 4, -6);
bx.fillSnake(board, positions, 7, 0, -3);
bx.fillSnake(board, positions, 5, 2, -2);
}
}
And the main
#include <iostream>
#include <string>
#include <ctime>
#include "Board.h"
using namespace std;
int main()
{
Boxes f;
Board bo;
std::cout << "****** SNAKES AND LADDERS ******" << std::endl;
int size_y;
int size_x;
std::cout << "What size board do you want? Pick the number of rows and columns." << std::endl;
std::cout << "For balance, best size is 10x10." << std::endl;
std::cout << "Rows: " << std::endl;
cin >> size_y;
std::cout << "Columns: " << std::endl;
cin >> size_x;
int flag;
std::cout << "Press 2 if you want to play multiplayer (2 players). Press 1 for single player." << std::endl;
cin >> flag;
if (flag == 2)
{
player2.on = true;
}
std::cout << "Player 1: Select a letter/number on the keyboard for your character." << std::endl;
cin >> player1.symbol;
if (player2.on == true)
{
std::cout << "PLayer 2: Select a letter/number on the keyboard for your character." << std::endl;
cin >> player2.symbol;
}
system("CLS");
char **board;
board = new char *[size_y];
int **position_status;
position_status = new int *[size_y];
for (int i = 0; i < size_y; i++)
{
board[i] = new char [size_x];
position_status[i] = new int [size_x];
}
f.fill(board, position_status, size_y, size_x);
bo.draw(board, position_status, size_y, size_x);
bo.loop(board, position_status, size_y, size_x);
char stop;
std::cout << "Press e to end the programme." << std::endl;
cin >> stop;
for (int i = 0; i < size_y; i++)
{
delete[] board[i];
delete[] position_status[i];
}
delete board;
delete position_status;
return 0;
}
This code is about a snakes and ladders game.
Let me know if you need the class player because I used it on the class board.

How to initialize static member array with a result of a function?

I'm translating such fragment of this Python file to C++:
SIDE = 3
LINES = []
for y in range(SIDE):
row = tuple((x, y) for x in range(SIDE))
LINES.append(row)
for x in range(SIDE):
col = tuple((x, y) for y in range(SIDE))
LINES.append(col)
LINES.append(tuple((x, x) for x in range(SIDE)))
LINES.append(tuple((SIDE - x - 1, x) for x in range(SIDE)))
LINES holds (x, y) coordinates of possible lines in Tic Tac Toe game. So for SIDE = 3 it holds:
[((0, 0), (1, 0), (2, 0)),
((0, 1), (1, 1), (2, 1)),
((0, 2), (1, 2), (2, 2)),
((0, 0), (0, 1), (0, 2)),
((1, 0), (1, 1), (1, 2)),
((2, 0), (2, 1), (2, 2)),
((0, 0), (1, 1), (2, 2)),
((2, 0), (1, 1), (0, 2))]
SIDE value can change.
What I've tried
Performance is crucial (that's why I reached for C++), so I would like to calculate LINES only once. Thus, I've chosen to implement LINES as a static member of the class TicTacToeState.
I started with such code:
static char init_lines() {
return 'a';
}
class TicTacToeState {
static char LINES;
};
char TicTacToeState::LINES = init_lines();
It works. How to change LINES to an array? Maybe vector will be better? With pairs?
Maybe static member is not the best choice, maybe there is an easier way?
How would you translate it to C++?
We know the size of LINES, it's always 2 * SIDE + 2.
Special requirement
All C++ code must be in one .cpp file, no headers. Why? Because this is fragment of a library for bot competitions and it's typical that you can submit only one file.
In C++ you can initialize static array members using group initialization
static int a[10] = {5}; //this will initialize first position item with 5 and rest with 0s
static char b[2] = {'b', 'b'};
static int c[2][2] = { {1,1}, {1,2} };
int main()
{
cout<< a[0] << endl; //output: 5
cout<< a[1] << endl; //output: 0
cout<< b[0] << endl; //output: b
cout<< c[0][1] << endl; //output: 1
}
Although the fact is you need to know size of the array not like in Python's list that are dynamically
If you need to insert to the table values calculated dynamically the best way to do this is to create factory method
static int** fact(int width, int height)
{
int** a;
a = new int*[width]; //we can do it when it is DYNAMIC array!
a[0] = new int[height];
a[1] = new int[height];
for(int i = 0; i < width; i++)
for(int k = 0; k < height; k++)
a[i][k] = i*k;
return a;
}
static int** c = fact(2, 2); //you can call it with your SIDE var
int main()
{
cout<< c[1][1] << endl; //output: 1
}
Of course you can process it in loops
The same approach will be proper when you will decide to use std Vector class which is equvalent of Python's dynamic list
I suppose you could do this using a lambda function like this:
#include <vector>
#include <iostream>
const auto SIDE = 3U;
struct coord
{
unsigned x;
unsigned y;
coord(unsigned x, unsigned y): x(x), y(y) {}
};
static const auto lines = [] // lambda function
{
// returned data structure
std::vector<std::vector<coord>> lines;
for(auto y = 0U; y < SIDE; ++y)
{
lines.emplace_back(); // add a new line to back()
for(auto x = 0U; x < SIDE; ++x)
lines.back().emplace_back(x, y); // add a new coord to that line
}
for(auto x = 0U; x < SIDE; ++x)
{
lines.emplace_back();
for(auto y = 0U; y < SIDE; ++y)
lines.back().emplace_back(x, y);
}
lines.emplace_back();
for(auto i = 0U; i < SIDE; ++i)
lines.back().emplace_back(i, i);
lines.emplace_back();
for(auto i = 0U; i < SIDE; ++i)
lines.back().emplace_back(SIDE - i - 1, i);
return lines;
}(); // NOTE: () is important to run the lambda function
int main()
{
for(auto const& line: lines)
{
std::cout << "(";
for(auto const& coord: line)
std::cout << "(" << coord.x << ", " << coord.y << ")";
std::cout << ")\n";
}
}
Output:
((0, 0)(1, 0)(2, 0))
((0, 1)(1, 1)(2, 1))
((0, 2)(1, 2)(2, 2))
((0, 0)(0, 1)(0, 2))
((1, 0)(1, 1)(1, 2))
((2, 0)(2, 1)(2, 2))
((0, 0)(1, 1)(2, 2))
((2, 0)(1, 1)(0, 2))

Wrong shortest distance BFS algorithm?

I am doing this problem http://community.topcoder.com/stat?c=problem_statement&pm=2915&rd=5853, but my program gives wrong output, I tried more ways and it does not work properly. I do not get it, because other people do it like me and they are fine. Can you please check if I have properly implemented the BFS? Thanks in advance.
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
#define P push
#define PP pop();
#define T front();
int mo[][2] = { {-2, -1}, {-2, 1}, {2, -1}, {2, 1}, {-1, -2}, {1, -2}, {-1, 2}, {1, 2} };
int m[8][8];
int BFS(int sy, int sx, int fy, int fx)
{
queue<int> s;
m[sy][sx] = 1;
s.P(sy);
s.P(sx);
s.P(0);
while(!s.empty())
{
int d = s.T s.PP
int x = s.T s.PP
int y = s.T s.PP
for(int i=0;i < 8;i++)
{
int yy = y + mo[i][0];
int xx = x + mo[i][1];
if(yy < 0 || yy > 7 || xx < 0 || xx > 7) continue;
if(m[yy][xx] != -1) continue;
if(yy == fy && xx == fx) return d + 1;
m[yy][xx] = 0;
s.P(yy);
s.P(xx);
s.P(d+1);
}
}
return -1;
}
class CaptureThemAll {
public:
int fastKnight(string knight, string rook, string queen) {
vector<int> p{knight[0] - 'a', knight[1] - '1', rook[0] - 'a', rook[1] - '1', queen[0] - 'a', queen[1] - '1'};
memset(m, -1, sizeof(m));
int a = BFS(p[1], p[0], p[3], p[2]);
memset(m, -1, sizeof(m));
int b = BFS(p[1], p[0], p[5], p[4]);
memset(m, -1, sizeof(m));
int c = BFS(p[3], p[2], p[5], p[4]);
return min(a,b) + c;
}
};
I think the problem might be that you push y,x,d so your queue will be
Front y Middle x End d
But when you pop the front element you place it (y) into a variable called d.
It may work better if you change:
int d = s.T s.PP
int x = s.T s.PP
int y = s.T s.PP
to
int y = s.T s.PP
int x = s.T s.PP
int d = s.T s.PP