Called function clears changes of previous one - c++

I'm working on a cellular automaton where changes happen in every rounds. Obviously, I made a loop for it - basically it works, fortunately, but if I want to add another type of cells to the map, one type of cells works, but the other doesn't do anything: the game begins and e.g. in this example, the Conway-automaton starts growing, but the red test-cells are just staying without any changes.
#define fldwidth 110
#define fldheight 140
typedef struct tiles
{
unsigned char red, green, blue;
}tiles;
const tiles TEST_ALIVE = {255,0,0};
const tiles TEST_DEAD = {50,0,0};
const tiles CONWAY_ALIVE = {0,255,0};
const tiles CONWAY_DEAD = {0,50,0};
//Maes módszere a struktúrák egyenlőségének vizsgálatára
bool equality(tiles* a, const tiles* b)
{
if (a->red == b->red && a->green == b->green && a->blue == b->blue)
{
return true;
} else {
return false;
}
}
//sejttípus 1.: tesztsejt: minden magányos vagy túlbuzgó sejt meghal
void Test(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &TEST_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &TEST_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &TEST_ALIVE) == false && counter >= 2)
{
arrb[i][j] = TEST_ALIVE;
}
if (equality(&arra[i][j], &TEST_ALIVE) == true && (counter == 0 || counter > 6))
{
arrb[i][j] = TEST_DEAD;
}
}
}
}
//sejttípus 2.: Conway életjátéka
void Conway(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &CONWAY_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &CONWAY_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &CONWAY_ALIVE) == false && counter == 3)
{
arrb[i][j] = CONWAY_ALIVE;
}
if (equality(&arra[i][j], &CONWAY_ALIVE) == true && (counter != 2 && counter != 3))
{
arrb[i][j] = CONWAY_DEAD;
}
}
}
}
This is content of the loop:
Test(fielda,fieldb);
Conway(fielda,fieldb);
end = false;
round++;
for (j = 0; j < fldheight; j++)
{
for (i = 0; i < fldwidth; i++)
{
fielda[i][j] = fieldb[i][j];
}
}
As I mentioned, in this example, Conway cells grow, but Test cells just stay. How to make them work simultaneously?
(I use Allegro libraries so if that has something for this problem, feel free to share with me!)

Test(fielda,fieldb); sets every cell of fieldb based on the current value of fielda. And then Conway(fielda,fieldb); sets every cell of fieldb based on the current value of fielda, overwriting fieldb so that everything Test did is gone. One way to fix this is to change your loop to:
Test(fielda,fieldb);
Conway(fieldb,fielda); //switched the parameters
end = false;
round++;
//there is no need to copy fieldb to fielda here because Conway already did
But this might not be the right fix depending on exactly how you want test and conway to interact with each other.

Related

C++ adding borders on monsters (C++ text-based game)

void Map::Movement()
{
int ch;
switch (ch = _getch())
{
case KEY_W: //up
if (Player::posy != 1)
{
if (AboveM == false)
{
Player::posy--;
DisplayMap();
}
}
break;
case KEY_S: //down
if (Player::posy != 20)
{
if (BelowM == false)
{
Player::posy++;
DisplayMap();
}
}
break;
case KEY_A: //left
if (Player::posx != 1)
{
if (LeftM == false)
{
Player::posx--;
DisplayMap();
}
}
break;
case KEY_D: //right
if (Player::posx != 20)
{
if (RightM == false)
{
Player::posx++;
DisplayMap();
}
}
break;
I can't for the life of me figure out where to put this so that the borders for the mob will work correctly (first question I know it isn't asked well since I haven't added the rest of the code but it should be simple to figure out)I've been putting it every place I could think of the last week or so as well as trying out everything else I could that would run I either get weird random errors or it runs as if the monster as no borders at all.
if ((Player::posy = Enemy::enemyBuild::posy) && (Player::posx = Enemy::enemyBuild::posx +1))
{
bool RightM = true;
}
if ((Player::posy = Enemy::enemyBuild::posy) && (Player::posx = Enemy::enemyBuild::posx -1))
{
bool LeftM = true;
}
if ((Player::posx = Enemy::enemyBuild::posx) && (Player::posy = Enemy::enemyBuild::posy +1))
{
bool BelowM = true;
}
if ((Player::posx = Enemy::enemyBuild::posx) && (Player::posy = Enemy::enemyBuild::posy -1))
{
bool AboveM = true;
}

Combining for-loops in C++

I am making a GoBoard and want to check if the Black player has won the game. I made four for loops to check, whether there are 5 stones in a row horizontally, vertically or diagonally. I would like to combine them however, to save some lines of code. How to do it? Is it possible to simply check for the White player as well using the same for loops or should I make a new bool for the White player?
class goBoard {
private:
boardSquare* entrance; // A pointer containing the address of the boardSquare-object at the top left of the grid.
void zip (boardSquare*, boardSquare*);
boardSquare* makeRow (); //(int amount)?
int m, n;
public:
//goBoard ();
goBoard (int numberOfRows, int numberOfColumns);
~goBoard ();
void build ();
void computer (char colour);
bool squareEmpty (int x, int y);
void human (char colour);
void print ();
bool done ();
bool won ();
void makeMove (int x, int y, char colour);
};//class goBoardbool
goBoard::wonBlack () {
boardSquare* currentSquare = entrance; //assuming that the player starts at the entrance
bool nextSquare = true;
if ((*currentSquare).colour == 'B') {
for (int i = 0; i <= 4; i++) {
if (nextSquare == true) {
currentSquare = (*currentSquare).neighbours[2]; //.neighbours[2] is a pointer to the square to the right of the current square
if ((*currentSquare).colour != 'B')
nextSquare = false;
}
}
for (int i = 0; i <= 4; i++) {
if (nextSquare == true) {
currentSquare = (*currentSquare).neighbours[4];
if ((*currentSquare).colour != 'B')
nextSquare = false;
}
}
for (int i = 0; i <= 4; i++) {
if (nextSquare == true) {
currentSquare = (*(*currentSquare).neighbours[2]).neighbours[4];
if ((*currentSquare).colour != 'B')
nextSquare = false;
}
}
for (int i = 0; i <= 4; i++) {
if (nextSquare == true) {
currentSquare = (*(*currentSquare).neighbours[6]).neighbours[4];
if ((*currentSquare).colour != 'B')
nextSquare = false;
}
}
if (nextSquare == true)
return true;
}
return false;
}//goBoard::won
If you want to reduce the linecount, I would go for something on this line:
enum class Direction {vertical, horizontal, downRight, upRight};
enum class Sign {negative, zero, positive}
enum class Semen {white, black};
template <typename Elem>
unsigned int howManyInARow(Direction direction, Sign sign, Elem elem, Semen semen){
unsigned int ret = 0;
if(elem == semen){
ret = 1;
}
if(negative != sign)
ret += howManInARow(direction, positive, elem.getNeighbour(direction, positive), semen);
if(positive != sign)
ret += howManInARow(direction, negative, elem.getNeighbour(direction, negative), semen);
return ret;
}
Could'nt test it because I don't have the elements. Give it a try and I can elaborate on it if you like it

I cannot figure out why this while loop is endless [duplicate]

This question already has answers here:
Can anyone tell me why these functions are not giving me a result in a reasonable spectrum?
(2 answers)
Closed 9 years ago.
Here is the code I am currently working with:
bool playCraps(int currentGame, bool detailPrint, char isBetting, int startingBet)
{
bool crapsResult = NULL;
int currentGameStorage[100];
int currentRoll = 1;
int point = roll2Dice();
int printingNumber = 0;
currentGameStorage[0] = point;
if(point == 7 || point == 11)
{
crapsResult = true;
}
else if(point == 2 || point == 3 || point == 12)
{
crapsResult = false;
}
else
{
crapsResult = NULL;
}
while(crapsResult != true || crapsResult != false)
{
currentGameStorage[currentRoll] = roll2Dice();
if(currentGameStorage[currentRoll] == point)
{
crapsResult = true;
}
else if(currentGameStorage[currentRoll] == 7)
{
crapsResult = false;
}
currentRoll += 1;
}
currentRoll -= 1;
if(detailPrint == true)
{
cout << "Game " << currentGame << ": ";
for(printingNumber = 0; printingNumber <= currentRoll; printingNumber += 1)
{
cout << currentGameStorage[printingNumber] << " ";
}
if(crapsResult == true)
{
cout << "win";
}
else if(crapsResult == false)
{
cout << "lose";
}
cout << endl;
}
return crapsResult;
}
Whenever I run it it creates am emdless loop with no text appearing in the terminal. The function roll2Dice() simulates the roll of two six sided dice using the rand() function and adds the two results together. Any help would be appreciated.
Your while test, crapsResult != true || crapsResult != false is necessarily true, and therefore does not terminate. The crapsResult value is either true of false, which will make one of the two halves of the expression true, and one false. Both true || false and false || true evaluate to true.
As others have noted it's pretty obvious why the loop never ends.
Your use of NULL makes me think you wish you could have a bool which could hold three values (unset, true and false). You could achieve this with minimal changes by using a pointer to bool, but that's pretty disgusting. Enums are what you really need:
enum CrapsResult
{
unrolled,
true_result,
false_result
};
The pertinent code then becomes*:
CrapsResult crapsResult = unrolled;
int currentGameStorage[100];
int currentRoll = 1;
int point = roll2Dice();
int printingNumber = 0;
currentGameStorage[0] = point;
if(point == 7 || point == 11)
{
crapsResult = true_result;
}
else if(point == 2 || point == 3 || point == 12)
{
crapsResult = false_result;
}
else
{
crapsResult = unrolled;
}
while(crapsResult == unrolled)
{
currentGameStorage[currentRoll] = roll2Dice();
if(currentGameStorage[currentRoll] == point)
{
crapsResult = true_result;
}
else if(currentGameStorage[currentRoll] == 7)
{
crapsResult = false_result;
}
currentRoll += 1;
}
*I haven't actually compiled this.
while(crapsResult != true || crapsResult != false)
equals to
while(crapsResult == false || crapsResult == true)
.
//while(crapsResult == (false || true)) // Don´t matter
so as boolean has only false or true
it will always evaluate true and equals to this expression
while(true)
In C and C++, expressions can resolve to true or false based on the following: 0 is false, everything else is true. The formal definition of C's macros FALSE and TRUE is #define FALSE 0 and #define TRUE (!(FALSE)).
A variable of type bool can either be true or false. You initialize your crapsResult with the value of NULL. NULL is a macro defined as 0UL or 0ULL, which evaluates to false.
bool crapsResult = NULL;
is equivalent to
bool crapsResult = false;
So when your code does the following:
while (crapsResult != true || crapsResult != false)
one of these conditions is always met, so the loop always repeats.
You will need a second variable, presumably of type bool, to determine if you have an acceptable answer.
bool crapsResult = false;
bool haveCrapsResult = false;
int currentGameStorage[100];
int currentRoll = 1;
int point = roll2Dice();
int printingNumber = 0;
currentGameStorage[0] = point;
if(point == 7 || point == 11)
{
crapsResult = true;
haveCrapsResult = true;
}
else if(point == 2 || point == 3 || point == 12)
{
crapsResult = false;
haveCrapsResult = false;
}
while(!haveCrapsResult)
{
currentGameStorage[currentRoll] = roll2Dice();
if(currentGameStorage[currentRoll] == point)
{
crapsResult = true;
haveCrapsResult = true;
}
else if(currentGameStorage[currentRoll] == 7)
{
crapsResult = false;
haveCrapsResult = true;
}
currentRoll += 1;
}
currentRoll -= 1;
if(detailPrint == true)
{
cout << "Game " << currentGame << ": ";
for(printingNumber = 0; printingNumber <= currentRoll; printingNumber += 1)
{
cout << currentGameStorage[printingNumber] << " ";
}
if(crapsResult == true)
{
cout << "win";
}
else /*if(crapsResult == false) is redundant */
{
cout << "lose";
}
cout << endl;
}
return crapsResult;

Called function clears changes of previous one

I'm working on a cellular automaton where changes happen in every rounds. Obviously, I made a loop for it - basically it works, fortunately, but if I want to add another type of cells to the map, the whole thing doesn't work! I mean, one type of cells works, but the other doesn't do anything: The game begins and e.g. in this example, the Conway-automaton starts growing, but the red test-cells are just staying without any changes.
These are the two functions (with predefined things):
#define fldwidth 110
#define fldheight 140
//struktúra, aztán a sejtek definíciója
typedef struct tiles
{
unsigned char red, green, blue;
}tiles;
const tiles TEST_ALIVE = {255,0,0};
const tiles TEST_DEAD = {50,0,0};
const tiles CONWAY_ALIVE = {0,255,0};
const tiles CONWAY_DEAD = {0,50,0};
//Maes módszere a struktúrák egyenlőségének vizsgálatára
bool equality(tiles* a, const tiles* b)
{
if (a->red == b->red && a->green == b->green && a->blue == b->blue)
{
return true;
} else {
return false;
}
}
//sejttípus 1.: tesztsejt: minden magányos vagy túlbuzgó sejt meghal
void Test(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &TEST_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &TEST_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &TEST_ALIVE) == false && counter >= 2)
{
arrb[i][j] = TEST_ALIVE;
}
if (equality(&arra[i][j], &TEST_ALIVE) == true && (counter == 0 || counter > 6))
{
arrb[i][j] = TEST_DEAD;
}
}
}
}
//sejttípus 2.: Conway életjátéka
void Conway(tiles arra[fldwidth][fldheight], tiles arrb[fldwidth][fldheight])
{
int a,b,i,j,counter;
for (j=1;j<fldheight-1;j++)
{
for (i=1;i<fldwidth-1;i++)
{
if (equality(&arra[i][j], &CONWAY_ALIVE) == true)
{
counter = -1;
} else {
counter = 0;
}
for (b=j-1;b<=j+1;b++)
{
for (a=i-1;a<=i+1;a++)
{
if (equality(&arra[a][b], &CONWAY_ALIVE) == true)
{
counter+=1;
}
}
}
arrb[i][j] = arra[i][j];
//itt a sejtek szabályai jönnek; mindig a születést tesszük előre, utána a halált!
if (equality(&arra[i][j], &CONWAY_ALIVE) == false && counter == 3)
{
arrb[i][j] = CONWAY_ALIVE;
}
if (equality(&arra[i][j], &CONWAY_ALIVE) == true && (counter != 2 && counter != 3))
{
arrb[i][j] = CONWAY_DEAD;
}
}
}
}
and this is the loop itself:
while(!end)
{
al_wait_for_event_timed(event_queue,&asd,0.001); //várakozás
if(asd.type == ALLEGRO_EVENT_KEY_DOWN)
{
if(asd.keyboard.keycode == ALLEGRO_KEY_ENTER)
{
Test(fielda,fieldb);
Conway(fielda,fieldb);
end = false;
round++;
for (j = 0; j < fldheight; j++)
{
for (i = 0; i < fldwidth; i++)
{
fielda[i][j] = fieldb[i][j];
}
}
}
}
for (j = 0; j < fldheight; j++)
{
for (i = 0; i < fldwidth; i++)
{
al_draw_filled_rectangle(20 + (4*i), 20 + (4*j), 24 + (4*i), 24 + (4*j), al_map_rgb(fielda[i][j].red, fielda[i][j].green, fielda[i][j].blue));
}
}
}
Can you tell me what is wrong with it? Or maybe the problem is not in the loop?
Your problem is that the second function you call reverses all the changes made by the first function. That is why you see only one working.
The best way to get both working it to let each function operate only on one colour channel. Test uses only the red colour channel (both for reading and changing), while Conway uses only the green colour channel. Be prepared to see cells with different colours: these were affected by both functions.

C++ Rectangle to rectangle Collision

I'm having a really bad time here looking for the error in my code.
My collision detection won't work here even the algorithm I searched in Google.
void PollEvents()
{
for (int i = 0;i < NUMBER_OF_BLOCKS; ++i)
{
Rectangle& a = blocks[i];
if (mouse.state == GLFW_PRESS)
{
//look for any block to grab
if (mouse.leftClick && !blocks[selectedBlock].Grab() &&
a.Hover(mouse.pos.x, mouse.pos.y))
{
//prevent grabbing another block
if (i != selectedBlock) {
selectedBlock = i;
}
a.Grab() = true;
if (a.IsTypeHorizontal()) {
diff = mouse.pos.x - a.Left();
} else {
diff = mouse.pos.y - a.Top();
}
}
if (a.Grab())
{
for (int j = 0;j < NUMBER_OF_BLOCKS; ++j)
{
//skip for any self-checking
if (i == j) continue;
Rectangle& b = blocks[j];
//check for rectangle collision
if (!a.Collide(b) || b.Collide(a)) {
//j++;
//how does this block will move.
if (a.IsTypeVertical()) {
a.SetY(mouse.pos.y - diff);
} else {
a.SetX(mouse.pos.x - diff);
}
} else {
switch (a.sideHit)
{
case UP:
//a.SetY(b.Bottom());
printf("UP\n");
break;
case DOWN:
//a.SetY(b.Top() + a.GetHeight());
printf("DOWN\n");
break;
case LEFT:
//a.SetX(b.Right());
printf("LEFT\n");
break;
case RIGHT:
//a.SetX(b.Left() - a.GetWidth());
printf("RIGHT\n");
break;
}
}
//check for bound collision
a.BoundCheck(1.f);
}
}
} else {
a.Grab() = false;
}
}
}
Collision detection:
bool Rectangle::Collide(const Rectangle& r) {
if (IsTypeHorizontal()) {
if (r.Hover(Left(), Top()) && r.Hover(Right(), Top())) {
sideHit = UP;
return true;
} else if (r.Hover(Right(), Bottom()) && r.Hover(Left(), Bottom())) {
sideHit = DOWN;
return true;
}
// } else if (r.Hover(Left(), Top())) {
// sideHit = UP;
// return true;
// } else if (r.Hover(Right(), Top())) {
// sideHit = UP;
// return true;
// } else if (r.Hover(Right(), Bottom())) {
// sideHit = DOWN;
// return true;
// } else if (r.Hover(Left(), Bottom())) {
// sideHit = DOWN;
// return true;
// }
} else {
if (r.Hover(Left(), Top()) && r.Hover(Left(), Bottom())) {
sideHit = LEFT;
return true;
} else if (r.Hover(Right(), Top()) && r.Hover(Right(), Bottom())) {
sideHit = RIGHT;
return true;
}
// } else if (r.Hover(Left(), Top())) {
// sideHit = LEFT;
// return true;
// } else if (r.Hover(Left(), Bottom())) {
// sideHit = LEFT;
// return true;
// } else if (r.Hover(Right(), Top())) {
// sideHit = RIGHT;
// return true;
// } else if (r.Hover(Right(), Bottom())) {
// sideHit = RIGHT;
// return true;
// }
}
return false;
}
Code for Hover:
inline float Hover(float X, float Y) const {
return X >= Left() &&
X <= Right() &&
Y >= Bottom() &&
Y <= Top();
}
I'm trying to make my own unblockme.
Please help me on my collision-detection. It's been 3 days now since I got stuck in this problem.
UPDATE
I have found out the problem why all rect-rect collision detection won't work in my program.
Bug:
if (!a.Collide(b)) {
//Move()
} else {
//Resolve collision
}
This one should be
if (!Rectangle::Collide(a, b)) {
//Move()
} else {
//Resolve collision
}
Making the Collide() a static member of Rectangle because, as you can see in my implementation of Collide(), it bases its decision on its own member so a.Hover(b.x, b.y) doesn't make any sense.
Hope this helps a little bit to all newbies like me.
To do rect/rect collision detection, if any of one (edges parallel to x and y axis) rect's four points is inside the other rect, we have a collision.
An easier way than to check each of the four points is to check if one X edge is between both the other rect's X edges, and if one Y edge is between both the other rect's Y edges - if both are true, we have a collision (because the two edges must meet at a point inside of the other rect). So we just check this in both directions:
bool isclamped(float mid, float A, float B)
{
if (A > B)
{
return mid >= B && mid <= A;
}
return mid >= A && mid <= B;
}
bool checkcollisiononeway(rect rectA, rect rectB)
{
if (isclamped(rectA.left, rectB.left, rectB.right)
|| isclamped(rectA.right, rectB.left, rectB.right))
&& (isclamped(rectA.bottom, rectB.bottom, rectB.top)
|| isclamped(rectA.top, rectB.bottom, rectB.top))
{
return true;
}
return false;
}
bool checkcollisionbothways(rect rectA, rect rectB)
{
return checkcollisiononeway(rectA, rectB) || checkcollisiononeway(rectB, rectA);
}
To determine the angle of collision after detecting a collision, find the angle between their two centers using atan2(rectA.y - rectB.y, rectA.x - rectB.x) (the angle is returned in radians, not in degrees)