Remove Line from Canvas in WPF - c#

Hy guys, I'm trying to delete a Line previously created by button pressed. I also want the line to be deleted by button pressed. There are a large number of lines on my canvas, so I've tried selecting it by name to delete it but I failed. Also I tried by Uid and did not work.
Here is the code for the line created:
private void butonAdaugare_Click(object sender, RoutedEventArgs e)
{
Linie1.Y2 = Linie1.Y2 + 21;
Linie2.Y2 = Linie2.Y2 + 21;
Linie3.Y2 = Linie3.Y2 + 21;
Linie4.Y2 = Linie4.Y2 + 21;
Line linienoua = new Line();
linienoua.Uid = "LinieNoua" + i;
linienoua.X1 = 10;
linienoua.Y1 = Linie4.Y2;
linienoua.X2 = 670;
linienoua.Y2 = Linie4.Y2;
linienoua.Visibility = System.Windows.Visibility.Visible;
linienoua.Stroke = System.Windows.Media.Brushes.Black;
linienoua.StrokeThickness = 1;
canvas1.Children.Add(linienoua);
i++;
foreach (Line l in canvas1.Children.OfType<Line>())
{
for (int j = 2; j < 15; j++)
{
if (l.Name == "V" + j)
l.Y2 = l.Y2 + 21;
}
}
}
And this is the removal part by Uid:
private void butonStergere_Click(object sender, RoutedEventArgs e)
{
if (Linie1.Y2 > 101 && Linie2.Y2 > 101 && Linie3.Y2 > 101 && Linie4.Y2 > 101)
{
Linie1.Y2 = Linie1.Y2 - 21;
Linie2.Y2 = Linie2.Y2 - 21;
Linie3.Y2 = Linie3.Y2 - 21;
Linie4.Y2 = Linie4.Y2 - 21;
}
foreach (Line l in canvas1.Children.OfType<Line>())
{
if (l.Uid == "LinieNoua" + i)
canvas1.Children.Remove(l);
for (int j = 2; j < 15; j++)
{
if (l.Name == "V" + j && l.Y2 > 91)
l.Y2 = l.Y2 - 21;
}
}
i--;
}
Any thoughts on this ?

Without a good, minimal, complete code example, it is hard to provide an answer with a high level of confidence. You have left too much information out of your question to know for sure what the problem is.
However, from the code you did post, there does seem to be one obvious problem: the value of i is being decremented only after the code to remove the line, but it seems that variable contains the index value for the next line to be added, not the most recently-added one.
It seems likely to me that if you simply move the decrement to occur prior to the loop that finds and removes the object, it would work:
private void butonStergere_Click(object sender, RoutedEventArgs e)
{
if (Linie1.Y2 > 101 && Linie2.Y2 > 101 && Linie3.Y2 > 101 && Linie4.Y2 > 101)
{
Linie1.Y2 = Linie1.Y2 - 21;
Linie2.Y2 = Linie2.Y2 - 21;
Linie3.Y2 = Linie3.Y2 - 21;
Linie4.Y2 = Linie4.Y2 - 21;
}
i--;
Line lineToRemove = null;
foreach (Line l in canvas1.Children.OfType<Line>())
{
if (l.Uid == "LinieNoua" + i)
{
lineToRemove = l;
}
for (int j = 2; j < 15; j++)
{
if (l.Name == "V" + j && l.Y2 > 91)
l.Y2 = l.Y2 - 21;
}
}
if (lineToRemove != null)
{
canvas1.Children.Remove(lineToRemove);
}
}
<edit>
From your description in the comments, it sounds like when you made my originally suggested change, the code simply crashed (i.e. "the program exits directly", as you put it). Since you didn't provide a complete code example, there is no way for me to actually test any proposed solution, but I strongly suspect the crash you are seeing is due to the fact that the code attempts to modify (remove an element from) the canvas1.Children collection, which is the same collection that is being enumerated.
I have edited the proposed code change to avoid performing that illegal operation. Instead, the element to remove is simply noted in a local variable, and it is removed at the end, after the enumeration of all of the children has completed.
</edit>
For future reference, this seems like an excellent scenario for a debugger. If you were to simply set a breakpoint in the butonStergere_Click() method and step through each iteration of the loop, looking for the object you expect to be removed, it would be readily apparent when you find that object why the code itself wasn't identifying it.
Most bugs happen because we as a programmer have made an assumption about something that turns out to not be true. The best way to find bugs then is to use a debugger and examine the validity of each and every assumption we made, until we find the discrepancy.

Related

Unreachable code detected. Why?

Im trying to learn c# by reading Herbert Schildt "c# 4.0 the complete reference" and in one of examples I have this warning CS0162 Unreachable code detected and underlined Console. How to fix that and why it happened?
using System;
class ProdSum
{
static void Main()
{
int prod;
int sum;
int i;
sum = 0;
prod = 1;
for (i = 1; 1 <= 10; i++)
{
sum = sum + i;
prod = prod * i;
}
Console.WriteLine("Summ = " + sum);
Console.WriteLine("Prod = " + prod);
Console.ReadKey();
}
}
1 <= 10 is always true, so the code that follow the for loop is never reached. You meant i <= 10
for (i = 1; i <= 10; i++)
Your condition is comparing digit 1 with number 10
1 <= 10
This expression will always be true and control will never flow out of the loop.
You probably need i <= 10

Run time of shellsort and insertionsort change depending on execution order

1/ DateTime before = DateTime.Now;
2/ shellSort(List1);
3/ DateTime after = DateTime.Now;
4/ Console.WriteLine(after - before);
5/
6/ before = DateTime.Now;
7/ insertionSort(List2);
8/ after = DateTime.Now;
9/ Console.WriteLine(after - before);
I am trying to compare the run time of two different sorting algorithms. List1 here is equal to List2. I was expecting shell sort to be faster than insertion sort but although first WriteLine differs, it usually prints something like this = 00:00:00.0035037. The second one however, either prints 00:00:00 or something smaller than the first print. I thought maybe the insertion sort was better suited for List's current state however even when i swap the line 7 and line 2 i still get the same result. What is causing this? Why is the second executed function runs faster? Or am i using the Dates completely wrong?
Edit : I used Stopwatch instead of DateTime Class as advised in another post. The result is pretty much the same. The second one usually runs faster but every now and then it's slower than the first one. I also used a pre-written shellsort code to see if my implementation was bad but that was also a dead end.
As requested, shellsort and insertionsort implementations
static void shellSort(List<int> numbers) // Implementation i found online
{
int i, j, increment, temp;
increment = 3;
while (increment > 0)
{
for (i = 0; i < numbers.Count ; i++)
{
j = i;
temp = numbers[i];
while ((j >= increment) && (numbers[j - increment] > temp))
{
numbers[j] = numbers[j - increment];
j = j - increment;
}
numbers[j] = temp;
}
if (increment / 2 != 0)
increment = increment / 2;
else if (increment == 1)
increment = 0;
else
increment = 1;
}
}
public static void insertionSort(List<int> numbers)
{
int i = 0;
while (i != numbers.Count)
{
int k = i;
while (k != 0 && numbers[k] < numbers[k - 1])
{
int temp = numbers[k - 1];
numbers[k - 1] = numbers[k];
numbers[k] = temp;
k--;
}
i++;
}
}
Also this was my implementation of shellsort
public static void shellSort(List<int> Liste)
{
int n = Liste.Count;
int gap = (Liste.Count - 1) / 2;
while (gap > 0)
{
int i = 0;
for(int k = gap; k < n; k++) {
int p = i;
int m = k;
while (p >= 0)
{
if (Liste[p] > Liste[m])
{
int temp = Liste[p];
Liste[p] = Liste[m];
Liste[m] = temp;
m = p;
}
else
break;
p = p - gap;
}
i++;
}
gap = gap / 2;
}
}

Prevent Stack Overflow in a Minesweeper Clone

I'm creating a Minesweeper clone. Thus far, I've gotten to revealing adjacent tiles when the tile clicked has zero adjacent mines, below is my method for revealing mines.
struct data
{
public Button tile;
public bool mine, flag, clicked;
public int adjMines;
}
data[,] dat;
//Defaults
Size gridSize = new Size(16, 16);
Size tileSize = new Size(16, 16);
int mines = 40, flags = 0;
bool valid(int x, int y)
{
return (x >= 0 && y >= 0 && y < gridSize.Height && x < gridSize.Width);
}
void reveal(Button btn)
{
btn.BackColor = Color.DimGray;
start = true;
btn.Enabled = false;
//find button clicked, forget everything you ever learned about efficiency.
for (int i = 0; i < gridSize.Width; i++)
for (int j = 0; j < gridSize.Height; j++)
if (dat[i, j].tile == btn)
{
if (dat[i, j].adjMines == 0)
{
for (int ii = -1; ii <= 1; ii++)
for (int jj = -1; jj <= 1; jj++)
if (valid(i + ii, j + jj))
reveal(dat[i + ii, j + jj].tile);
}
else
btn.Text = dat[i, j].adjMines.ToString();
}
}
I keep getting a StackOverflowException when I run it, which doesn't come as much of a surprise, but I don't know how to fix it without doing away with the struct, which is a requirement. Any ideas?
The problem is that when you "reveal", you reveal all the neighbors. When the neighbor is revealed, it reveals all of its neighbours, including the first one, and now you have an infinite recursion.
The trick is: before you reveal the very first one, make a hash set of "in progress reveals". Before you recurse, add the current button to the "in progress" set. In the reveal method return immediately if the button is already in the in-progress set. You know that all its neighbours are already in the process of being revealed, so there's no work to do.
It would probably help if you didn't recursively try to reveal the same tile:
for (int ii = -1; ii <= 1; ii++)
for (int jj = -1; jj <= 1; jj++)
if (valid(i + ii, j + jj) && !(ii == 0 && jj == 0))
reveal(dat[i + ii, j + jj].tile);
Note the !(ii == 0 && jj == 0) test added - that will stop one of the stack overflow reasons. Apart from that, you also need to mark the node as 'enabled' before going recursive, it'll keep bouncing back and forth otherwise.
It's not a really efficient method you've chosen to implement, but it should work with this fix.
It looks like you are calling reveal from inside reveal. Reveal goes through each tile. You are calling it for all adjacent tiles which then goes through each tile and then calls all adjacent tiles. I would suggest looking through your use of recursion.

C# check given word to answer word

I'm making a simple spell checker for C#, I want to try and compare a given answer to the randomly chosen word.
I want to compare the first letter to all the letters given in the answer so I can tell if it's correct, it's there was a swap of letters, a deletion or an added letter. I would ultimately like to be able to tell if only one letter was wrong to see a substitution was used.
For example, correct answer hello:
checking first letter ~H
h e l l o
1 0 0 0 0
h h e l l o
1 1 0 0 0 0
e l l o
0 0 0 0
Then go through it for the second letter.
I've absolutely no idea when it comes to C#.
I've tried
int CheckErrors(string Answer, string Guess)
{
if (Answer == Guess)
{
return 1;
}
if (Answer == null || Guess == null)
{
return -1;
}
for (int i = 0; i <= Answer.Length; i++)
{
if (Guess[i] != Answer[i])
{
count++;
//substitution = -4
//deletion = -5
//transposition = -6
//insertion = -7
}
return count;
}
return -9;
}
but I just can't get any further.
UPDATE:
with further research I guess what I was trying to do is something like:
STRING answer = answer_given
STRING input = correct_answer
int check = 0;
FOR (int i = 0; i < input.Length; i++)
{
FOR (int ii = 0; ii < answer.Length; ii++)
{
if (input[i] == answer[i])
{
int check++;
}
}
}
Obviously I know this would keep adding check up, but I can't guess what how else to do it.
ANOTHER UPDATE!
I can use this-
int CheckErrors(string Answer, string Guess)
{
int[,] d = new int[Answer.Length + 1, Guess.Length + 1];
for (int i = 0; i <= Answer.Length; i++)
d[i, 0] = i;
for (int j = 0; j <= Guess.Length; j++)
d[0, j] = j;
for (int j = 1; j <= Guess.Length; j++)
for (int i = 1; i <= Answer.Length; i++)
if (Answer[i - 1] == Guess[j - 1])
d[i, j] = d[i - 1, j - 1]; //no operation
else
d[i, j] = Math.Min(Math.Min(
d[i - 1, j] + 1, //a deletion
d[i, j - 1] + 1), //an insertion
d[i - 1, j - 1] + 1 //a substitution
);
return d[Answer.Length, Guess.Length];
}
But I need a way to do a count for the amount of times each error is used?
Several issues with your function:
You're trying to use a single return value to handle multiple scenarios in which the meaning of that value is not consistent. It's not advisable for a function to be able to return both a state (match, one or both values null, no match, etc) and a counter.
If you're going to use numbers to represent return states, use enum to make it more readable.
Your for loop always terminates after one iteration because it hits the return statement every time. Your return statement needs to be moved after the for loop.
if (Guess[i] != Answer[i]) will throw an exception if i is greater than the length of Guess.
It's not clear what count is supposed to represent, and it's not defined in the function.
You need to better define what exactly is your function supposed to do. If answer is "Hello" and guess is "Hhello", what are you returning? The number of letters that don't match (1)? A code that represents what the error was (Insertion)? Where the error is located? If you need more than one of those things, then you need a separate function.
You may get inspiration by looking at Approximate String Matching in Wikipedia and StackOverflow.
Have you considered trying string.Compare(...)?
http://msdn.microsoft.com/en-us/library/zkcaxw5y.aspx

Damerau–Levenshtein distance algorithm, disable counting of delete

How can i disable counting of deletion, in this implementation of Damerau-Levenshtein distance algorithm, or if there is other algorithm already implemented please point me to it.
Example(disabled deletion counting):
string1: how are you?
string2: how oyu?
distance: 1 (for transposition, 4 deletes doesn't count)
And here is the algorithm:
public static int DamerauLevenshteinDistance(string string1, string string2, int threshold)
{
// Return trivial case - where they are equal
if (string1.Equals(string2))
return 0;
// Return trivial case - where one is empty
if (String.IsNullOrEmpty(string1) || String.IsNullOrEmpty(string2))
return (string1 ?? "").Length + (string2 ?? "").Length;
// Ensure string2 (inner cycle) is longer_transpositionRow
if (string1.Length > string2.Length)
{
var tmp = string1;
string1 = string2;
string2 = tmp;
}
// Return trivial case - where string1 is contained within string2
if (string2.Contains(string1))
return string2.Length - string1.Length;
var length1 = string1.Length;
var length2 = string2.Length;
var d = new int[length1 + 1, length2 + 1];
for (var i = 0; i <= d.GetUpperBound(0); i++)
d[i, 0] = i;
for (var i = 0; i <= d.GetUpperBound(1); i++)
d[0, i] = i;
for (var i = 1; i <= d.GetUpperBound(0); i++)
{
var im1 = i - 1;
var im2 = i - 2;
var minDistance = threshold;
for (var j = 1; j <= d.GetUpperBound(1); j++)
{
var jm1 = j - 1;
var jm2 = j - 2;
var cost = string1[im1] == string2[jm1] ? 0 : 1;
var del = d[im1, j] + 1;
var ins = d[i, jm1] + 1;
var sub = d[im1, jm1] + cost;
//Math.Min is slower than native code
//d[i, j] = Math.Min(del, Math.Min(ins, sub));
d[i, j] = del <= ins && del <= sub ? del : ins <= sub ? ins : sub;
if (i > 1 && j > 1 && string1[im1] == string2[jm2] && string1[im2] == string2[jm1])
d[i, j] = Math.Min(d[i, j], d[im2, jm2] + cost);
if (d[i, j] < minDistance)
minDistance = d[i, j];
}
if (minDistance > threshold)
return int.MaxValue;
}
return d[d.GetUpperBound(0), d.GetUpperBound(1)] > threshold
? int.MaxValue
: d[d.GetUpperBound(0), d.GetUpperBound(1)];
}
public static int DamerauLevenshteinDistance( string string1
, string string2
, int threshold)
{
// Return trivial case - where they are equal
if (string1.Equals(string2))
return 0;
// Return trivial case - where one is empty
// WRONG FOR YOUR NEEDS:
// if (String.IsNullOrEmpty(string1) || String.IsNullOrEmpty(string2))
// return (string1 ?? "").Length + (string2 ?? "").Length;
//DO IT THIS WAY:
if (String.IsNullOrEmpty(string1))
// First string is empty, so every character of
// String2 has been inserted:
return (string2 ?? "").Length;
if (String.IsNullOrEmpty(string2))
// Second string is empty, so every character of string1
// has been deleted, but you dont count deletions:
return 0;
// DO NOT SWAP THE STRINGS IF YOU WANT TO DEAL WITH INSERTIONS
// IN A DIFFERENT MANNER THEN WITH DELETIONS:
// THE FOLLOWING IS WRONG FOR YOUR NEEDS:
// // Ensure string2 (inner cycle) is longer_transpositionRow
// if (string1.Length > string2.Length)
// {
// var tmp = string1;
// string1 = string2;
// string2 = tmp;
// }
// Return trivial case - where string1 is contained within string2
if (string2.Contains(string1))
//all changes are insertions
return string2.Length - string1.Length;
// REVERSE CASE: STRING2 IS CONTAINED WITHIN STRING1
if (string1.Contains(string2))
//all changes are deletions which you don't count:
return 0;
var length1 = string1.Length;
var length2 = string2.Length;
// PAY ATTENTION TO THIS CHANGE!
// length1+1 rows is way too much! You need only 3 rows (0, 1 and 2)
// read my explanation below the code!
// TOO MUCH ROWS: var d = new int[length1 + 1, length2 + 1];
var d = new int[2, length2 + 1];
// THIS INITIALIZATION COUNTS DELETIONS. YOU DONT WANT IT
// or (var i = 0; i <= d.GetUpperBound(0); i++)
// d[i, 0] = i;
// But you must initiate the first element of each row with 0:
for (var i = 0; i <= 2; i++)
d[i, 0] = 0;
// This initialization counts insertions. You need it, but for
// better consistency of code I call the variable j (not i):
for (var j = 0; j <= d.GetUpperBound(1); j++)
d[0, j] = j;
// Now do the job:
// for (var i = 1; i <= d.GetUpperBound(0); i++)
for (var i = 1; i <= length1; i++)
{
//Here in this for-loop: add "%3" to evey term
// that is used as first index of d!
var im1 = i - 1;
var im2 = i - 2;
var minDistance = threshold;
for (var j = 1; j <= d.GetUpperBound(1); j++)
{
var jm1 = j - 1;
var jm2 = j - 2;
var cost = string1[im1] == string2[jm1] ? 0 : 1;
// DON'T COUNT DELETIONS! var del = d[im1, j] + 1;
var ins = d[i % 3, jm1] + 1;
var sub = d[im1 % 3, jm1] + cost;
// Math.Min is slower than native code
// d[i, j] = Math.Min(del, Math.Min(ins, sub));
// DEL DOES NOT EXIST
// d[i, j] = del <= ins && del <= sub ? del : ins <= sub ? ins : sub;
d[i % 3, j] = ins <= sub ? ins : sub;
if (i > 1 && j > 1 && string1[im1] == string2[jm2] && string1[im2] == string2[jm1])
d[i % 3, j] = Math.Min(d[i % 3, j], d[im2 % 3, jm2] + cost);
if (d[i % 3, j] < minDistance)
minDistance = d[i % 3, j];
}
if (minDistance > threshold)
return int.MaxValue;
}
return d[length1 % 3, d.GetUpperBound(1)] > threshold
? int.MaxValue
: d[length1 % 3, d.GetUpperBound(1)];
}
here comes my explanation why you need only 3 rows:
Look at this line:
var d = new int[length1 + 1, length2 + 1];
If one string has the length n and the other has the length m, then your code needs a space of (n+1)*(m+1) integers. Each Integer needs 4 Byte. This is waste of memory if your strings are long. If both strings are 35.000 byte long, you will need more than 4 GB of memory!
In this code you calculate and write a new value for d[i,j]. And to do this, you read values from its upper neighbor (d[i,jm1]), from its left neighbor (d[im1,j]), from its upper-left neighbor (d[im1,jm1]) and finally from its double-upper-double-left neighbour (d[im2,jm2]). So you just need values from your actual row and 2 rows before.
You never need values from any other row. So why do you want to store them? Three rows are enough, and my changes make shure, that you can work with this 3 rows without reading any wrong value at any time.
I would advise not rewriting this specific algorithm to handle specific cases of "free" edits. Many of them radically simplify the concept of the problem to the point where the metric will not convey any useful information.
For example, when substitution is free the distance between all strings is the difference between their lengths. Simply transmute the smaller string into the prefix of the larger string and add the needed letters. (You can guarantee that there is no smaller distance because one insertion is required for each character of edit distance.)
When transposition is free the question reduces to determining the sum of differences of letter counts. (Since the distance between all anagrams is 0, sorting the letters in each string and exchanging out or removing the non-common elements of the larger string is the best strategy. The mathematical argument is similar to that of the previous example.)
In the case when insertion and deletion are free the edit distance between any two strings is zero. If only insertion OR deletion is free this breaks the symmetry of the distance metric - with free deletions, the distance from a to aa is 1, while the distance from aa to a is 1. Depending on the application this could possibly be desirable; but I'm not sure if it's something you're interested in. You will need to greatly alter the presented algorithm because it makes the mentioned assumption of one string always being longer than the other.
Try to change var del = d[im1, j] + 1; to var del = d[im1, j];, I think that solves your problem.

Categories