This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I just completed this code and would like to change the following code to a loop. Each department has a specific button that they are supose to click and should be visible only to those who are within either dept 1, 2, or 3.
Can someone give me some kind of guidence here.
pchk.Visible = true;
Int32 count = 0;
count = chk.GetCount(1);
// dept 1
if (count == -1)
{
btnDept1.Visible = false;
}
else
{
btnDept1.Text = "Next dep1[" + count.ToString() + "]";
if (count == 0)
btnDept1.Enabled = false;
}
// dept 2
count = chk.GetCount(2);
if (count == -1)
{
btnDept2.Visible = false;
}
else
{
btnDept2.Text = "Next dep2 [" + count.ToString() + "]";
if (count == 0)
btnDept02.Enabled = false;
}
// dept 3
count = chk.GetCount(3);
if (count == -1)
{
btnDept3.Visible = false;
}
else
{
btnDept3.Text = "Next dept3 [" + count.ToString() + "]";
if (count == 0)
btnDept3.Enabled = false;
}
}
The biggest challenge with converting this to a loop is getting the btnDept1 values based on a numeric value. One way would be to introduce a method which does this with a switch statement
Button GetButton(int id) {
switch (id) {
case 1: return btnDept1;
case 2: return btnDept2;
...
}
}
Or another approach would be to keep them in an array and use the index to access the array. Either way once you have that you can collapse to a loop in the following way
for (int i = 0; i < TheCount; i++) {
int id = i + 1;
Button button = GetButton(id);
int count = chk.GetCount(2);
if (count == -1) {
button.Visible = false;
} else {
button.Text = String.Format("Next dep{0} [{1}]", id, count);
if (count == 0) {
button.Enabled = false;
}
}
}
for (int i = 1; i <= 3; i++)
{
count = chk.GetCount(i);
if (count == -1)
{
switch (i)
{
case 1:
btnDept1.Visible = false;
break;
case 2:
btnDept2.Visible = false;
break;
case 3:
btnDept3.Visible = false;
break;
}
}
else
{
switch(i)
{
case 1:
btnDept1.Text = "Next dep1[" + count.ToString() + "]";
if (count == 0)
btnDept1.Enabled = false;
break;
case 2:
btnDept1.Text = "Next dep1[" + count.ToString() + "]";
if (count == 0)
btnDept1.Enabled = false;
break;
case 3:
btnDept1.Text = "Next dep1[" + count.ToString() + "]";
if (count == 0)
btnDept1.Enabled = false;
break;
}
}
}
Try something like this:
private void SetButton(int id, Button btn)
{
var count = chk.GetCount(id);
if (count == -1)
{
btn.Visible = false;
}
else
{
btn.Text = String.Format("Next dep{0}[{1}]", id.ToString(), count.ToString());
if (count == 0)
btn.Enabled = false;
}
}
Usage can be something like this:
SetButton(1, btnDept1);
SetButton(2, btnDept2);
SetButton(3, btnDept3);
Of course, if you use an array / list of buttons it can be even easier...
e.g.
Button[] buttons = new Button[] { btnDept1, btnDept2, btnDept3};
for (int i = 0; i < buttons.Length; i++)
SetButton(i, buttons[i]);
Here is an easier, way to get the button you want. Simply append the i value to "btnDept" in ActiveForm.Controls[...]. Check for null, and go to work...
for (int i = 0; i < deptCount; i++)
{
Button b = ActiveForm.Controls["btnDept" + i.ToString()] as Button;
if (b != null)
{
if (count == -1)
{
b.Visible = true;
}
else
{
// etc.
}
}
}
Related
Not sure how stackoverflow questions work, but I am trying to piggy-back off my earlier issue.
I have got rid of all the errors and dig is not null anymore because I actually needed it to have a value and I realized that from people's help earlier but now my function is not being called.
What am I missing??
"Dig" is defined early in my code (public string dig = default;)
private void button1_Click(object sender, EventArgs e)
{
using (StreamWriter objWriter = new StreamWriter("C:\\temp\\Test.txt"))
{
int numpins = int.Parse(textBox1.Text);
string basepin = textBox2.Text;
int pinlength = basepin.Length;
string formatspecifier = "{0:d" + pinlength.ToString() + "}";
long pinnumber = long.Parse(basepin);
for (int d = 0; d < numpins; d++)
{
dig = basepin;
if (dig == null)
{
throw new Exception("null value not allowed");
}
else
{
GetCheckDigit(dig);
}
basepin = string.Format(formatspecifier, pinnumber);
objWriter.WriteLine(basepin);
pinnumber++;
}
objWriter.Close();
}
}
This is my function
private static string GetCheckDigit(string dig)
{
var sum = 0;
var result = true;
var digits = dig.ToCharArray();
for (int i = digits.Length - 1; i >= 0; i--)
{
var num = digits[i] - 48;
if (result)
{
num *= 2;
if (num > 9)
num -= 9;
}
sum += num;
result = !result;
}
if ((sum % 10) == 0)
{
return "0";
}
return (10 - (sum % 10)).ToString();
}
Unless numpins is lower than 0 or basepin is null, GetCheckDigit(dig) is being called.
In case you meant it doesn't output anything to the screen it's because
GetCheckDigit(dig) doesn't output anything to screen, just returns the string.
I have tried to add students to the array through the use of a for loop that checks the current array to make sure that there isn't a student within the array that already has the student's name that is being input.
bool found = false;
for (int i = 0; i < 3; i++)
{
resultMessage.Text = "Hello";
if (newStudent[i] != null)
{
string fullName = newStudent[counter].Name();
if (fullName.ToUpper() == newStudent[i].Name().ToUpper())
{
resultMessage.Text = "Name is already in the system.";
found = true;
}
}
}
if (found == false)
{
if (counter > 2)
{
resultMessage.Text = "Array is full.";
}
else
{
newStudent[counter] = new Student(StudentID.Text, FirstName.Text, MiddleInitial.Text, LastName.Text, HouseNumber.Text, Street.Text, CityCounty.Text, Country.Text,
State.Text, ZipCode.Text, DOB.Text);
resultMessage.Text = "Age: " + newStudent[counter].Age;
}
}
counter++;
The counter is static and is incremented at the end of the button's code. It currently will not pass through the newStudent[i] == null; statement. It goes to it, thinks the array is empty and continues to the next portion of the code. I am not using much of the HTML code, I am doing all of the functionality through the previous code.
I think you should increase counter only while adding a new student, you can do this by returning from the button when a duplicate student is found or maximum counter is reached.
for (int i = 0; i < 3; i++)
{
resultMessage.Text = "Hello";
if (newStudent[i] != null)
{
string fullName = newStudent[counter].Name();
if (fullName.ToUpper() == newStudent[i].Name().ToUpper())
{
resultMessage.Text = "Name is already in the system.";
return;
}
}
}
if (counter > 2)
{
resultMessage.Text = "Array is full.";
return;
}
else
{
newStudent[counter] = new Student(StudentID.Text, FirstName.Text, MiddleInitial.Text, LastName.Text, HouseNumber.Text, Street.Text, CityCounty.Text, Country.Text,
State.Text, ZipCode.Text, DOB.Text);
resultMessage.Text = "Age: " + newStudent[counter].Age;
}
counter++;
I'm trying to use continue; but looks like - incorrect;
Every 3 times I have same "i" value. How can I skip iterator when running if(currentShiftCD != 3 & currentShiftAB == 3) and if(currentShiftDC != 3 & currentShiftBA == 3) for the first time after switching bools firsThreeDays and secondThreeDays
I want output to startlike: 1,2,3,4,5,6..19 but have with same values:
for (int i = 1; i <20; i++)
{
if (firstThreeDays)
{
if (currentShiftAB != 3)
{
currentShiftAB++;
Console.WriteLine(i + " A-B");
}
if (currentShiftCD != 3 & currentShiftAB == 3)
{
currentShiftCD++;
Console.WriteLine(i + " C-D");
}
if (currentShiftAB == 3 & currentShiftCD == 3)
{
firstThreeDays = false;
secondThreeDays = true;
currentShiftAB = 0;
currentShiftCD = 0;
continue;
}
}
if (secondThreeDays)
{
if (currentShiftBA != 3)
{
currentShiftBA++;
Console.WriteLine(i + " B-A");
}
if (currentShiftDC != 3 & currentShiftBA == 3)
{
currentShiftDC++;
Console.WriteLine(i + " D-C");
}
if (currentShiftBA == 3 & currentShiftDC == 3)
{
secondThreeDays = false;
firstThreeDays = true;
currentShiftBA = 0;
currentShiftDC = 0;
continue;
}
}
}
Console.ReadLine();
The problem is in the sequencing of your first two if statements, inside the firstThreeDays as well as secondThreeDays. Use if, else-if, else-if construct.
// Suppose your loop has executed once. Now, currentShiftAB is 2.
if (currentShiftAB != 3) // currentShiftAB is not 3.It enters this if.
{
currentShiftAB++; // currentshiftAB is now 3.
Console.WriteLine(i + " A-B"); //It prints 3 A-B
}
// Now, currentShiftAB is 3 but currentShiftCD is not 3.
// your code enters this if condition as well at the same time.
// That's why you are getting duplicate output for i=3.
if (currentShiftCD != 3 & currentShiftAB == 3)
{
currentShiftCD++;
Console.WriteLine(i + " C-D");
}
I wouldn't use continue to "solve" your problem just use the else clause with your first if
for (int i = 1; i <20; i++)
{
if (firstThreeDays)
{
if (currentShiftAB != 3)
{
currentShiftAB++;
Console.WriteLine(i + " A-B");
}
if (currentShiftCD != 3 & currentShiftAB == 3)
{
currentShiftCD++;
Console.WriteLine(i + " C-D");
}
if (currentShiftAB == 3 & currentShiftCD == 3)
{
firstThreeDays = false;
secondThreeDays = true;
currentShiftAB = 0;
currentShiftCD = 0;
}
}
else if (secondThreeDays)
{
if (currentShiftBA != 3)
{
currentShiftBA++;
Console.WriteLine(i + " B-A");
}
if (currentShiftDC != 3 & currentShiftBA == 3)
{
currentShiftDC++;
Console.WriteLine(i + " D-C");
}
if (currentShiftBA == 3 & currentShiftDC == 3)
{
secondThreeDays = false;
firstThreeDays = true;
currentShiftBA = 0;
currentShiftDC = 0;
}
}
}
Console.ReadLine();
This will guarantee that the if (secondThreeDays) block doesn't get run in the same iteration as the if (firstThreeDays) block.
I'm trying to wait for 20 seconds before adding + 1 value to i (Int), But i want to do it without Thread.Sleep.
This is my code, By the way I'm not a Pro programmer.
private void Refresh_App_TimerNH_Tick(object sender, EventArgs e)
{
label18.Text = "Timer Activated";
int i = 0;
i = i + 1;
if (i == 16)
{
i = 0;
}
else
{
}
if (i == 1)
{
webBrowser1.Refresh();
userIdLabel1.BackColor = Color.Red;
label20.Text = "+1";
//**i want to add 20 second gap here**
i = i + 1;
}
else
{
}
if (i == 2)
{
webBrowser2.Refresh();
userIdLabel2.BackColor = Color.Red;
label20.Text = "+2";
i = i + 1;
}
else
{
}
if (i == 3)
{
webBrowser3.Refresh();
userIdLabel3.BackColor = Color.Red;
label20.Text = "+3";
i = i + 1;
}
else
{
}
if (i == 4)
{
webBrowser4.Refresh();
userIdLabel4.BackColor = Color.Red;
label20.Text = "+4";
i = i + 1;
}
else
{
}
if (i == 5)
{
webBrowser5.Refresh();
userIdLabel5.BackColor = Color.Red;
label20.Text = "+5";
i = i + 1;
}
else
{
}
if (i == 6)
{
webBrowser6.Refresh();
userIdLabel6.BackColor = Color.Red;
label20.Text = "+6";
i = i + 1;
}
else
{
}
if (i == 7)
{
webBrowser7.Refresh();
userIdLabel7.BackColor = Color.Red;
label20.Text = "+7";
i = i + 1;
}
else
{
}
if (i == 8)
{
webBrowser8.Refresh();
userIdLabel8.BackColor = Color.Red;
label20.Text = "+8";
i = i + 1;
}
else
{
}
if (i == 9)
{
webBrowser9.Refresh();
userIdLabel9.BackColor = Color.Red;
label20.Text = "+9";
i = i + 1;
}
else
{
}
if (i == 10)
{
webBrowser10.Refresh();
userIdLabel10.BackColor = Color.Red;
label20.Text = "+10";
i = i + 1;
}
else
{
}
if (i == 11)
{
webBrowser11.Refresh();
userIdLabel11.BackColor = Color.Red;
label20.Text = "+11";
i = i + 1;
}
else
{
}
if (i == 12)
{
webBrowser12.Refresh();
userIdLabel12.BackColor = Color.Red;
label20.Text = "+12";
i = i + 1;
}
else
{
}
if (i == 13)
{
webBrowser13.Refresh();
userIdLabel13.BackColor = Color.Red;
label20.Text = "+13";
i = i + 1;
}
else
{
}
if (i == 14)
{
webBrowser14.Refresh();
userIdLabel14.BackColor = Color.Red;
label20.Text = "+14";
i = i + 1;
}
else
{
}
if (i == 15)
{
webBrowser15.Refresh();
userIdLabel15.BackColor = Color.Red;
label20.Text = "+15";
i = i + 1;
}
else
{
}
if (i == 16)
{
webBrowser16.Refresh();
userIdLabel16.BackColor = Color.Red;
label20.Text = "+16";
i = i + 1;
}
else
{
}
Refresh_App_TimerNH.Stop();
label18.Text = "Timer De-Activated";
Refresh_App_TimerNH.Start();
}
I think it might be easy but not for me, Because i'm new to c#
First off, Tim S's answer -- break up your logic into smaller chunks and simplify the timer logic -- is good. But to answer your specific question, which was "how do I delay between statements without Sleep", is: make the method async and then use await Task.Delay(...).
You are right to avoid Sleep; using it is a bad programming practice, and will hang your application. await Task.Delay does an asynchronous wait -- that is, the method returns immediately, the app keeps on processing UI messages, and when the delay is done, the program schedules the remainder of the method to execute later.
Note that during an asynchronous wait, by design messages keep on getting processed. If one of those messages causes your event handler to run again then you can get into the very confusing situation of having multiple control points in the same non-recursive method. Try to avoid that.
Right now your logic is convoluted, and probably very different from what you want it to do.
Your code will be much simpler if you put your webBrowserX and userIdLabelX items in some sort of list together.
public class MyPair
{
public WebBrowser WebBrowser { get; set; }
public Label UserIdLabel { get; set; }
}
private List<MyPair> pairs;
private int refreshIndex = 0;
private void StartTimer()
{
pairs = // populate pairs somehow
refreshIndex = 0;
var timer = new System.Windows.Forms.Timer();
timer.Interval = 20000
timer.Tick += MyTickHandler;
timer.Start();
label18.Text = "Timer Activated";
}
private void MyTickHandler(object sender, EventArgs e)
{
pairs[refreshIndex].WebBrowser.Refresh();
pairs[refreshIndex].UserIdLabel.BackColor = Color.Red;
label20.Text = "+" + (refreshIndex + 1);
refreshIndex = (refreshIndex + 1) % pairs.Count;
}
Note that this timer never deactivates, it loops through the list of pairs repeatedly.
This is a tic tac toe generator. Computer vs. Computer only, a little different than the usual Player vs. Computer. I have most of my code written for this, but the issue I am having is sometimes when I generate the game, the whole board fills up and there will be a line of X's and a line of O's and it will come up as a tie. Sometimes there is two lines of X's or two lines of O's generated, and the game doesn't stop after the first line with 3 in a row...any insights? Thank you.
namespace TicTacToe
{
public partial class Form1 : Form
{
private Random rn = new Random();
const int SIZE = 9;
char[] cell = new char[SIZE];
char firstPlayer = ' ', secondPlayer = ' ';
private void button1_Click(object sender, EventArgs e)
{
//Clear the labels and starting values
for (int i = 0; i < SIZE; i++)
{
cell[i] = ' ';
}
label10.Text = "";
//Pick X or O to go first
switch (rn.Next(2))
{
case 0: firstPlayer = 'O'; secondPlayer = 'X'; break;
case 1: firstPlayer = 'X'; secondPlayer = 'O'; break;
}
//Get five non-repeating numbers from 0 to 8
int[] positions = new int[5];
positions[0] = rn.Next(9);
for (int i = 1; i < 5; i++)
{
int temp = rn.Next(9);
for (int j = 0; j < i; j++)
{
if (temp == positions[j])
{
i--;
break;
}
else
{
positions[i] = temp;
}
}
}
//Set each position found to have first players letter
for (int i = 0; i < 5; i++)
{
cell[positions[i]] = firstPlayer;
}
for (int i = 0; i < SIZE; i++)
{
if (cell[i] != firstPlayer)
{
cell[i] = secondPlayer;
}
}
//Place cell values into the labels
label1.Text = cell[0].ToString();
label2.Text = cell[1].ToString();
label3.Text = cell[2].ToString();
label4.Text = cell[3].ToString();
label5.Text = cell[4].ToString();
label6.Text = cell[5].ToString();
label7.Text = cell[6].ToString();
label8.Text = cell[7].ToString();
label9.Text = cell[8].ToString();
//Check for a winner
switch(checkWinner())
{
case 'T' : label10.Text = "It's a tie!"; break;
case 'O' : label10.Text = "O Wins!"; break;
case 'X' : label10.Text = "X Wins!"; break;
default: label10.Text = "This will never appear"; break;
}
}
private char checkWinner()
{
//return either 'T' for tie, 'O' for O wins, and 'X' for X wins
char winner = ' ';
int winning_line = 0;
//check for a row win
if(cell[0].Equals(cell[1]) && cell[0].Equals(cell[2]))
{
winning_line++;
winner = cell[0];
}
if (cell[3].Equals(cell[4]) && cell[3].Equals(cell[5]))
{
winning_line++;
winner = cell[3];
}
if (cell[6].Equals(cell[7]) && cell[6].Equals(cell[8]))
{
winning_line++;
winner = cell[6];
}
//check for column wins
if (cell[0].Equals(cell[3]) && cell[0].Equals(cell[6]))
{
winning_line++;
winner = cell[0];
}
if (cell[1].Equals(cell[4]) && cell[1].Equals(cell[7]))
{
winning_line++;
winner = cell[1];
}
if (cell[2].Equals(cell[5]) && cell[2].Equals(cell[8]))
{
winning_line++;
winner = cell[2];
}
//check for diagonal winner
if (cell[0].Equals(cell[4]) && cell[0].Equals(cell[8]))
{
winning_line++;
winner = cell[0];
}
if (cell[2].Equals(cell[4]) && cell[2].Equals(cell[8]))
{
winning_line++;
winner = cell[2];
}
if (winning_line == 0 || winning_line > 1)
winner = 'T';
return winner;
}
public int i { get; set; }
}
}
if (winning_line == 0 || winning_line > 1)
If there are two lines, it will r port a tie. If you want to stop when a line is made, you needto check for a winner after each move, not after the entire board has been filled.
The second diagonal winner check should be 6 instead of 8.
You are currently checking:
X O O
O X O
O O X
and:
O O X
O X O
O O X
Obviously the last x should be to the left.
Additionaly as others have posted. Making two lines should not result in a tie. One player could even make two lines alone, causing a tie.
Change the function to return a result right away when it finds a winning row and check for it after every move.
This works: You need to get rid of the...
if (winning_line == 0 || winning_line > 1)
replace that line of code with these three piece of code:
if (winnerX == " X ")
{
theWinner = winnerX;
}
if (winnerO == " O ")
{
theWinner = winnerO;
}
if(winnerX == " X " && winnerO == " O ")
{
winnerT = " T ";
theWinner = winnerT;
}
So what I did was change a couple things. I didn't use the "winning_line++;" bit of code.
instead I did something like this for each of the if statement checks.
if (cell[2, 0].Equals(cell[1, 1]) && cell[2, 0].Equals(cell[0, 2]))
{
if (cell[2, 0] == 0)
{
winnerX = " X ";
}
else if (cell[2, 0] == 1)
{
winnerO = " O ";
}
}
So I have 4 strings that I'm using, one to keep track if X is has a winning line, same for O. I then have the winnerT string for keeping track of the Tie. its only used in place of where your old tie check if statement was.
You will also need to change your switch statement too if you decide to use strings instead of integers i.e
switch (checkWinner())
{
case " X ":
textBox1.Text = "X Wins!";
break;
case " O ":
textBox1.Text = "O Wins!";
break;
case " T ":
textBox1.Text = "It's a tie!";
break;
}
Hi think you should have a function that given a grid and a new pawn tell you if the game is over.
Then if the game is finished, you know that the winner is the last pawn played.
I think the Open source project MikMak of Marthyi has a perfect implementation of that, see
bool IsFinished(Grid currentState, Pawn newPawn)
in:
https://github.com/Marthyi/MikMak/blob/master/MikMakSolution/Morpion/MorpionManager.cs
Good luck!