For loop just... not starting? - c++

This is a bizarre problem. I've got a void function that performs a for loop and nothing else, but the for loop doesn't ever start, even though the function is being called. Here is the function:
void Cell::Consolidate()
{
cout << "Consolidating (outside)...\n";
for(int i = 0; i < m_Tiles.size(); ++i)
{
cout << "Consolidating (inside)...\n";
int row = m_Tiles[i]->GetRow();
int col = m_Tiles[i]->GetCol();
//Check below.
if((*m_pTileMap)[row + 1][col].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row + 1][col].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row + 1][col].pParentCell);
}
}
//Check above.
else if((*m_pTileMap)[row - 1][col].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row - 1][col].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row - 1][col].pParentCell);
}
}
//Check the right.
else if((*m_pTileMap)[row][col + 1].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row][col + 1].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row][col + 1].pParentCell);
}
}
//Check the left.
else if((*m_pTileMap)[row][col - 1].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row][col - 1].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row][col - 1].pParentCell);
}
}
}
}
When I run the program, "Consolidating (outside)...\n" gets send to cout, but "Consolidating (inside)...\n" does not. Nothing that is supposed to happen in the loop actually happens, either (for example the SetColor() calls don't do anything, nor does anything happen if I send things to cout anywhere else in the loop), so I can only assume the loop is not starting at all. Why not? What could cause this?

i < m_Tiles.size()
This loop condition gets checked on entrance to the loop, not only after each iteration. If your m_Tiles vector is empty, well, no loop for you.

Most likely, m_Tiles.size() returns a negative value or zero value.

Related

Anonymous Function which returns different types C++

I want to create an anonymous function which takes in an int and a set as parameters, and either modify the set (be a void) or return false based on the int. Is it possible to do?
Code is here. You can see the repetitive if statements which bother me.
bool sudoku2(std::vector<std::vector<char>> grid) {
std::set<char> row, col, block;
for (std::size_t i = 0; i < grid.size(); i++) {
for (std::size_t j = 0; j < grid[i].size(); j++) {
if (grid[i][j] != '.') {
if (row.find(grid[i][j]) == row.end()) {
row.insert(grid[i][j]);
} else {
return false;
}
}
if (grid[j][i] != '.') {
if (col.find(grid[j][i]) == col.end()) {
col.insert(grid[j][i]);
} else {
return false;
}
}
if (grid[i/3*3 + j/3][i%3*3 + j%3] != '.') {
if (block.find(grid[i/3*3 + j/3][i%3*3 + j%3]) == block.end()) {
block.insert(grid[i/3*3 + j/3][i%3*3 + j%3]);
} else {
return false;
}
}
}
row.clear();
col.clear();
block.clear();
}
return true;
}

Delete enemy from vector array

This is my first question on this site. I learn programming for a year and I always found a answer for my problem in projects. I know that this is REALLY simple problem and here is a code:
#include "stdafx.h"
#include "Wave.h"
Wave::~Wave()
{
}
void Wave::setEnemyCount(int count) {
nemyCount = count;
}
bool Wave::createWave() {
for (int i = 0; i < enemyCount; i++) {
enemyArray.push_back(Enemy());
}
for (int i = 0; i < enemyArray.size(); i++) {
int randomPositionX = rand() % 150 + 10;
int randomPositionY = rand() % 50 + 10;
if (!enemyArray.at(i).init(randomPositionX, randomPositionY)) {
std::cout << "Create wave(init enemies) - failed\n";
return false;
}
}
return true;
}
void Wave::drawWave(Window* window) {
window->setCursor({ 0, 2 });
window->setColor(Window::Color::RED);
std::cout << "Enemies: " << enemyArray.size();
window->setColor(Window::Color::WHITE);
for (int i = 0; i < enemyArray.size(); i++) {
enemyArray.at(i).draw(window);
//std::cout << i;
}
}
void Wave::update(Bullet* bullet, Player* player) {
for (int i = 0; i < enemyArray.size(); i++) {
if (player->checkShoot()) {
if ((bullet->getPositionX() >= enemyArray.at(i).getPositionX() && bullet->getPositionX() <= enemyArray.at(i).getPositionX() + 5)) {
if ((bullet->getPositionY() >= enemyArray.at(i).getPositionY() && bullet->getPositionY() <= enemyArray.at(i).getPositionY() + 5)) {
player->addScore(10);
enemyArray.erase(enemyArray.begin() + i);
}
}
}
}
if (enemyArray.size() <= 0) {
std::cout << "WAVE COMPLETE";
Sleep(2000);
enemyCount += 5;
createWave();
}
}
int Wave::getEnemyCount() const {
return enemyCount;
}
The collision work correct, but when bullet touch a enemy of index for example: 5, a code always remove the enemy of last index, so I can remove each enemy only shoot to one enemy with index 5 or 1 or 7.
When you do enemyArray.erase(...) you shouldn't increment i because you will skip one element.
So you should rewrite the loop like this:
for (int i = 0; i < enemyArray.size();) {
if (player->checkShoot()) {
if ((bullet->getPositionX() >= enemyArray.at(i).getPositionX() && bullet->getPositionX() <= enemyArray.at(i).getPositionX() + 5)) {
if ((bullet->getPositionY() >= enemyArray.at(i).getPositionY() && bullet->getPositionY() <= enemyArray.at(i).getPositionY() + 5)) {
player->addScore(10);
enemyArray.erase(enemyArray.begin() + i);
continue;
}
}
}
++i;
}
Or, with a more idiomatic style:
for (auto it = enemyArray.begin(), end = enemyArray.end();it!=end;) {
if (player->checkShoot()) {
if ((bullet->getPositionX() >= it->getPositionX() && bullet->getPositionX() <= it->getPositionX() + 5)) {
if ((bullet->getPositionY() >= it->.getPositionY() && bullet->getPositionY() <= it->getPositionY() + 5)) {
player->addScore(10);
enemyArray.erase(it);
continue;
}
}
}
++it;
}
Of course, if you wan a single enemy to be removed at a time, you should break instead of continue in the loop, after having erased the element.
For completeness, you can also use std::remove_if if you want to remove all enemies touched by the bullet, it's more optimal than the 2 loops above, because it does less moving of elements when multiple elements are removed.

Huffman coding c++

So I am working on Huffman coding for a project. However, my code just doesn't work. When i ran it on visual studio, it didn't give me an error. What I was trying to do is to read a file and put all of them into a string. And get the frequency for each character in that string. But I think when the file got a little bit large, it seems like my code is running in a infinite loop. Can anyone explain anything to me? By the way, I had a sorted function that I used to sort a vector of node* by their frequency.
ifstream infile;
infile.open(filename);
string q;
string line;
while (getline(infile, line))
{
q += line;
}
char y;
int count = 0;
int check = 0;
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
}
}
if (check == 0)
{
for (int i = 0; i < q.size(); i++)
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}
sort(list1.begin(), list1.end(), sorter); //sort them from small to big
while (list1.size() > 1)
{
node*left = list1[0];
node*right = list1[1];
list1.erase(list1.begin(), list1.begin() + 2);
double sum = left->freq + right->freq;
node* x = new node;
x->freq = sum;
x->left = left;
x->right = right;
list1.push_back(x);
sort(list1.begin(), list1.end(), sorter);
}
list1.clear();
return true;
The following is my sort function
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() != '\0') {
return (int)a->getCharacter() < (int)b->getCharacter();
}
return false;
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
I see two major problems.
You have a for loop inside a for loop both initializing and using int i
Change the variable name of the inner loop.
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
.
.
if (check == 0)
{
for (int i = 0; i < q.size(); i++) //Change this to int j for example
{
.
.
And the Sorter struct. I would rewrite it as this.
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() == '\0') return true;
return (int)a->getCharacter() < (int)b->getCharacter();
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
A few suggestions for your for loop:
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
//You can avoid this entire loop by using a structure like map
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
//break; //if you use a loop, break it once you find the character.
}
}
if (check == 0)
{
for (int j = 0; j < q.size(); j++)//Renamed variable + you can start this loop from j = i as you know there is no occurrence of y before that.
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}

Checking for overlapping characters in a wordsearch game

I am developing a wordsearch generator to learn c++ better and I am stuck on preventing non-overlapping words from overlapping, such as a side-to-side word writing over a letter in a top-down word. Here is the code snippet:
else if (random_choice == 1 && random_word.size() <= 10-j && words_vector.size() != 0) {
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i][j+x] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
j += 1;
}
j -= 1;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
What I have done was create a two dimensional array [10][11] filled with the 0 (zero) character so when I iterate through it all spaces are filled with 0 except for the 11th space in each line with a newline character to make a 10X10 grid. In my else if loop, the first part already has a word chosen and it tests if the word will fit in its proper space by checking if a 0 is present. If it runs into a non-zero character (such as if it runs into a letter from a top-down or diagonal word) the inner loop terminates, sets the boolean flag, and inputs a 1 (or any random letter) instead of the whole word. What happens is that the whole word is inserted anyways and overwrites one letter from the top down word. What am I doing wrong? Here is the rest of the code:
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
srand(time(NULL));
const char* const a_to_z = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
int random_char;
char wordsearch [10][11] = {0};
bool flag;
string words_array[] = {"CAT", "HELLO", "GOODBYE", "DOG", "BAT", "NEW", "SAY", "MAY", "DAY", "HAY"};
vector<string> words_vector (words_array, words_array + sizeof(words_array) / sizeof(string));
string words_found_array[] = {};
vector<string> words_found_vector (words_found_array, words_found_array + sizeof(words_found_array) / sizeof(string));
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 11; j++) {
int random_choice = rand() % 5;
int random_word_number = rand() % words_vector.size();
string random_word = words_vector[random_word_number];
if (j == 10) {
wordsearch[i][j] = '\n';
}
else if (random_choice == 1 && random_word.size() <= 10-j && words_vector.size() != 0) {
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i][j+x] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
j += 1;
}
j -= 1;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
else if (random_choice == 2 && random_word.size() <= 10-i && words_vector.size() != 0) {
int temp_i = i;
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i+x][j] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
i += 1;
}
i = temp_i;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
else {
int random_char = rand() % 26 + 0;
wordsearch[i][j] = a_to_z[random_char];
}
}
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 11; j++) {
cout<<wordsearch[i][j];
}
}
cout<<"Your words are:"<<endl;
for (int x = 0; x < words_found_vector.size(); x++) {
cout<<words_found_vector[x]<<endl;
}
}
One more thing:
//words_vector.erase(words_vector.begin()+random_word_number);
crashes my program. I think it is a scoping issue with this:
int random_choice = rand() % 5;
int random_word_number = rand() % words_vector.size();
string random_word = words_vector[random_word_number];
What I want to do is eventually have the user give me a list of words they want to search for and this function chooses some of them and presents it to the user when playing the game. This not functioning correctly also causes duplicates to appear in the crossword and words-to-find-list.
Thank you for your help!
You have this error twice in your code:
if (flag = true)
That is not a condition, it's an assignment. It assigns true to flag, and the if-block will always execute. You need to make it a comparison condition by using ==
if (flag == true)
A more common way to write that in C++ would be just
if (flag)

Game of Life array edges acting weird

I saw Conway's Game of Life and decided to make my own.
I have a bool array to represent the world, but the edges (Top and bottom) are acting weird, random cells becomes live.
In this code, it does not print the bottom and top of the world, but this is a bad solution.
The world "wraps" at the right and the left, causing even more problems, but that is for another time.
#include <iostream>
const int height = 20;
const int width = 20;
bool now_world[height][width];
bool then_world[height][width];
void clear_world();
void place_random_live_cells();
void then_world_initialization();
void print_world();
void generation_pass();
void update_worlds();
int main(int argc, const char * argv[])
{
using namespace std;
srand((unsigned)time(NULL));
int timer = 0;
int generation = 0;
clear_world();
place_random_live_cells();
then_world_initialization();
bool running = true;
while (running) {
if (timer == 50000000) {
cout << "Generation #" << generation << endl;
print_world();
generation_pass();
update_worlds();
++generation;
timer = 0;
}
++timer;
}//While (running) ends here
return 0;
}
void place_random_live_cells()
{
int percent = 30;
int max_live_cells = ((height * width) / 100) * percent;
int current_live_cells = 0;
while (current_live_cells < max_live_cells) {
int ycoords = 0 + (rand() % (height + 1));
int xcoords = 0 + (rand() % (width + 1));
if (now_world[ycoords][xcoords] == false) {
now_world[ycoords][xcoords] = true;
} else {
current_live_cells--;
}
++current_live_cells;
}
}
//A generation pass and cells die and some cells come to life
void generation_pass()
{
using namespace std;
int neighbours = 0;
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii+1][jjj ] == true) {
++neighbours;
}
if (now_world[iii+1][jjj-1] == true) {
++neighbours;
}
if (now_world[iii ][jjj+1] == true) {
++neighbours;
}
if (now_world[iii ][jjj-1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj ] == true) {
++neighbours;
}
if (now_world[iii-1][jjj-1] == true) {
++neighbours;
}
//Apply rules to the cells
//Dead cells with three live neighbours becomes alive
if (then_world[iii][jjj] == false && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with fewer than two, they die
if (then_world[iii][jjj] == true && neighbours < 2) {
then_world[iii][jjj] = false;
}
//Alive with 2 or three live neighbours live on unchanged
if (then_world[iii][jjj] == true && neighbours == 2) {
then_world[iii][jjj] = true;
}
if (then_world[iii][jjj] == true && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with more than three, they die
if (then_world[iii][jjj] == true && neighbours > 3) {
then_world[iii][jjj] = false;
}
//Dead cells without exactly three live neighbours remain dead
//Reset neighbour value to zero
neighbours = false;
}
}
}
//Make next generation identical to current
//This is only called once
void then_world_initialization()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
then_world[iii][jjj] = now_world[iii][jjj];
}
}
}
//Make the next generation be today
//This is called every generation
void update_worlds()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = then_world[iii][jjj];
}
}
}
//Set all cells to dead
void clear_world()
{
for (long iii = 0; iii < height; iii++) {
for (long jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = false;
then_world[iii][jjj] = false;
}
}
}
//Print world
void print_world()
{
using namespace std;
char live = 'X';
char dead = '.';
for (long iii = height; iii > 0; iii--) {
for (long jjj = width; jjj > 0; jjj--) {
if (iii != 0 && iii != height) {
if (now_world[iii][jjj]) {
cout << live;
} else {
cout << dead;
}
cout << " ";
}
}
cout << endl;
}
cout << endl;
}
Having done this for a course I taught in the past, the most common issue I always see people having is going outside the bounds of the array they're using.
If you look at the if statements in your nested for loop, I think you'll find some issues. For instance, in this case, what happens when iii equals (height-1) or jjj equals (width-1)?
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
You're going outside the bounds of your array and so your results will be undefined. You may get segfaults, but you may just also get spurious data. C++ doesn't enforce you staying within the bounds of the array you define.
Make sure you also handle cases like this:
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
What if iii equals zero?
Hope that helps.
You're trying to access out-of-boundary indexes in your array.
I'm not sure what behaviour you expect, but an easy way is to not calculate updates for cells on the edges.
So in generation_pass the loops should go from 1 till height-1.