I've created a simple game in C++ in which a player must avoid being bitten by zombies to survive.
The zombies are stored as Z characters in an array called zeds.
I am trying to write a function that can check if any zombies collide, and act accordingly.
I've written this if statement:
for (int i; i < MAXZEDS; ++i);
if (zeds[i].x == zeds[i].x && zeds[i].y == zeds[i].y)
{
--zlives;
updateLives();
}
Obviously it doesn't work, I'm just wondering if I can somehow rewrite this to only decrement zlives if a zombie collides with another zombie but NOT itself.
Apologies for the title I couldn't find a better way to summarize my issue. Thanks in advance for any help.
You need a double loop so you can compare two different zombies.
Something like this.
for (int i = 0; i < MAXZEDS - 1; ++i)
{
// Looping from i + 1 ensures that we only test each pair once.
for (int j = i + 1; j < MAXZEDS; ++j)
{
if (zeds[i].x == zeds[j].x && zeds[i].y == zeds[j].y)
{
--zlives;
updateLives();
}
}
}
The simplest way is 2 loops.
for (int i = 0; i < MAXZEDS; ++i) {
for (int j = i+1; j < MAXZEDS; ++j) {
if (zeds[i].x == zeds[j].x && zeds[i].y == zeds[j].y)
{
--zlives;
updateLives();
}
}
}
If the object order in zeds is not important, and operator<() is defined correctly for the element type of zeds, then you could sort zeds and check consecutive elements to get lower complexity.
Try using nested for loops:
for (int i = 0; i < MAXZEDS; i++)
{
for (int j = 0; j < MAXZEDS; j++)
{
if (i == j) continue; // Don't compare the current zed with itself
else if (zeds[i].x == zeds[j].x && zeds[i].y == zeds[j].y)
{
--zlives;
updateLives();
}
}
}
This iterates through zeds twice and compares each item in the array with each other item. I am sure there are more efficient ways, but this is the simplest.
Related
I have a std::vector<std::unique_ptr<object>> myObjects_ptrs. I need to, starting in one of my objects, circle back again to where I started.
I am doing this as follows:
while(true)
{
for(int i = 0; i < myObjects_ptrs.size(); ++i)
{
myObjects_ptr[i]->doSomething();
//and here I need to circle back
for(int j = i + 1; j < myObjects_ptr.size(); ++j)
{
//do some things with each other object
}
for(int j = 0; j < i; ++j)
{
//do the same things with the rest of the objects
}
}
}
Is this the standard way of doing that? My problem is that once I detect something, then I dont need to keep going around. For example if I find something during the first loop then there is no need to go through the second loop. I con solve this by adding an extra if before the second loop; but is there a better way?
You could use a modulus, i.e. the two inner loops would become:
int numObjects = myObjects_ptr.size();
for (int j = i + 1; j < numObjects + i + 1; ++j)
{
// Get object
auto& obj = myObjects_ptr[j % numObjects];
}
You could replace the two inner loops with something like this:
for(int j = i + 1;; j++)
{
j %= myObjects_ptr.size();
if (j == i)
{
break;
}
// Do stuff
}
I'm trying to make a merging algorithm and it works fine except for one thing: a single tile can merge twice in one move so 4224 becomes 8400 instead of 4440 when I move left.
I've tried adding a break statement at the end of the else if block and adding a flag if a tile has merged but none of these things helped. I sincerely apologise for any mistakes that I might have made but this is my first post on stackoverflow.
#define TILES_X 4
#define TILES_Y 4
//Moving UP with SDL library
for (int i = 0; i < TILES_X; i++) {
for (int j = 1; j < TILES_Y; j++) {
if (gameBoard[i][j] != 0) {
for (int k = 0; k < j; k++) {
if (gameBoard[i][k] == 0) {
gameBoard[i][k] = gameBoard[i][j];
gameBoard[i][j] = 0;
}
else if (gameBoard[i][k] == gameBoard[i][j] && (gameBoard[i][k+1]==0||gameBoard[i][k+1]==gameBoard[i][k])) {
gameBoard[i][k] = 2 * gameBoard[i][j];
gameBoard[i][j] = 0;
}
}
}
}
}
I am trying to get the summary of CFG with given input. I have to list the terminals with the count of how many times it appears in the rule. However, I'm having trouble with it counting multiple terminals on the same rule.
for (int i = 0; i < cfg.size(); i++)
{
for (int j = 0; j < cfg[i].size(); j++)
{
for (int k = 0; k < terminal.size(); k++)
{
if (strcmp(cfg[i][j].c_str(), terminal[k].c_str()) == 0)
{
//TO-DO if counter[k] already incremented do not increment counter[k] again
counter[k]++;
break;
}
}
}
}
For example if the rule is
Z -> a b b b
It will return 3 for b when the correct answer would be 1.
Any help on how I can how I can leave that rule after it has already been counted would be great. Thank you
I'm not sure if I understand what you mean, but maybe changing the loops order would help?
for (int i = 0; i < cfg.size(); ++i)
{
for (int k = 0; k < terminal.size(); ++k)
{
for (int j = 0; j < cfg[i].size(); ++j)
{
if (strcmp(cfg[i][j].c_str(), terminal[k].c_str()) == 0)
{
++counter[k];
break;
}
}
}
}
I want to get rid of this goto statement. Can any one tell me the logic for the same. The code below is not the exact code that I want to modify, but it will support my question. Please don't ask the significance of the code when commenting on this post as it is just an example.
int result[i][j];
for (int i = 0; i<100; i++)
{
for (j = 0; j<100; j++)
{
result[i][j] = j++;
if (j == 80)
goto break1;
}
}
break1:
…;
Put those loops in a function, give it a proper name and return; when it is done. If it is complicated enough to need two loops, it deserves a name.
A finished flag is so hard to read that you should put that construct in its own function anyway, making it obsolete.
Exceptions are only for errors you cannot handle locally. Use them to notify higher level functions that something you cannot fix went wrong, not if something that was supposed to happen happened.
I would see three possible solutions.
Put the code into a function and leave that function with return
Use a "finished" flag like already demonstrated well in the answers by Michel Keijzers, Bas in het Feld and EvilTeach.
(C++ only) surround the code-section with a try-catch-block and throw and exception when you want to leave the code. But keep in mind that exceptions are usually supposed to be used for error-handling. So you should only use this pattern when terminating the loops is the result of an error conditions.
Since you want to break two loops, you have to notify the outer loop. You can do this by having a boolean that checks for that:
bool break_loop = false;
for (int i = 0; i < 100; ++i) {
for (int j = 0; j < 100; ++j) {
if (j == 80) {
break_loop = true;
break;
}
}
if (break_loop) break;
}
Use a boolean to break from the for loop(s).
int result[i][j];
bool cont = 1;
for (int i =0;i<100;i++)
{
for(j = 0;j<100;j++)
{
result[i][j] = j++;
if(j == 80)
{
cont = 0;
break;
}
}
if (cont == 0)
break;
}
break1;
(note: not tested on real compiler).
int result[i][j];
for (int i = 0; i<100; i++)
{
for (j = 0; j<100; j++)
{
result[i][j] = j++;
if (j == 80)
{
i = 100;
break;
}
}
}
I sometimes like changing the control variable(s)
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
/* work */
if (j == 80) i = j = 100; // 100 makes both loops terminate
}
}
int result[i][j];
for (int i = 0; i<100; i++)
{
int j;
for (j = 0; j<100; j++)
{
result[i][j] = j++;
if (j == 80)break;
}
if(j == 80) break;
}
Know this is an old question but can be modified simply
I'm looking to implement a bubble sort. I have the following code that I wrote, which uses a for loop inside of a do loop. How can I make this into a bubble sort that uses two for loops?
Here's my code:
do {
switched = false;
for (int i = 1; i < size; i++) {
if (a[i] < a[i-1]) {
int temp = a[i];
a[i] = a[i-1];
a[i-1] = temp;
switched = true;
}
}
} while (switched);
(This is tagged homework, but this is studying for the final exam, not actual homework.)
Because you know the last element in the list will always be sorted (since it bubbled up to the top) you can stop there.
for(int x = size; x >= 0; x--) {
bool switched = false;
for(int i = 1; i < x; i++) {
if(blah) {
// swap code here
switched = true;
}
}
if(!switched) break; // not the biggest fan of this but it gets the job done
}
A bit obligate, but hey, you asked for it:
for(bool switched=true; switched;)
{
switched = false;
for (int i = 1; i < size; i++) {
if (a[i] < a[i-1]) {
int temp = a[i];
a[i] = a[i-1];
a[i-1] = temp;
switched = true;
}
}
}
Two for loops...
Since the maximum number of times your inner loop will run is size times, you know that the outer loop only can be bound by size.
for (int x = 0; x < size; x++ )
{
switched = false;
for (int i = 1; i < size; i++)
{
if (a[i] < a[i - 1])
{
int temp = a[i];
a[i] = a[i - 1];
a[i - 1] = temp;
switched = true;
}
}
if(switched)
{
break;
}
}
A simple improvement to bubble sort is to remember the last location where a swap occurred. After each pass the elements beyond that point are sorted. Next time through the loop only iterate up to the previous high water mark.
void bubble_sort(int *arr, int size)
{
for (int hwm; size > 1; size = hwm)
{
hwm = 0;
for (int i = 1; i < size; ++i)
{
if (arr[i] < arr[i-1])
{
std::swap(arr[i], arr[i-1]);
hwm = i;
}
}
}
}
You can run the inside loop size times instead of checking switched, by having an outer loop for(int j=0; j<size; ++j). To make it slightly less badly inefficient you can make the inner loop 1 step shorter each time.
The first full pass through the loop (that is, the first iteration of your outer do loop) is guaranteed to put the largest element in position a[size - 1]. (Do you see why?) The next full pass is guaranteed not to change that, and, in addition, to put the second-largest element in position a[size - 2]. (Again, do you see why?) And so on. So the first pass needs i to go from 1 to size - 1, but the second only needs i to go from 1 to size - 2, the third only needs i to go from 1 to size - 3, and so on. Overall, you need at most size - 1 passes (with the last pass just covering position 1 and comparing a[1] to a[0] to make sure the smallest element is in place).
So, your outer for-loop needs to vary max_i, initially set to size - 1 and ending up at 1, and your inner for-loop needs to vary i from 1 to max_i.
Think about the maximum number of times the do loop can execute.
A really silly method to use two for loops would be as follows:
for(bool switched=true;switched;)
{
switched=false;
for(int i=1; i<size; ++i)
{
if (a[i] < a[i-1])
{
int temp = a[i];
a[i] = a[i-1];
a[i-1] = temp;
switched = true;
}
}
}
A more serious answer might be as below... but now that I think about it this probably is not bubble sort:
for(int i=0; i<(size-1); ++i)
{
for(int j=(i+1); j<(size-1); ++j)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}