Keeping accurate conditions during loop repetition - c#

I'm doing one method for calculating a pause, which has certain breaks checks. The method of calculating the time (from-to), at the same time I want to check, and if the time is less than 30, let me report the error.
It would have succeeded in a commencement if the loop would not have been repeated.
Can I somehow, if the condition is correct, skip that part?
In the pause of the variables I come to my values: 6, 56, 4
this is the method
private double CalculateBreak(List<PRAESENZZEIT> arrivals, out string error)
{
error = null;
double totalBreak = 0;
for (int i = 1; i < arrivals.Count();)
{
for (int n=i-1; n < arrivals.Count();)
{
double pause = (arrivals[i].ZPZ_Von - arrivals[n].ZPZ_Bis).TotalMinutes;
//this part
if (pause > 30)
error = "OK";
else
error = "error1";
//end
i += 1;
totalBreak += pause;
break;
}
if (totalBreak < 60)
{
error = "error2";
}
}
return totalBreak;
}

Edit: after some to-and-fro in the comments there is a further change required. If this still doesn't do what you want then lease open another question which concentrates on that part alone because I have no idea what you're saying. Code in the original answer commented out. This now returns the error if there has been one
Your loops are wrong. You only need one of them. The for n loop is going through all arrivals, when it looks like you only need to look at the previous one. Try something like this:
private double CalculateBreak(List<PRAESENZZEIT> arrivals, out string error)
{
error = null;
double totalBreak = 0;
for (int i = 1; i < arrivals.Count();)
{
// Check the i-th against the previous one (i - 1)
double pause = (arrivals[i].ZPZ_Von - arrivals[i - 1].ZPZ_Bis).TotalMinutes;
// //this part
// if (pause > 30)
// error = "OK";
// else
if (pause < 30) // new
{ // new
error = "Pausenzeitverletzung";
} // new
//end
i += 1;
totalBreak += pause;
// break;
// if (totalBreak < 60)
// {
// error = "Pausenzeitverletzung";
// }
}
// new: moved if block
if (totalBreak < 60)
{
error = "Pausenzeitverletzung";
}
return totalBreak;
}

Related

How to find a way of output the number of attempts for each question of the quiz?

I am making the quiz application on C# in Console version. I have almost done all things, but I don't know how to show the number of attempts for each question, after when the quiz is finished. If you know something, let me know.
I can not add more lines of the code, as the website doesn't allow to do it
if (keys[index] == answer) // Answer is correct
{
Console.WriteLine();
Console.WriteLine("Congratulations. That's correct!");
Console.WriteLine();
totalScore += markPerQuestion;
index++;
Console.WriteLine("The total score is: {0}", totalScore);
Console.WriteLine("Used attempt(s): {0}", attempt);
attempt = 1;
count = attempt;
markPerQuestion = 20;
}
else // Answer is incorrect
{
attempt++;
count++;
if (attempt <= 3)
{
markPerQuestion /= 2;
}
else if (attempt > 3 && attempt < 5) // The fourth attempt gives zero points
{
markPerQuestion = 0;
totalScore += markPerQuestion;
}
else if(attempt >= 5) // Move to the next question
{
Console.WriteLine("Sorry, you used all attempts for that question. Moving to the next question");
index++;
markPerQuestion = 20;
attempt = 1;
count = attempt;
continue;
}
Console.WriteLine("Oops, try again");
}
if ((index > keys.Length - 1 && index > questions.Length - 1)) // Questions and answer keys are finished
{
for (int i = 0; i < questions.Length; i++)
{
Console.WriteLine("Question {0} was answered after {1} attempt(s)", (i + 1), count);
}
break;
}
Consider this solution:
Create a public class that will allow you to store the results.
public class QuizMark
{
public int Attempts;
public int Mark;
}
For the Console app create a method to control the Quiz. Call the method Quiz() from the Main method.
private const int MAX_ATTEMPTS = 5;
private static void Quiz()
{
var quizResults = new List<QuizMark>();
var questionAnswers = new List<int>() { 1, 3, 5, 2, 3, 6 };
foreach(var a in questionAnswers)
{
var v = QuizQuestion(a);
quizResults.Add(v);
}
int i = 0;
quizResults.ForEach(e => Console.WriteLine($"Question: {++i} Attempts: {e.Attempts} Mark: {e.Mark}"));
var total = quizResults.Sum(s => s.Mark);
Console.WriteLine($"Total Points: {total}");
}
Notice the List collection that stores an object of the class QuizMark. This is where the results of each question are stored: attempts and points.
The List questionAnswers simply contains the expected answer to each of the questions.
Now create the method that is going to control how each question in the quiz will be handled:
private static QuizMark QuizQuestion(int answer)
{
var quizMark = new QuizMark();
int guess = 0; //Store ReadLine in this variable
int mark = 20;
for (int attempt = 1; attempt < MAX_ATTEMPTS + 1; attempt++)
{
guess++; //remove when adding Console.ReadLine
if (guess.Equals(answer))
{
quizMark.Attempts = attempt;
quizMark.Mark = mark;
break;
}
else
{
mark = attempt <= 3 ? mark/2 : 0;
quizMark.Attempts = attempt;
quizMark.Mark = mark;
}
}
return quizMark;
}
You will need to replace the incrementor guess++ with the actual guess the user makes. This code is designed to go though automatically just as a demonstration.
IMPORTANT NOTE:
You will want to do some error handling any time you allow users to enter data. They might enter non-integer values. Probably using a loop around a Console.ReadLine where you check the value of the input with a Int32.TryParse().

Simple For loop and if statement

What I am trying to do is limit the withdrawal amount by $20 increments up to $500. I know I am missing some simple element in here to do this. My code worked until I tried to do the increments of 20.
double AccountBalance = 1500;
double WithdrawalAmount;
WithdrawalAmount = double.Parse(textInput.Text);
Double MaxWithdrawalAmount = 0;
for (MaxWithdrawalAmount = 0; MaxWithdrawalAmount <= 500; MaxWithdrawalAmount += 20)
{
if (WithdrawalAmount == MaxWithdrawalAmount)
{
double Total = (AccountBalance - WithdrawalAmount);
textTotal.Text = ("Total amount" + Convert.ToString(Total));
}
else
{
textError.Text = ("Only Increments of $20 allowed for withdraw up to $100");
textTotal.Text = ("" + AccountBalance);
}
}
You should handle your loop in a different way
bool ok = false;
for (MaxWithdrawalAmount = 0; MaxWithdrawalAmount <= 500; MaxWithdrawalAmount += 20)
{
if (WithdrawalAmount == MaxWithdrawalAmount)
{
double Total = (AccountBalance - WithdrawalAmount);
textTotal.Text = "Total amount" + Convert.ToString(Total);
ok = true;
break;
}
}
if (!ok)
{
textError.Text = ("Only Increments of $20 allowed for withdraw up to $100");
textTotal.Text = ("" + AccountBalance);
}
I have moved the error message outside the loop. If, inside the loop I find the correct value for withdrawal then I stop the loop and set a flag to avoid the final error message
Side note, if you don't need double values the whole code could be reduced to a few lines using the remainder operator . For example
int WithdrawalAmount = 120;
if ((WithdrawalAmount % 20) == 0)
... good ...
else
... bad ...

How to recall a loop after it runs and its condition is reset

Not sure if I've numbed my mind trying to figure this but I'm trying to get a loop to trigger again after it runs by changing its condition in a later branch of code based on user input. Here's the code:
int moveend = 1;
for (int move = 0; move < moveend; move++)
{
if (move < 1)
{
Console.WriteLine("Enter a direction to move\n");
//forloop that allows the output to cycle the legth of array and branch to a new line on 4th output
for (int i = 0; i < width; i++)
{
//for loop code
}
//This is the code i'm using to re trigger the previous loop with "move = 0"
ConsoleKeyInfo kb = Console.ReadKey();
if (kb.Key == ConsoleKey.UpArrow)
{
map[7, 1] = 1;
map[11, 1] = 0;
move = 0;
Console.WriteLine("FIre");
}
}
else
{
Console.WriteLine("END");
}
}
I'm not sure why it is that I can see the "Fire" with this code but it doesn't loop again despite the loop condition being reset within the loop. I expected it to reprint the loop info with the updated array coordinates map[7, 1] = 1; map[11, 1] = 0; but it doesn't. Am I overlooking something or is there something I'm missing about loops?
The reason is that you set move to 0, but it is already zero.
The loop can loosely be translated to this:
int move = 0;
while (move < moveend)
{
... rest of your code
move++;
}
So move is 0 the whole time throughout the loop, and is increased at the end, and then it is no longer < moveend.
To keep running the loop, perhaps you don't want a for loop at all?
bool keepRunning = true;
while (keepRunning)
{
keepRunning = false;
... rest of your code
if (...)
keepRunning = true; // force another run through the loop
}
I am not sure why are you doing it like that I think this might help you to accomplish your task
bool dirtyBool = true;
while(dirtyBool)
{
if (move < 1)
{
Console.WriteLine("Enter a direction to move\n");
//forloop that allows the output to cycle the legth of array and branch to a new line on 4th output
for (int i = 0; i < width; i++)
{
//for loop code
}
//This is the code i'm using to re trigger the previous loop with "move = 0"
ConsoleKeyInfo kb = Console.ReadKey();
if (kb.Key == ConsoleKey.UpArrow)
{
map[7, 1] = 1;
map[11, 1] = 0;
move = 0;
dirtyBool=false;
Console.WriteLine("FIre");
}
}
else
{
dirtyBool=false;
Console.WriteLine("END");
}
}
I have added a variable dirtyBool of type Bool which will make loop it again. Modify the code according to your usablility

No error but something is wrong with DataGridView

I roughly translated vb.net code to c# for a simple POS system i'm coding for school. But when i try to add things to the datagrid using button click event there is no change in the datagrid. there are no errors. the datagrid is not connected to a database, at least not yet.
here's the code where i insert things to the datagrid:
private void txtAdd_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtProduct.Text) & !string.IsNullOrEmpty(txtQuantity.Text) & !string.IsNullOrEmpty(txtPrice.Text))
{
var with = dataSales;
int ii = 0;
int orderproduct = 0;
int count = 0;
for (ii = 0; ii <= with.RowCount - 1; ii++)
{
if (txtProduct.Text == Convert.ToString(dataSales[0, ii].Value))
{
count = count + 1;
if (count != 0)
{
orderproduct = Convert.ToInt32(dataSales[2, ii].Value) + Convert.ToInt32(txtQuantity.Text);
dataSales[2, ii].Value = orderproduct;
dataSales[3, ii].Value = Convert.ToInt32(dataSales[2, ii].Value) * Convert.ToInt32(dataSales[1, ii].Value);
}
else
{
if (count == 0)
{
float sum = Convert.ToInt32(txtPrice.Text) * Convert.ToInt32(txtQuantity.Text);
dataSales.Rows.Add(txtProduct.Text, txtPrice.Text, txtQuantity.Text, sum);
count = 0;
}
txtProduct.Clear();
txtQuantity.Clear();
txtPrice.Clear();
}
}
else
{
MessageBox.Show("Nothing is Selected", "Error");
}
}
}
}
Follow your counter and you will understand why you never get anything added. You start with 0 but add +1 every single time there is text to add. PUt it in debug and watch.
EDITED: Due to your comment you do not know how to debug. Open the .cs file in Visual Studio, Click on the left margin for the line that tests for text in the fields (the line below):
if (!string.IsNullOrEmpty(txtProduct.Text) & !string.IsNullOrEmpty(txtQuantity.Text) & !string.IsNullOrEmpty(txtPrice.Text))
Now start the program, enter text and run it. It will stop on that line. You can then hit F11 and it will go to the line that increments the counter. This means you will always run this branch.
if (count != 0)
{
orderproduct = Convert.ToInt32(dataSales[2, ii].Value) + Convert.ToInt32(txtQuantity.Text);
dataSales[2, ii].Value = orderproduct;
dataSales[3, ii].Value = Convert.ToInt32(dataSales[2, ii].Value) * Convert.ToInt32(dataSales[1, ii].Value);
}
NOTE: You do not need this:
if (count == 0)
{
}
Why? You have already sent anything not 0 to the other branch. The else is sufficient at this point, and no need to waste a cycle determining if something that will ALWAYS be zero is zero

Generating new Sudoku grid C#

I’m trying to make a C# application using Visual Studio 2008, that solves Sudoku puzzles.
My problem is that I can’t seem to figure the code for generating a new puzzle by the application. The idea that I’m trying to implement is as follows:
Start with an empty puzzle
Generate numbers for all cells in the puzzle
Empty the appropriate number of cells, based on required level of difficulty
Solve the puzzle
Is the score for the puzzle in the acceptable range for the required level of difficulty?
6a. If NO -> Regenerate puzzle (go to 1.)
6b. If YES -> Puzzle generated (display it)
Used code for “New game” button:
//--------------------------------------------------
// Starting a new game menu button
//--------------------------------------------------
public void NewToolStripMenuItem_Click(System.Object sender, System.EventArgs e)
{
if (GameStarted) // this cheking part seems to work (message is displayed and game gets saved if selected)
{
MsgBoxResult response = (MsgBoxResult)(MessageBox.Show("Doriți salvarea jocului curent?", "Salvează jocul curent...", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question));
if (response == MsgBoxResult.Yes)
{
SaveGameToDisk(false);
}
else if (response == MsgBoxResult.Cancel)
{
return;
}
}
// Changing the cursor while generating
System.Windows.Forms.Cursor.Current = Cursors.WaitCursor;
ToolStripStatusLabel1.Text = "Se generează un puzzle nou...";
// Creating an instance for the SudokuPuzzle class
SudokuPuzzle sp = new SudokuPuzzle();
string puzzle = string.Empty;
// Determining the difficulty level selected (from menu objects)
if (EasyToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(1);
}
else if (MediumToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(2);
}
else if (DifficultToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(3);
}
else if (ExtremelyDifficultToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(4);
}
else if (EmptyPuzzleToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(5);
}
// Changing to default cursor
System.Windows.Forms.Cursor.Current = Cursors.Default;
StartNewGame();
// Initialisation of the grid
int counter = 0;
for (int row = 1; row <= 9; row++)
{
for (int col = 1; col <= 9; col++)
{
if (puzzle[counter].ToString() != "0")
{
SetCell(col, row, System.Convert.ToInt32(puzzle[counter].ToString()), (short)0);
}
counter++;
}
}
}
So the code for the next function called, GetPuzzle(1) :
//--------------------------------------------------
// Obtaining a new puzzle (of the required level)
//--------------------------------------------------
public string GetPuzzle(int level)
{
int score = 0;
string result;
do
{
result = GenerateNewPuzzle(level, ref score);
if (result != string.Empty)
{
// Verify if the generated puzzle is of the selected dificulty
switch (level)
{
// The average for dificutly 1
case 1:
if (score >= 42 && score <= 46)
{
goto endOfDoLoop;
}
break;
// The average for dificutly 2
case 2:
if (score >= 49 && score <= 53)
{
goto endOfDoLoop;
}
break;
// The average for dificutly 3 case 3:
if (score >= 56 && score <= 60)
{
goto endOfDoLoop;
}
break;
// The average for dificutly 4
case 4:
if (score >= 112 && score <= 116)
{
goto endOfDoLoop;
}
break;
}
}
} while (!false); // loops ending
endOfDoLoop:
return result;
}
Next function used is GenerateNewPuzzle():
//--------------------------------------------------
// Generating a new puzzle
//--------------------------------------------------
public string GenerateNewPuzzle(int level, ref int score)
{
int c;
int r;
string str;
int numberofemptycells = 0;
// Initializing the entire grid
for (r = 1; r <= 9; r++)
{
for (c = 1; c <= 9; c++)
{
actual[c, r] = 0;
possible[c, r] = string.Empty;
}
}
// Empty the stacks used
ActualStack.Clear();
PossibleStack.Clear();
// Complete by solving an empty grid
try
{
// First used logical methods to solve the grid
if (!SolvePuzzle())
{
// Then use brute force
SolvePuzzleByBruteForce();
}
}
catch (Exception)
{
// If there’s any error, return emptry string
return string.Empty;
}
// Create a copy for the actual array
actual_backup = (int[,])(actual.Clone());
// Set the number of empty cells based on the difficulty level
switch (level)
{
// For difficulty level 1
case 1:
numberofemptycells = RandomNumber(40, 45);
break;
// For difficulty level 2
case 2:
numberofemptycells = RandomNumber(46, 49);
break;
// For difficulty level 3
case 3:
numberofemptycells = RandomNumber(50, 53);
break;
// For difficulty level 4
case 4:
numberofemptycells = RandomNumber(54, 58);
break;
}
// Empty the stacks used by brute force
ActualStack.Clear();
PossibleStack.Clear();
BruteForceStop = false;
// Create empty cells
CreateEmptyCells(numberofemptycells);
// Convert the values from the actual array to string
str = string.Empty;
for (r = 1; r <= 9; r++)
{
for (c = 1; c <= 9; c++)
{
str += (string)(actual[c, r].ToString());
}
}
// Verrify that the puzzle has only one solution
int tries = 0;
do
{
totalscore = 0;
try
{
if (!SolvePuzzle())
{
// If puzzle is not solved and difficulty level is 1-3
if (level < 4)
{
// Choose another combination of cells to empty
VacateAnotherPairOfCells(ref str);
tries++;
}
else
{
// Puzzles of difficulty 4 don’t guranty a single solution
SolvePuzzleByBruteForce();
goto endOfDoLoop;
}
}
else
{
// The puzzle has 1 solution
goto endOfDoLoop;
}
}
catch (Exception)
{
return string.Empty;
}
// If too many tries are executed, exit at 50
if (tries > 50)
{
return string.Empty;
}
}
while (true);
endOfDoLoop:
// Return the obtained score and the puzzle as a string
score = totalscore;
return str;
}
And last useful (I think) function, VacateAnotherPairOfCells():
//--------------------------------------------------
// Empty another pair of cells
//--------------------------------------------------
private void VacateAnotherPairOfCells(ref string str)
{
int c;
int r;
// Search for a pair of cells to empty (the empty cells should be simetrical from the center of the grid)
do
{
c = RandomNumber(1, 9);
r = RandomNumber(1, 9);
} while (!(int.Parse(str[(c - 1) + (r - 1) * 9].ToString()) == 0));
// Restore the value of the cell from the backup array
str = str.Remove(System.Convert.ToInt32((c - 1) + (r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((c - 1) + (r - 1) * 9), (string)(actual_backup[c, r].ToString()));
// Restore the value of the simetrical cell
str = str.Remove(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), (string)(actual_backup[10 - c, 10 - r].ToString()));
// Search for another pair of cells that can be emptyed
do
{
c = RandomNumber(1, 9);
r = RandomNumber(1, 9);
} while (!(int.Parse(str[(c - 1) + (r - 1) * 9].ToString()) != 0));
// Delete the cell from the string
str = str.Remove(System.Convert.ToInt32((c - 1) + (r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((c - 1) + (r - 1) * 9), "0");
// Delete the simetrical cell from the string
str = str.Remove(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), "0");
// Reinitilisation of the grid
short counter = (short)0;
for (int row = 1; row <= 9; row++)
{
for (int col = 1; col <= 9; col++)
{
if (System.Convert.ToInt32(str[counter].ToString()) != 0)
{
actual[col, row] = System.Convert.ToInt32(str[counter].ToString());
possible[col, row] = (string)(str[counter].ToString());
}
else
{
actual[col, row] = 0;
possible[col, row] = string.Empty;
}
counter++;
}
}
}
} }
The rest of the functions and code I didn't think to be necessary as everything else works. If I import an empty or partial puzzle the application can automatically solve it using the same methods used for solving the automatically generated grids. But when I click "New puzzle" from the menu, the application gets stuck with no error (so I have to kill the process).
Maybe this isn't the easiest method to generate a valid board, and I apologize for the length of the code, but I really need to fix and use this one. I tried to fix this myself, many times, but in the last 2 months I came to no solution (just a lot of frustration from my incompetence in this matter)… So I would appreciate any kind of help that I could get from here.
Problem solved!
There is actually no problem with the code above, my problem was given to the fact that I had some coding mistake in "SolvePuzzleByBruteForce()" function. The function in question was not posted here, so the code above needs no correction and it functions properly.
I can put the "SolvePuzzleByBruteForce()" if anyone wants to, but I find it irrelevant given the fact that it's nothing special and the internet is full of such functions anyway.
To reply to the comments:
#HighCore the use of goto is not relevant to my question.
#Mark Lakata the question was not vague. I stated the problem, the thing it needed to do, and the code used. And it wasn't homework problem as I'm not in school, nor would I try 2 months to make a homework.
#Wilson thank you for your comments, it helped me trace down and figure out the problem in the bad function.

Categories