Add selected elements to list using for loop - c#

I'm trying to add the integers 6 from 30, except for 22 and 26, to a List using a for loop. But 22 and 26 are still being added. What did I do wrong?
List<int> lineNumbers = new List<int>();
for (int x = 6; x < 30; x++)
{
if ((x != 22) || (x != 26))
{
lineNumbers.Add(x);
}
}
The two integers are not added if the code is like below:
for (int x = 6; x < 30; x++)
{
if (x == 22 )
{
}
else if (x == 26)
{
}
else
{
lineNumbers.Add(x);
}
}

You need to replace the || with &&:
for (int x = 6; x < 30; x++)
{
if ((x != 22) && (x != 26))
{
lineNumbers.Add(x);
}
}
Or perhaps, to be more clear:
for (int x = 6; x < 30; x++)
{
if ((x == 22) || (x == 26))
continue;
lineNumbers.Add(x);
}
Alternatively, you could perform this as a one-liner using LINQ. This isn't necessarily faster or anything, so if your for loop is clearer to you, then keep it as-is.
lineNumbers.AddRange(Enumerable.Range(6, 24).Except(new[] { 22, 26 }));

Change your conditions. Use && instead of ||
if ((x != 22) && (x != 26))

Use && instead of || because you want to match between both conditions.
if ((x != 22) && (x != 26))
You can also do this using LINQ (not necessarily but I like LINQ :)
var lineNumbers = Enumerable.Range(6, 30).Except(new[] {22, 26}).ToList();

Replace if ((x != 22) || (x != 26)) to if ((x != 22) && (x != 26))
Or you can use continue like below :
for (int x = 6; x < 30; x++)
{
if ((x == 22) || (x == 26))
continue;
else
lineNumbers.Add(x);
}

Related

Can I execute only specific portion of nested if else in c#?

This is not the actual code but it's what I want to do.
for loop is must but the nested if else loop inside should be executed according to the value of count_final which can be random between 1 to 3.
Like if the value of count_final is 3, all if...else loop should be considered. but if the value of count_final is 2, then only if...(1st)else if and else part only be executed. And if count_final=1 then only if and else part is executed (not any else-if).
Thought of putting another if...else within every if...else and checking count_final, but what if I'm not getting values of count2 and count3 when count_final=1.
Same, when count_final=2, I'm not getting the value of count3.
Ask in comment if you don't understand my question.
int count_final=Session["abc"];
//count_final=1;
//count_final=2;
//count_final=3;
for(int i=1;i<=10;i++)
{
if ((count1 <= count5) && (count1 <= count6))
{
Label1.Text="Hello1";
}
else if (count2 <= count4 && count2 <= count6)
{
Label2.Text="Hello2";
}
else if (count3 <= count4 && count3 <= count5)
{
Label3.Text="Hello3";
}
else
{
Label1.Text="Hello1";
}
}
Seems you have collection of "conditions" where amount of executed conditions depend on value of finalCount.
var rules = new Func<string>[]
{
() => (count1 <= count5 && count1 <= count6) ? "Hello1" : null,
() => (count2 <= count4 && count2 <= count6) ? "Hello2" : null,
() => (count3 <= count4 && count3 <= count5) ? "Hello3" : null
};
Label1.Text = rules.Take(finalCount)
.Select(rule => rule())
.Where(result => result != null)
.DefaultIfEmpty("Hello1")
.First();
Of course this solution is assuming that finalCount is always 1, 2 or 3.
DefaultIfEmpty is playing role of last else - will be used all conditions fails.
if i understand right.. which is a little unlikely
just add more criteria to your ifs!
if ((count1 <= count5) && (count1 <= count6))
{
if (count_final == 3 || count_final == 2) Label1.Text="Hello1";
}
else if (count2 <= count4 && count2 <= count6)
{
if (count_final == 3) Label2.Text="Hello2";
}
else if (count3 <= count4 && count3 <= count5)
{
if (count_final == 3) Label3.Text="Hello3";
}
else
{
if (count_final == 3 || count_final == 1) Label1.Text="Hello1";
}
Remembering that from what I understood there will be loops in that can achieve nothing, eg, if count_final == 2 and its not less or equal to count5 or count6, nothing will happen, same as for count_final == 1, if it matches any of the first bits the last else wont happen.
I suggest extending the conditions of your else if statements:
int count_final=Session["abc"];
//count_final=1;
//count_final=2;
//count_final=3;
for(int i=1; i<=10; i++)
{
if ((count1 <= count5) && (count1 <= count6))
{
Label1.Text="Hello1";
}
else if (count_final >= 2 && count2 <= count4 && count2 <= count6)
{
Label2.Text="Hello2";
}
else if (count_final >= 3 && count3 <= count4 && count3 <= count5)
{
Label3.Text="Hello3";
}
else
{
Label1.Text="Hello1";
}
}
When count_final == 1 this will not try to evaluate count2, count3 or count4 (which I understand is a requirement) because && will not evaluate its right hand side when there is false on the left.
Is this what you are looking for? To use less if/else statements:
int count_final = Session["abc"]; // random between 1 and 3
for(int i=1; i <= 10; i++)
{
switch(count_final)
{
case 3:
Label1.Text="Hello1";
// no break; so all gets executed
case 2:
Label2.Text="Hello2";
case 1:
Label3.Text="Hello3";
default: Label1.Text="Hello1";
}
}

recursive stackoverflow minesweeper c#

I am writing a game of minesweeper. Below is code for 3 methods in minesweeper. The first method is to check all the spaces around the button pressed and to count how many bombs are around it. The next method is to be called recursively, in order that if the user pressed a button with 0 buttons around it, it will open all of the squares that also indicate 0 squares around it. The third method is to check that it will be in bound the check. The empty space recursive call is getting me a stackoverflow error, what am I doing wrong?
Thanks!
private int GameLogicChecker(int x, int y)
{
int count = 0;
if (_grid[x, y] != -1)
{
if (x + 1 < SizeX)
{ //Right
if (_grid[x + 1, y] == -1)
count++;
}
if (x - 1 > 0)
{ //Left
if (_grid[x - 1, y] == -1)
count++;
}
if (y + 1 < SizeY)
{ //Upper
if (_grid[x, y + 1] == -1)
count++;
}
if (y - 1 > 0)
{ //Lower
if (_grid[x, y - 1] == -1)
count++;
}
if (x + 1 < SizeX && y + 1 < SizeY)
{ //Right-Upper
if (_grid[x + 1, y + 1] == -1)
count++;
}
if (x + 1 < SizeX && y - 1 > 0)
{ //Right-Lower
if (_grid[x + 1, y - 1] == -1)
count++;
}
if (x - 1 > 0 && y + 1 < SizeY)
{ //Left-Upper
if (_grid[x - 1, y + 1] == -1)
count++;
}
if (x - 1 > 0 && y - 1 > 0)
{ //Left-Lower
if (_grid[x - 1, y - 1] == -1)
count++;
}
}
return count;
}
void OpenEmptySpace(int x, int y)
{
for (var k = -1; k <= 1; k++)
{
for (var l = -1; l <= 1; l++)
{
if (CheckBounds(x + k, y + l) && GameLogicChecker(x + k, y + l) == 0)
{
_buttons[x + k, y + l].Text = "0";
OpenEmptySpace(x + k, y + l);
}
}
}
}
private bool CheckBounds(int x, int y)
{
return x >= 0 && x < SizeX && y >= 0 && y < SizeY;
}
For k = 0 and l = 0, you are calling yourself again and again and again...
Thanks to #BenVoigt for pointing out that two zeroes adjacent to each other will also lead to infinite recursion. So, in order to solve that one method is to create a boolean grid too and set a particular cell's value to true if it has been run through once. Assuming the grid is called Explored, I've added the condition for it in the code below.
If you insist on your current code, try changing the condition to:
if (CheckBounds(x + k, y + l)
&& GameLogicChecker(x + k, y + l) == 0
&& !(k == 0 && l == 0)
&& !Explored[x + k, y + l])
{
Explored[x + k, y + l] = true;
_buttons[x + k, y + l].Text = "0";
OpenEmptySpace(x + k, y + l);
}
Here is another answer for you, rewriting your methods one-by-one following better coding practices. Like in the other answer, a boolean grid called Explored[SizeX, SizeY] has been assumed.
1. GameLogicChecker()
private int GameLogicChecker(int x, int y)
{
if (_grid[x, y] == -1) return 0;
int count = 0;
if (x + 1 < SizeX && _grid[x + 1, y] == -1) //Right
{
count++;
}
if (x - 1 > 0 && _grid[x - 1, y] == -1) //Left
{
count++;
}
if (y + 1 < SizeY && _grid[x, y + 1] == -1) //Upper
{
count++;
}
if (y - 1 > 0 && _grid[x, y - 1] == -1) //Lower
{
count++;
}
if (x + 1 < SizeX && y + 1 < SizeY && _grid[x + 1, y + 1] == -1) //Right-Upper
{
count++;
}
if (x + 1 < SizeX && y - 1 > 0 && _grid[x + 1, y - 1] == -1) //Right-Lower
{
count++;
}
if (x - 1 > 0 && y + 1 < SizeY && _grid[x - 1, y + 1] == -1) //Left-Upper
{
count++;
}
if (x - 1 > 0 && y - 1 > 0 && _grid[x - 1, y - 1] == -1) //Left-Lower
{
count++;
}
return count;
}
What's better? Quicker returning from the method for special case. Reduced nesting in If(...) blocks.
2. OpenEmptySpace()
public/private void OpenEmptySpace(int x, int y)
{
for (var deltaX = -1; deltaX <= 1; deltaX += 2)
{
for (var deltaY = -1; deltaY <= 1; deltaY += 2)
{
var thisX = x + deltaX;
var thisY = y + deltaY;
if (OpeningNotNeeded(thisX, thisY))
{
continue;
}
Explored[thisX, thisY] = true;
_buttons[thisX, thisY].Text = "0";
OpenEmptySpace(thisX, thisY);
}
}
}
private bool OpeningNotNeeded(int x, int y)
{
return !CheckBounds(x, y)
|| GameLogicChecker(x, y) != 0
|| Explored[x, y];
}
What's better? Properly named indexing variables in both loops. Properly written condition (+= 2 instead of ++). Reduced nesting in If(...). Easier to read method call in the If(...) instead of three predicates. Useful temporary variables added which make it clear what x + k and y + l were in the code written earlier.
3. CheckBounds() is written fine.

C# IndexOutOfRange Array Exception

I'm trying to create a 2D char array to hold a grid of chars which will be used as a sort of 'map' for a 2D console game.
I am getting a:
IndexOutOfRange exception
..and cannot see why. I've stepped through the code in debug mode and still cannot see the issue.
It steps through the code fine until it hits X = 25 and Y = 1, the upper right boundary of my grid.
I have _gameWidth and _gameHeight created as follows, outside of main but still inside the class:
static int _gameWidth = 25;
static int _gameHeight = 15;
Following is the code that fails, when trying to generate and populate the grid. It fails at this point:
else if (x == _gameWidth && y == 1)
_grid[x, y] = '╕';
static void GenerateGrid()
{
for (int y = 1; y <= _gameHeight; y++)
{
for (int x = 1; x <= _gameWidth; x++)
{
if (x == 1 && y == 1)
_grid[x, y] = '╒';
else if (x == _gameWidth && y == _gameHeight)
_grid[x, y] = '╛';
else if (x == _gameWidth && y == 1)
_grid[x, y] = '╕';
else if (x == 1 && y == _gameHeight)
_grid[x, y] = '╘';
else if ((x != 1 && y == _gameHeight) || (x != _gameWidth && y == 1))
_grid[x, y] = '═';
else if ((x == 1 && y > 1 && y < _gameHeight) || (x == _gameWidth && y > 1 && y < _gameHeight))
_grid[x, y] = '│';
else
_grid[x, y] = 'x';
}
Console.WriteLine("");
}
}
Change
for (int i = 1; i <= gameHeight; i++)
to
for (int i = 0; i < gameHeight; i++)
and do the same for width.
EDIT:
This is because array indexes start at the number 0 and end with the length of the array minus 1.
This exception means that you have accessed an invalid index. From the way you have written the loop I can tell that you think that indexes go from 1 to the length of the array. Arrays are zero-based, though. Use the standard loop form:
for (int i = 0; i < length; i++)
Your loop starts at one. You can use the Visual Studio for loop template. Just type "for<tab><tab>".
Your program might benefit from the Code Review Stack Exchange site.

Re-factor common code between if and else if [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have an if...else if statement as follows:
If(x > y && order.invoice != 1)
{
DoSomething();
x = x + y;
}
else if(order.invoice == 1)
{
x = x + y;
}
Is there a better way to re-factor this. I kind of not feeling well having x = x + y in both if and else if.
if (order.invoice != 1 && x > y) {
DoSomething();
}
if (order.invoice == 1 || x > y) {
x = x + y;
}
You can either do the assignment twice or do one of the if statements twice. This calculation is simple enough that I wouldn't worry about it.
It can be shortened as such, though:
if(x > y && order.invoice != 1)
{
DoSomething();
x += y;
}
else if(order.invoice == 1)
{
x += y;
}
One more option could be to use an flag to see whether or not to increment, but you still have the same tug-of-war between complexity and single calls vs. simplicity and semi-redundant code.
bool increment = false;
if(x > y && order.invoice != 1)
{
DoSomething();
increment = true;
}
else if(order.invoice == 1)
{
increment = true
}
if (increment) { x += y; }
Here's a proof/systematic way to refactor it. Start with:
if (x > y && order.invoice != 1)
{
DoSomething();
x = x + y;
}
else if (order.invoice == 1)
{
x = x + y;
}
So the question is, what set of inputs leads to x = x + y? Well:
x = x + y
<=> (x > y && order.invoice != 1) ||
(!(x > y && order.invoice != 1) && order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
((x <= y || order.invoice == 1) && order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
((x <= y && order.invoice == 1) || (order.invoice == 1 && order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
((x <= y && order.invoice == 1) || order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
order.invoice == 1
<=> (x > y || order.invoice == 1) && (order.invoice != 1 || order.invoice == 1)
<=> (x > y || order.invoice == 1)
Thus it's equivalent to
if (x > y && order.invoice != 1)
{
DoSomething();
}
if (x > y || order.invoice == 1)
{
x = x + y;
}
You can also use a truth table
x > y | order.invoice == 1 | x = x + y
F | F | N
F | T | Y
T | F | Y
T | T | Y
which again gives you
x = x + y
<=> !(x <= y && order.invoice != 1)
<=> x > y || order.invoice == 1
Lastly, I disagree with this sort of refactoring unless it actually makes the code more understandable.
Saving lines of code doesn't mean you made the code more readable (and therefore does not make it
obviously more maintainable)

Replace buttons location

l have problem with my c# winform project.
In my project I have a function that switches the location of buttons to their old location if they are in the same area.
private void myText_MouseUp(object sender, MouseEventArgs e)
{
Point q = new Point(0, 0);
Point q2 = new Point(0, 0);
bool flag = false;
int r = 0;
foreach (Control p in this.Controls)
{
for (int i = 0; i < counter; i++)
{
if (flag)
{
if (p.Location.X == locationx[i] && p.Location.Y == locationy[i])
{
oldx = e.X;
oldy = e.Y;
flag = true;
r = i;
}
}
}
}
foreach (Control p in this.Controls)
{
for (int j = 0; j < counter; j++)
{
if ((locationx[j] == p.Location.X) && (locationy[j] == p.Location.Y))
{
Point arrr = new Point(oldx, oldy);
buttons[j].Location = arrr;
buttons[r].Location = new Point(locationx[j], locationy[j]);
}
}
}
}
The problem with this code is that if they are in the same area, the buttons do not switch their locations. Instead they goes to the last button location.
If someone could help me that will help me alot :)
The if statement always evaluates to true. This means that the final j loop will do this:
// last time round the i loop, i == counter-1
// and q == new Point(locationx[counter-1], locationy[counter-1])
for (int j = 0; j < counter; j++)
{
Point q2 = new Point(locationx[j], locationy[j]);
buttons[i].Location = q2;
buttons[j].Location = q;
}
The net result of this is that every button's Location is set to q, which is
new Point(locationx[counter-1], locationy[counter-1])
Why does the if statement always evaluate to true. Well, first of all let's look at a couple of the or clauses in the if statement:
|| ((q.Y >= q2.Y) && (q.X <= q2.X))
|| ((q.Y >= q2.Y) && (q.X == q2.X))
This is equivalent to
|| ((q.Y >= q2.Y) && (q.X <= q2.X))
The line containing the == test has absolutely no impact on the final result of the condition. In fact all the lines containing == can be similarly treated. This leaves:
|| ((q.Y >= q2.Y) && (q.X <= q2.X))
|| ((q.Y >= q2.Y) && (q.X >= q2.X))
|| ((q.Y <= q2.Y) && (q.X >= q2.X))
|| ((q.Y <= q2.Y) && (q.X <= q2.X))
We can condense
|| ((q.Y >= q2.Y) && (q.X <= q2.X))
|| ((q.Y >= q2.Y) && (q.X >= q2.X))
into
|| ((q.Y >= q2.Y)
and similarly
|| ((q.Y <= q2.Y) && (q.X >= q2.X))
|| ((q.Y <= q2.Y) && (q.X <= q2.X))
is the same as
|| ((q.Y <= q2.Y)
Combine
|| ((q.Y >= q2.Y)
|| ((q.Y <= q2.Y)
and you can see that the if condition always evaluates to true.

Categories