combine adjacent parallel lines - c#

There is an image which only has vertical lines and horizontal lines. But there are some lines that are the same or they are close to each other, but they should be combined to only one line. Also I wrote loop to add line in a new list, the speed is slow. So I wonder if there are some efficient way for me to combine these adjacent lines to one line.
The following is the code:
for (int i = 0; i < RecoverLine_list.Count; i++) {
for (int j = 0; j < RecoverLine_list.Count; j++) {
for (int m = 0; m < RecoverLine_list.Count; m++) {
if (RecoverLine_list[i] != RecoverLine_list[j]
&& RecoverLine_list[i] != RecoverLine_list[m]
&& RecoverLine_list[j] != RecoverLine_list[m]) {
if (RecoverLine_list[i].orientation == 0
&& RecoverLine_list[j].orientation == 0
&& RecoverLine_list[m].orientation == 0) {
if (Math.Abs(RecoverLine_list[i].P1.Y - RecoverLine_list[j].P1.Y) < 3
&& Math.Abs(RecoverLine_list[i].P1.Y - RecoverLine_list[m].P1.Y) < 3
&& Math.Abs(RecoverLine_list[j].P1.Y - RecoverLine_list[m].P1.Y) < 3) {
// define RecoverLine_list[i] as grid line
GridLine_list.Add(RecoverLine_list[i]);
}
}
}
}
}
}

(REWRITTEN) So, assuming you want to somehow filter horizontal and vertical lines which are 'similar' and want both the code and good condition for what 'similar' should be, then here are my thoughts:
First split horizontal and vertical lines:
List<Line> vert = new List<Line>();
List<Line> horiz = new List<Line>();
foreach(Line ln in RecoverLine_list)
if(ln.orientation == 0) horiz.Add(ln);
else vert.Add(ln);
horiz.Sort(x, y => x.P1.Y.CompareTo(y.P1.Y));
vert.Sort(x, y => x.P1.X.CompareTo(y.P1.X));
or something like that (not exactly sure what your orientation is, I am just guessing including the coding of sorting using lambdas).
Then you can search the lines in one pass extracting good-ones:
List<Line> filtered = new List<Line>();
for(int i = 0; i < horiz.Count; i++) {
filtered.Add(ln); // always add, we can skip next:
if(i+1 >= horiz.Count) break;
if(Math.Abs(horiz[i].P1.Y - horiz[i+1].P1.Y) <= 3)
&& Math.Abs(horiz[i].P1.X - horiz[i+1].P1.X) <= 3)
&& Math.Abs(horiz[i].P2.X - horiz[i+1].P2.X) <= 3))
i++; // skip this line for being similar
}
but that is not final solution, because we can have lines close to each other in one coordinate but not in the other. So we need to add inner loop:
for(int i = 0; i < horiz.Count-1; i++) {
for(int j = i+1; j < horiz.Count; j++) {
if((horiz[j].P1.Y - horiz[i].P1.Y) > 3)
break; // this one is too far, all next will be
if(Math.Abs(horiz[i].P1.Y - horiz[j].P1.Y) <= 3)
&& Math.Abs(horiz[i].P1.X - horiz[j].P1.X) <= 3)
&& Math.Abs(horiz[i].P2.X - horiz[j].P2.X) <= 3))
horiz.RemoveAt(j--); // skip this line for being similar
}}
Got the idea? Same for vertical lines.

Related

C# method freezes entire program

I've written the following method in C# for a small Forms program I'm working on, but whenever I try to run this method the entire program freezes.
There are no errors and I've tried to do for (int n = 0; n<8; n++) instead of while(true), but that didn't seem to change anything...
Any ideas?
Thanks in advance!
public bool legalMove(int y, int x)
{
// Check if the cell is occupied
if (grid[x, y] != 0)
return false;
// Check if there's an opponents circle somewhere around it
for (int i = -1; i<=1; i++)
for (int j = -1; i<=1; j++)
{
if (i == 0 && j == 0)
continue;
int row = x + i;
int col = y + j;
if (row >= 0 && row < 8 && col >= 0 && col < 8 && grid[col,row] == -turn)
{
// Now we know that there's an opponents circle somewhere around this space, we now check if it can be captured
while(true)
{
row += i;
col += j;
if (row < 0 || row > 7 || col < 0 || col > 7 || grid[row, col] == 0)
return false; // Outside of the board or an empty space
else if (grid[row, col] == turn)
return true; // No empty spaces between our cell and another cell of ours
}
}
}
return false; // No cell found around ours
}
Here's the problem: for (int j = -1; i<=1; j++). Should be j<=1 instead of i<=1.

Extract strings from a textbox to a listbox

{
int numlines = txtbox.Lines.Count();
string[] l = txtbox.Lines;
for (int i = 0; i <= numlines; i++)
{
string lona = l[i].Substring(25, 12);
lstbox.Items.Add(lona);
}
}
Hi, I want to move some elements from a textbox to a listbox using a for loop and a substring method. This is the code i tryed and it causes an exception while running it in a loop.
Since C# collections are zero based, correct for loop uses < Count, not <= Count condintion:
for (int i = 0; i < numlines; i++) // i < numlines, not i <= numlines
{
...
}
Let's simplify the routine and get rid of for loop: we add each line which is long enough (so we'll be able to get a Substring):
foreach (string line in txtbox.Lines) {
if (line.Length >= 25 + 12)
lstbox.Items.Add(line.Substring(25, 12));
}

c# Recursion stackoverflowcrash

I am building a minesweeper game in C#, and one of my functions keeps crashing the program. The erorr message is Process is terminated due to StackOverflowException. I tried to find where is the problem in my recursion, but I didn't find it. The problem only happen if Openk is called, so I am pretty sure the problem is there. I tried to find if there is an infinite recursion, but didn't find it. What could be the problem?
public void Openk(int row, int col)
{
if (sqrs[row, col].IsBlank() == true)
{
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (IsValid(row - i, col - j))
{
if (sqrs[row - i, col - j].IsMine() == false)
sqrs[row - i, col - j].Open();
Openk(row - i, col - j);
}
}
}
}
}
public bool IsValid(int row, int col)
{
if (row >= n || row <= 0 || col >= n || col <= 0)
return false;
return true;
}
Your problem is that you keep looping and executing Openk on the same middle square each time. Maybe it is because of the unguarded if statement. It goes like this in your code.
You pass the selected coordinates of a square, say [5,5].
Then you loop a row before 5 (4), row 5, and a row after 5 (6).
For each row, your loop a square before the selected column 5 (4), column 5, and and the next column of 5 (6).
In your code, only when you reach the middle square (i = 0, j = 0), you execute the checking of square if it is a mine, and if it is not mine, you pass the selected coordinates after subtracting with zeros (i = 0, j = 0), which effectively loops the same spot again!
.
public void Openk(int row, int col)
{
if (sqrs[row, col].IsBlank() == true)
{
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
// Only execute the following code when checking the middle square, where i = 0, and j = 0.
if (i == 0 && j == 0) // Notice the braces I added, the code has the same effect if you don't type them.
{
// This if statement has not effect.
if (IsValid(row - i, col - j)) // It is like if (true)
{
if (sqrs[row-i, col-j].IsMine() == false)
sqrs[row - i, col - j].Open();
Openk(row - i, col - j); // row - 0 = row, col - 0 = col, your looping infinitely here.
}
}
}
}
}
}

Conway's Game of Life logic error

I'm taking a class that uses C# and our first assignment is to implement Conway's game of Life. We must do this by reading in a text file formatted something like this:
*
*
***
***
We then have to display the next 10 generations on the screen.
I have the file read into a string array, then I copy it to another array. I then go through it character by character and change the copied array to match what the next generation should be. My problem is that the code I have to count the live neighbors isn't working and I can't figure out why. I displayed the number of live neighbors for each cell on the screen and about half of them are wrong. I know the error is occurring with cells on the edge of the "board," but I can't figure out how to fix it.
Now, I don't want the whole thing written for me, that'd be a bit pointless. I just can't figure out where my logic is off. Any help would be appreciated. Also, I'm aware that my code is pretty poor, overall. This was just the only way I could figure it out. Sorry.
class Program
{
static void Main(string[] args)
{
//gets file name from command arguments
//checks to make sure file exists, exits if file does not exist
if (!File.Exists(Environment.GetCommandLineArgs()[1])) { System.Environment.Exit(1); }
//gets file name from command arguments then reads file into array of strings
string[] gen0 = File.ReadAllLines(Environment.GetCommandLineArgs()[1]);
string[] gen1 = gen0;
char alive = '*';
char dead = ' ';
//displays first generation
foreach (string s in gen0)
{
Console.WriteLine(s);
}
Console.WriteLine("=====================================");
//counts live neighbors of a cell
int count = 0;
for (int i = 0; i < gen0.Length; i++)
{
count = 0;
for (int j = 0; j < gen0[i].Length; j++)
{
//check top left neighbor
if (i > 0 && j > 0 && j < gen0[i-1].Length )
{
if (gen0[i - 1][j - 1] == alive) { count++; }
}
//check above neighbor
if (i > 0 && j < gen0[i-1].Length)
{
if (gen0[i - 1][j] == alive) { count++; }
}
//check top right neighbor
if (i > 0 && j + 1 < gen0[i - 1].Length)
{
if (gen0[i - 1][j + 1] == alive) { count++; }
}
//check left neighbor
if (j > 0)
{
if (gen0[i][j - 1] == alive) { count++; }
}
//check right neighbor
if (j + 1 < gen0[i].Length)
{
if (gen0[i][j + 1] == alive) { count++; }
}
//check bottom left neighbor
if (i + 1 < gen0.Length && j > 0 && j < gen0[i+1].Length)
{
if (gen0[i + 1][j - 1] == alive) { count++; }
}
//check below neighbor
if (i + 1 < gen0.Length && j < gen0[i+1].Length)
{
if (gen0[i + 1][j] == alive) { count++; }
}
//check bottom right neighbor
if (i + 1 < gen0.Length && j + 1 < gen0[i].Length && j + 1 < gen0[i+1].Length)
{
if (gen0[i + 1][j + 1] == alive) { count++; }
}
//Console.WriteLine(count);
//kills cells
if (count < 2 || count > 3)
{
gen1[i] = gen1[i].Remove(j, 1);
gen1[i] = gen1[i].Insert(j, dead.ToString());
}
//births cells
if (count == 3)
{
gen1[i] = gen1[i].Remove(j, 1);
gen1[i] = gen1[i].Insert(j, alive.ToString());
}
}
}
foreach (string s in gen1)
{
Console.WriteLine(s);
}
}
}
Your problem is very simple - you're resetting count in the wrong place. Put it inside the loop and it will (probably) work.
Regarding the rest of the code, if you want to make it significantly easier to follow just give your game area a one-element border.
You'll need to pad the file you read in (blank line above and below, blank characters to the left and right), and alter your loops to:
for (int i = 1; i < gen0.Length - 1; i++)
and
for (int j = 1; j < gen0[i].Length - 1; j++)
but your central count calculation can then be reduced down to a single calculation:
count = (gen0[i - 1][j - 1] == alive) ? 1 : 0 +
(gen0[i - 1][j] == alive) ? 1 : 0 +
... etc ...
which should make for cleaner code and ensure that any other errors you may make are significantly easier to spot.
So the first bug I see is that you don't actually copy the board for the next iteration.
gen1 = gen0;
The code above only assigns the gen1 reference to the same object as gen0. So when you modify gen1, you actually modify gen0 as well... causing inconsistencies in latter iterations. Try this:
gen1 = (string[])gen0.Clone();
Second bug is that int count = 0 should be in the second loop instead of first:
for (int i = 0; i< gen0.Length; i++)
{
// not here
// int count = 0
for (int j = 0; j < gen0[i].Length; j++)
{
// here
int count = 0
...
}
...
}
This way you reset the count for every cell instead of every row.

how i can empty listbox contents c#?

i have this code:
public void LoadData1(String link)
{
string temp="";
int pos = 0;
for (int x = 0, y = 0; x < link.Length; x++) //separate various code
if (link[x] == 'y')
{
for (temp = ""; y < x; y++)
if(link[y]!='y')
temp += link[y];
list[pos] = temp;
pos++;
y = x++;
}
string nota=list[0];
for (int a = 0; a < list.Count() && list[a]!=null ; a++,nota=list[a])
{
string tempI = "";
//immagine
for (int x = 0; x < nota.Count(); x++)
{
if (nota[x] == 'p')
tempI += '+';
else
tempI += nota[x];
}
//nome della pagina
string temp1 = "";
int c = tempI.Count();
if (tempI.Count() > 2)
if (tempI.ElementAt(2) == 'l') //sol
{
for (int x = 0; x < c; x++)
if (x == 3 && tempI.ElementAt(3) == 'd')
temp1 += '#';
else
temp1 += tempI.ElementAt(x);
}
else
{
for (int x = 0; x < c; x++)
if (x == 2 && tempI.ElementAt(2) == 'd')
temp1 += '#';
else
temp1 += tempI.ElementAt(x);
}
else
temp1 = tempI;
this.Temp.Add(new ImageText() { Text = temp1, linkImage = "/Accordi/"+tempI+".png" });
}
this.IsDataLoaded1 = true;
this.Temp = new ObservableCollection<ImageText>();
}
this fill a listbox composed of text and image. but i have this problem: when i fill the listbox with 3 element(for example) it's go all right, but when i call again the function for fill the listbox with 2 element, the listbox show the two element of call and at the third space show the element of my previous call!! how i can solve this problem?
the listbox is binding by temp, and the string link contains a sequence of code like "DoyDodyRey"
You're setting the 'nth' element each time you load data, but you're doing nothing about what's already there, so if you had a third element on a previous call, and only two on a subsequent one, the third one will still be there.
It's simply a matter of clearing it first, or removing excess items afterwards. It's difficult to see from your code exactly what's going on, but I think a call to list.Clear() right at the top of the method will probably do the job.
If you want to simply remove excess items, I think you should be able to add while (list.Count() >= pos) list.Remove(pos); right after your first for loop.
cant you declare the list at the begining so its empty
List<string> yourlist = new List<string>();
and you dont need to use pos in lists you can just use
yourlist.add(temp)
first post in the list gets yourlist[0] and so on
hope this helps a little :)

Categories

Resources