Basically what I am trying to do, is compare the selected Index of two combo boxes in Win Forms.
If ComboBoxA.SelectedIndex == 1 and, ComboBoxB.SelectedIndex == 1, I need to prevent that from happening, by changing ComboBoxB.SelectedIndex to 2.
I tried doing this through an If statement and couldn't get the results I was looking for.
if (Northern.SelectedIndex == 1 && NorthernEnd.SelectedIndex == 1)
NorthernEnd.SelectedIndex = 2;
However, I can't seem to get this to work. I am a beginner in C# working on my last assignment of the term.
You can handle the event to prevent the action:
if (Northern.SelectedIndex == 1 && NorthernEnd.SelectedIndex == 1)
e.Handled = true;
Here is the MSDN ref.
Related
I have a DataGridview in which the first column the user inputs a value, and the second column computes an answer, both are then plotted on a chart.
Currently the values in the second column are computed after pressing a "compute button".
However if the user presses the button before they have input any values in the first cells of the first column, the computed values in the cells of the second column come out as "NaN" and the application crashes when the code below runs or if code below is removed the crashes at "Generate Chart button"?
I'm new to C# and programming overall so I'm not sure how to prevent this from happening, perhaps somehow through validation.
This is what I've currently tried (code below), however I get a "System.ArgumentOutOfRangeException: 'Index was out of range."
foreach (DataGridViewRow rw in this.dataGridView3.Rows)
{
for (int G = 0; G < rw.Cells.Count; G++)
{
if (rw.Cells[G].Value == null || rw.Cells[G].Value == DBNull.Value || String.IsNullOrWhiteSpace(rw.Cells[G].Value.ToString()) || double.IsNaN(Convert.ToDouble(dataGridView1.Rows[G].Cells[1].Value)))
{
MessageBox.Show("Please compute Vulnerabiltiy Curve Points!");
}
else
{
chart1.Series["V-curve"].Points.AddXY(dataGridView3.Rows[G].Cells[1].Value, dataGridView3.Rows[G].Cells[0].Value);
}
}
}
I have listview with 3 items and 1 subitems
So I would like to check if a row on item[3] is String.Empty.
if items[3] is empty it will not pass my items[3] to label1.Text.
if items[3] is not empty it will pass my items[3] to my label1.Text
.
this is my code
if (listView1.Items[3].SubItems[1].Text == string.Empty)
{
label1.Text = "";
}
else
{
label1.Text = listView1.Items[3].SubItems[1].Text;
}
when my 3rd row is empty I got an error: InvalidArgument=Value of '3' is not valid for 'index'.
so how do i check the row if its empty and what validation should i do if it's empty i will not pass my items to label1.Text and if its not empty it will pass the Items to label1.Text
You have 3 items, So the maximum index is 2 because the index of the array count from 0.
Same principle for the subitem.
Use Items[2] and SubItems[0]
if (listView1.Items[2].SubItems[0].Text == string.Empty)
Indexes in C# start at 0, so a collection that has 3 items would have the indexes of 0, 1 and 2. Based on your question, your if statement should look like this:
if (listView1.Items[2].SubItems[0].Text == string.Empty)
When trying to access something by its index you should typically have some sort of safety check, like checking the .Length or .Count before attempting to access something that could be out of range. You can also leverage some Linq and the null conditional operator to make things a little safer (albeit slightly slower since its enumerating):
//Skip 2, take the 3rd if its there then take the first SubItem.
//label1.Text is either the text or an empty string
label1.Text = listView1.Items.Skip(2).FirstOrDefault()?.SubItems
.FirstOrDefault()?.Text ?? string.Empty;
I have a list of "Boxes". there is a value called "position" against each box in the list.
When my list of boxes is built, some are given a position (int) . Position is a value used by my code to determine where each box fits on my page.
So, I have a list with 13 boxes, I have one box with position =13 and one with position 4. the rest are currently null.
There is another field called "order" against a box. What I need to do now is order everything that doesn't have a "position" value by the value in "order". (order is not nullable).
Easy so far. However, what I now need to do is loop each value returned and give them a position value. BUT I need to skip over the position values that are already taken (currently 4 and 13).
This is what I am doing:
var orderedBoxes = (from a in boxes
orderby a.Order
where a.Position == null
select a).ToList();
List<int> takenPositions = (from a in boxes
where a.Position != null
select a.Position).ToList();
foreach (var box in orderedBoxes)
{
if (takenPositions.Contains(i))
{
// i++
// box.Position =i;
}
//box.Position =i;
}
i thought this might be ok, but upon reflection, what if takenPositions Does contains i and the value after i++ is also in takenPositions?
I feel I need some form of loop here to test the result of i++ after each increment.
Can anyone offer any help please!!
It might be solved if you'd change
if (takenPositions.Contains(i))
in
while (takenPositions.Contains(i))
It automatically increments until it finds a free position.
Sometimes I use the good old for loop:
int j = 0;
for (int i = 1; i <= boxes.Count; i++)
{
if (takenPositions.Contains(i)) continue;
orderedBoxes[j++].Position = i;
}
Relevant misc info:
Project = Tic Tac Toe (console app)
My issue is the following:
I have an array that initially is filled with 0's which MUST stay as 0's unless the user takes a move (then it'll become a 1) or the computer makes a move then it becomes a 2.
Example code:
else if (posStatus[2] != 0 && posStatus[5] != 0 && posStatus[8] != 0 && (posStatus[2] + posStatus[5] + posStatus[8] % 2 == 0))
{
if (posStatus[2] == 0)
{
posStatus[2] = 2;
return;
}
else if (posStatus[5] == 0)
{
posStatus[5] = 2;
return;
}
else if (posStatus[8] == 0)
{
posStatus[8] = 2;
return;
}
issue:
There is a grid that is 9 long which three rows, 3 columns and two diagonals. Initially all values are set to 0 and this is used to determine if the space is free so changing to another type would cause issues. If the value 1 is held player 1 has played there. If the value 2 is held the computer has played there.
So originally I had put in
posStatus[0] + posStatus[1] + posStatus[2] % 2 == 0)
Which decides where the computer will play in this case it will be the first row if the enemy player has put 2 values there which logically should work perfectly and it does apart from my issue which is as follows:
When nothing is played on a row the values are: 0, 0 ,0 if you do 0 + 0 + 0 % 2 you'll discover that equals 0 which is the parameter for the above condition. This means it will attempt to make sure there is a value in each row/column/diagonal which of course is not good as it means the player can win in 3 turns..
So to combat this I added in (I'm aware I can refactor it) I added:
posStatus[0] != 0 && posStatus[1] != 0 && posStatus[2] != 0
Which means if a row/column/diagonal is empty do not play there which means it never plays in empty rows/columns/diagonals which is an issue.
Suggestions?
You have to check few conditions for each time, need not to consider the sequence. Possible cases of win for any player would be:
0,1,2
0,3,6
0,4,8
1,4,7
2,4,6
2,5,8
3,4,5
AND 6,7,8
I am assuming that numbering is row wise and started from 0.
Now you have to tell computer based on the input of user.
For example:
User has selected 2, so you have posStatus[2] = 1 Now the only cells you have to check are 0,1,4,5 and 6 as these are the only possible cells for win.
To handle the beginning of game situation, you have two options:
Let the user start always.
Start anyone from 0,2,6 and 8 as these are part of the maximum solutions.
Another Approach:
There are 3 possibilities of success:
A. Row wise : Add or substitute number by 1 and check status ,
B. Column wise : Add or substitute number by 3 and check status ,
C. Diagonally : Add or substitute number by 2 AND 4 then check status
For example if user has selected i cell. Your check should be:
A. See the status of (i-2),(i-1),(i+1) AND (i+2) - Obviously this should be in range of 0-8
B. See the status of (i-6),(i-3),(i+3) AND (i+6)
C. See the status of (i-8),(i-4),(i-2),(i+2),(i+4) AND (i+8)
I am trying to figure out a way to get the Computer player to respond to my moves basically by seeing "This spot is taken, I should see if another is free and take it".
So far, I'm not making any improvements (been like 5 hours). I want the computer to realize if a certain button (which it chose at random) is taken, it should consider another choice. Not sure where the if/else should actually go or where/what I should put in for it to try another location.
Here's the snippet of code with comments on my idea (likely wrong placement where I want to do things):
if (c.Enabled == true) //if the button is free
{
if ((c.Name == "btn" + Convert.ToString(RandomGenerator.GenRand(1, 9)) )) //if a specific button is free
{
if ((c.Text != "X")) //if its empty
{
//do this
c.Text = "O"; //O will be inside the button
c.Enabled = false; //button can no long be used
CheckComputerWinner(); //check if it finishes task
return;
}
else //if it is an X
{
//try a different button choice instead
//see if that button is empty
//do stuff
//else
//... repeat until all buttons are checked if free
}
}
}
My question is simply: How can I fix this and understand what is going on? Or do it more efficiently?
You could create an array with those buttons so you don't have to check names:
Button[9] gameField;
Creating a [3,3] array might be more intuitive, but for this case a plain array is easier to work with.
Then, you could count how many of them are free:
int freeCount = gameField.Count(b => b.Text != "X");
If you want to randomly select one of the free ones, generate a random number in the range 0 - (freeCount - 1) and select the appropriate button:
int offset = RandomGenerator.GenRand(0, freeCount - 1);
Button target = gameField.Where(b => b.Text != "X").Skip(offset).FirstOrDefault();
if (target != null) {
// check it
}
The extension method Where filters your buttons to only return the free ones. Skip will skip the specified number of elements (for random selection) and FirstOrDefault returns the first element of the resulting sequence (or null if there is none).
Note: You might want to check for some cases before randomly selecting a field to make your AI a bit more ambitious:
Has the computer player two O in a row with the third field being free? If so, select that one.
Has the human player two X in a row with the third field being free? If so, select that one.
There are tricks to exploit that strategy and there are also better heuristics, but i'll leave that to you.
Your looking for a while loop here. You can modify your code as follows:
Button c;
// here you look for a Button within the Controls of your Form. It stops when an Enabled Button with Text != "X" is found
do
{
c = this.Controls.Find("btn" + Convert.ToString(RandomGenerator.GenRand(1, 9)), true).FirstOrDefault() as Button;
} while (c == null || !c.Enabled || c.Text == "X");
c.Text = "O"; //O will be inside the button
c.Enabled = false; //button can no long be used
CheckComputerWinner(); //check if it finishes task
return;