I have a function that is causing my program to hang. I have commented out the function and everything else runs just fine. The program gets to where the loop should end and it just waits for input. The isBomb() function is simply a getter and returns a true/false value. The function is part of a Minesweeper game. I am trying to figure out a way to figure out how many bombs are adjacent to the chosen cell. I could post the whole program, but it is around 250-350 lines. The makeNum method is a simple getter that sets the cell number equal to the value of the parameter.
void mazeDisplay::countBombAdj(int row, int col) {
int counter = 0;
/* for (int x = row - 1; x < row + 1; x++) {
while ((x > - 1) && (x < 4)) {
for (int y = col - 1; y < col + 1; y++) {
while ((-1 < y) && (y < 4)) {
if (mazeCells[x][y].isBomb() == true)
counter += 1;
}
}
}
}*/
mazeCells[row][col].makeNum(counter);
}
It's your line:
while ((x > - 1) && (x < 4))
x dosn't change and there aren't any break's in that loop so the loop is infinite.
Similarly for:
while ((-1 < y) && (y < 4))
It looks like, as others have commented, that you what if statements, not (infinite) while loops:
void mazeDisplay::countBombAdj(int row, int col) {
int counter = 0;
for (int x = row - 1; x < row + 1; x++) {
if ((x > - 1) && (x < 4)) {
for (int y = col - 1; y < col + 1; y++) {
if ((-1 < y) && (y < 4)) {
if (mazeCells[x][y].isBomb() == true)
counter += 1;
}
}
}
}
mazeCells[row][col].makeNum(counter);
}
Once you've entered one of your while-loops, the condition will never become false and you're stuck in it forever.
Also, checking those conditions with if instead would lead you to only scan a three-by-three square, which is a very boring minesweeper game.
You need to check if you're inside the board, not within that small square.
I would loop over the appropriate range instead of skipping invalid cells:
for (int x = std::max(0, row-1); x < std::min(number_of_rows, row+2); x++)
{
for (int y = std::max(0, col-1); y < std::min(number_of_cols, col+2); y++)
{
if (mazeCells[x][y].isBomb())
counter += 1;
}
}
Related
This function in the Game of Life assignment is supposed to loop through the 2nd array and check to see how many neighbors each cell has. When I call this in the main, not even in any sort of loop, the terminal freezes as if in an infinite while loop. Can anyone tell me what's wrong with my code? Thanks.
void Grids::simulate(int** myGrid, int rows, int columns)
{
int neighbors = 0; //variable to store how many neighbors a cell has
for (int r = 0; r < rows; ++r) // iterates through rows
{
for(int c = 0; c < columns; ++c)//iterates through columns
{
for(int x = -1; x < 2; x + 2) //iterates through -1 and 1, the spaces next to the cell
{
for(int y = -1; y < 2; y + 2)
{
if ((r + x >= 0) && (r + x < rows) && (c + y >= 0) && (c + y < columns)) //prevents indexing the 2d array outside of its bounds
{
if (myGrid[r + x][c + y] == 1) //checks if the surrounding cells are alive
{
++neighbors;
}
}
}
}
if (neighbors < 2) //underpopulation
{
myGrid[r][c] = 0; //dead
}
else if (neighbors == 3) //reproduction
{
myGrid[r][c] = 1; //alive
}
else if (neighbors >= 4) //overpopulation
{
myGrid[r][c] = 0; //dead
}
}
}
}
You should change this x + 2 to x += 2 and y + 2 to y += 2, to make the loop increase by 2 each cycle. I also advise you to remove extra parentheses in this line if (r + x >= 0 && r + x < rows && c + y >= 0 && c + y < columns).
So I'm relatively new to coding in SFML, so apologies if I made some newbie mistake. My project is Space Invaders in SFML. When I was working on the shooting, a problem arose. How do I do collision? I was familiar with shape.getGlobalBounds().intersect(), and it worked on previous projects. It didn't work. So I tried simplifying it. I used RectangleShape for both the enemy shape, and the bullet shape.
Here is the actual for loop, for the collision:
for (int y = 0; y <= 2; ++y) {
for (int x = 0; x <= 6; ++x) {
if (shootShape.getPosition().x < e.aliensX[x] && shootShape.getPosition().x > e.aliensX[x] + 15 ||
shootShape.getPosition().y < e.aliensY[y] && shootShape.getPosition().y > e.aliensY[y] + 15) {
e.aliensX[x] = -10;
e.aliensY[y] = -10;
shooting = false;
reload = false;
}
}
}
This is the shooting function:
void Player::shoot() {
if (reload) {
shootX = posX + 5;
shootY = posY - 50;
shootShape.setPosition(shootX, shootY);
shooting = true;
reload = false;
}
if (shooting) {
shootY -= 150 * 2 * deltaTime;
shootShape.setPosition(shootX, shootY);
}
}
And this is how I draw the enemies (I don't know how to create multiple enemies):
void Enemy::drawAliens() {
for (int j = 0; j <= arraySizeY; ++j) {
for (int i = 0; i <= arraySizeX; ++i) {
actualShape.setPosition(aliensX[i], aliensY[j]);
if (aliensY[i] <= p.shootY && aliensY[i] >= p.shootY) {
aliensX[i] = -10;
aliensY[i] = -10;
}
else {
win.draw(actualShape);
}
}
}
}
Explanation behind some of the variables:
aliensX is an array which contains the different x positions for the enemies.
aliensY is an array which contains the different y positions for the enemies.
shooting is a bool variable, which is true when the bullet is travelling.
reload is whether you can shoot.
EDIT:
Intersect will not work because of the way I created my enemies. They are all in ONE shape. I need it to work with specific coordinates, because I don't know a better way to create multiple enemies all at once. If there is a way to do that, advice would be appreciated!
It's rather easy, if you rely on SFML's templated sf::Rect class. Just retrieve the rectangle for both objects as global boundaries and try to intersect them:
const bool collides = firstDrawable.getGlobalBounds().intersect(secondDrawable.getGlobalBounds());`
Same can be done with a small temporary rectangle you can fill with dynamic values not directly associated with a sf::Drawable:
const sf::FloatRect bullet(x - width / 2, y - height / 2, width, height);
const bool collides = firstDrawable.getGlobalBounds().intersect(bullet);`
Your if statement is never true. You have
shootShape.getPosition().x < e.aliensX[x] && shootShape.getPosition().x > e.aliensX[x] + 15.
Your shootShape.getPosition().x can never be smaller than e.aliensX[x] and bigger than e.aliensX[x] + 15 at the same time. That's impossible. The same for y position. Change your if statement to
for (int y = 0; y <= 2; ++y) {
for (int x = 0; x <= 6; ++x) {
if (shootShape.getPosition().x > e.aliensX[x] && shootShape.getPosition().x < e.aliensX[x] + 15 ||
shootShape.getPosition().y > e.aliensY[y] && shootShape.getPosition().y < e.aliensY[y] + 15) {
e.aliensX[x] = -10;
e.aliensY[y] = -10;
shooting = false;
reload = false;
}
}
}
I have two grey scale images in txt files, one being a smaller block of the Main image. I have read the images into two different 2d vector matrices.
The Rows and the Columns of the images are:
Main: M = 768 N = 1024
SubImg: R = 49 C = 36
int R = 49; int C = 36; //Sub Image Rows / Columns
int M = 768; int N = 1024; //Main Image Rows / Columns
I want to loop through the Main image by blocks of width: 49 and height: 36 and put each block into an array, so I can compare the array with the Sub image (using Nearest Neighbor Search) to see which block has the closest result to the Sub image.
The problem I am having is that I cannot get the loop to display all of the blocks. When I run the loop only a certain number of block appear and the program clashes.
// Testing Main 2D Vector in block format
for (int bx = 0; bx < M; bx += R)
for (int by = 0; by < N; by += C)
{
for (int x = 0; x < R; ++x)
{
for (int y = 0; y < C; ++y)
{
cout << MainIMG_2DVector[bx + x][by + y] << " ";
}
}
cout << "\n\n" << endl;
}
Can someone please tell me what I have done wrong.
Thanks
EDIT +++++++++++++++++++++++++++++++++++++++++
After debugging
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
M=768 is not divisible by R=49, the last loop starts with bx=735 (15*49) and should ends to bx=735+48=783 > 768... Same problem in N=1024 and C=36 by=1008 (28*36) to by=1008+35=1043 > 1024. – J. Piquard
If I increase the width and the height, my main image stretch. Is there a way around this?
Two ways could be explored:
Way 1 - change the value R (and C) to the best divider of M (and N)
int M = 768; int N = 1024; //Main Image Rows / Columns
int R = 48; int C = 32; //Sub Image Rows (768=16*48) / Columns (1024=32*32)
Way 2 - prevent out of range error in the for-loop exit condition
For x, both conditions (x < R) and ((bx + x) < M)) shall be
true.
And for y, both conditions (y < C) and ((by + y) < N)) shall be
true.
for (int x = 0; ((x < R)&&((bx + x) < M)); ++x)
{
for (int y = 0; ((y < C)&&((by + y) < N)); ++y)
{
if ((bx + x)>=M) {
std::cout << (bx + x) << (by + y) << " ";
}
}
}
Instead of:
for (int x = 0; x < R; ++x)
{
for (int y = 0; y < C; ++y)
{
if ((bx + x)>=M) {
std::cout << (bx + x) << (by + y) << " ";
}
}
}
To represent all the cells I'm using a variable std::vector<bool> cells to represent the cells where true represents a live cell. To update the canvas, I have a variable std::vector<int> neighborCounts, where neighborCounts[i] represents how many live neighbors cell[i] has. In the update loop, I loop through all the cells, and if its a live cell, I add 1 to the neighborCounts of all the adjacent cells. Then after determining all of the neighbors, I once again loop through all the cells and perform the updates based on the number of neighbors it has.
std::vector<int> neighborCounts(NUM_ROWS * ROW_SIZE, 0);
for (int x = 0; x < ROW_SIZE; x++)
{
for (int y = 0; y < NUM_ROWS; y++)
{
if (cells[convertCoord(x, y)])
{
for (int m = x - 1; m <= x + 1; m++)
{
for (int n = y - 1; n <= y + 1; n++)
{
if (!(m == x && n == y) && m >= 0 && m < ROW_SIZE && n >= 0 && n < NUM_ROWS)
{
neighborCounts[convertCoord(m, n)] += 1;
}
}
}
}
}
}
for (int x = 0; x < ROW_SIZE; x++)
{
for (int y = 0; y < NUM_ROWS; y++)
{
int coord = convertCoord(x, y);
int numNeighbors = neighborCounts[coord];
if (cells[coord])
{
if (numNeighbors < 2)
{
cells[coord] = false;
}
else if (numNeighbors > 3)
{
cells[coord] = false;
}
}
else
{
if (numNeighbors == 3)
{
cells[coord] = true;
}
}
}
}
Then in the render function, I loop through all the cells and if its alive I draw it to the screen.
This seems to be the most straightforward way to do this, but there's definitely room for further optimization. How do powder toys and other apps manage a huge array of particles and yet still manage to run amazingly smooth? What is the most efficient way to manage all the cells in Conway's Game of Life?
I am building a game of life CA in C++ (openFrameworks). As I am new to C++ I was wondering if someone could let me know if I am setting up the vectors correctly in the following code. the CA does not draw to the screen and I am not sure if this is as a result of how I set up the vectors. I have to use 1D vectors as I intend to send data to Pure Data which only handles 1D structures.
GOL::GOL() {
init();
}
void GOL::init() {
for (int i =1;i < cols-1;i++) {
for (int j =1;j < rows-1;j++) {
board.push_back(rows * cols);
board[i * cols + j] = ofRandom(2);
}
}
}
void GOL::generate() {
vector<int> next(rows * cols);
// Loop through every spot in our 2D array and check spots neighbors
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
// Add up all the states in a 3x3 surrounding grid
int neighbors = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
neighbors += board[((x+i+cols)%cols) * cols + ((y+j+rows)%rows)];
}
}
// A little trick to subtract the current cell's state since
// we added it in the above loop
neighbors -= board[x * cols + y];
// Rules of Life
if ((board[x * cols + y] == 1) && (neighbors < 2)) next[x * cols + y] = 0; // Loneliness
else if ((board[x * cols + y] == 1) && (neighbors > 3)) next[x * cols + y] = 0; // Overpopulation
else if ((board[x * cols + y] == 0) && (neighbors == 3)) next[x * cols + y] = 1; // Reproduction
else next[x * cols + y] = board[x * cols + y]; // Stasis
}
}
// Next is now our board
board = next;
}
this looks weird in your code:
void GOL::init() {
for (int i =1;i < cols-1;i++) {
for (int j =1;j < rows-1;j++) {
board.push_back(rows * cols);
board[i * cols + j] = ofRandom(2);
}
}
}
"vector.push_back( value )" means "append value to the end of this vector" see std::vector::push_back reference
After doing this, you access the value of board[i * cols + j] and change it into a random value. What I think you are trying to do is:
void GOL::init() {
// create the vector with cols * rows spaces:
for(int i = 0; i < cols * rows; i++){
board.push_back( ofRandom(2));
}
}
This is how you would access every element at position x,y in your vector:
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
board[x * cols + y] = blabla;
}
}
This means that in void GOL::generate() you are not accessing the right position when you do this:
neighbors += board[((x+i+cols)%cols) * cols + ((y+j+rows)%rows)];
I think you want to do this:
neighbors += board[((x+i+cols)%cols) * rows + ((y+j+rows)%rows)];
so x * rows + y instead of x * cols + y