C# method freezes entire program - c#

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.

Related

C# Changing font colour while writing to Excel file

I'm encountering a bug in my code which is supposed to write the same values to both .csv and .xlsx files.
The values written to excel file are supposed to have different font colours (green, orange & red) based upon values returned from two other functions.
But quite a few values are written in the default black font.
I have looked at my code and don't see the issue.
This is my code:
public void Write(object[,] data)
{
// get process ids before running the excel codes
CheckExcellProcesses();
Application oXL;
_Workbook oWB;
_Worksheet oSheet;
Range oRng;
object misvalue = System.Reflection.Missing.Value;
//Start Excel and get Application object.
oXL = new Application();
oXL.Visible = true;
//Get a new workbook.
oWB = (_Workbook)(oXL.Workbooks.Add(""));
oSheet = (_Worksheet)oWB.ActiveSheet;
using (_writer = new StreamWriter(_pathToFile))
{
int cols = data.GetLength(1);
for (int i = 0, n = data.GetLength(0); i < n; i++)
{
StringBuilder builder = new StringBuilder();
for (int j = 0; j < cols; j++)
{
builder.Append(data[i, j]);
// Write to Excel file
oRng = (Range)oSheet.Cells[i + 1, j + 1];
oRng.Value2 = data[i, j]; //Excel rows and columns are 1 based.
if (i > 1 && j > 0 && j < 9 && (Convert.ToDouble(data[i, 9])) < 0.05 && (Convert.ToDouble(data[i, j])) != 0.0) //Skip header row and first row, skip the first column containing the date and column with RMS error.
{
//Build lists and carry out assessments
ListBuilder(i, j, Convert.ToDouble(data[i, j]));
int assess5 = Convert.ToInt32(Assessment5Day(i, j, Convert.ToDouble(data[i, j])));
int assess50 = Convert.ToInt32(Assessment50Day(i, j, Convert.ToDouble(data[i, j])));
#Region Issue is here...
int FontChecker = 50;
RepeatFontCheck:
if (assess5 < 3 && assess50 < 10)
{
builder.Append(" Green");
oRng.Font.Color = XlRgbColor.rgbGreen;
FontChecker = 0;
}
if (assess5 >= 3 && assess50 <= 10)
{
builder.Append(" Orange");
oRng.Font.Color = XlRgbColor.rgbOrange;
FontChecker = 0;
}
if (assess5 > 3 && assess50 > 10)
{
builder.Append(" Red");
oRng.Font.Color = XlRgbColor.rgbRed;
FontChecker = 0;
}
//Repeat Font Colour check
if(FontChecker != 0)
{
goto RepeatFontCheck;
}
#EndRegion
}
if (j != cols - 1)
builder.Append(SEPARATOR);
}
_writer.WriteLine(builder.ToString());
}
_writer.Close();
//Find the right directory
var path = _pathToFile;
if (path.EndsWith(".csv", StringComparison.CurrentCultureIgnoreCase))
path = path.Substring(0, path.Length - 4) + ".xlsx";
//Save excel file and exit
oWB.SaveAs(path);
}
// kill the right process after export completed
KillExcel();
}
Please have a look and advise.
quite a few values are written in the default black font.
It is not completely clear what you mean by that, but it seems you expect all cells to be red, orange or green.
However, your cases where you assign the colors do not cover all possibilities, so that expectation is wrong:
if (assess5 < 3 && assess50 < 10)
if (assess5 >= 3 && assess50 <= 10)
if (assess5 > 3 && assess50 > 10)
So what do you think happens if assess5 < 3 and assess50 >= 10?
Ok. According to #oerkelens comment, I had not considered all possibilities in my if conditionals.
The new conditionals have eliminated the values in black font colour.
The code is as follows:
if (assess5 < 3 && assess50 < 10)
{
builder.Append(" Green");
oRng.Font.Color = XlRgbColor.rgbGreen;
FontChecker = 0;
}
if (assess5 >= 3 && assess50 <= 10)
{
builder.Append(" Orange");
oRng.Font.Color = XlRgbColor.rgbOrange;
FontChecker = 0;
}
if (assess5 > 3 && assess50 > 10)
{
builder.Append(" Red");
oRng.Font.Color = XlRgbColor.rgbRed;
FontChecker = 0;
}
if (assess5 < 3 && assess50 >= 10) // StackExchange answer.
{
builder.Append(" Red");
oRng.Font.Color = XlRgbColor.rgbRed;
FontChecker = 0;
}
Regards.
worksheet.Cells[1, i].Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.White);
Try this !

How do i check in a 2d array if the next position is a specific object?

I'm creating a maze game in a 2d array but i can't figure out how to make walls/doors/etc to work. I'm thinking that when i press 'W' it will change the position of the character only if the next position isnt a wall. How do i check that?
Here's my code for the map and the movement:
const int ROWS = 16, COLUMNS = 24;
Blocks[,] map = new Blocks[COLUMNS, ROWS];
int playerRow = 3, playerColumn = 11;
Character gubbe = new Character();
// Create map
for (int row = 0; row < ROWS; row++)
{
for (int column = 0; column < COLUMNS; column++)
{
if (row == 0 || row == ROWS - 1 || column == 0 || column == COLUMNS - 1)
map[column, row] = new Wall();
else
map[column, row] = new EmptySpace();
}
}
while (true) // TODO: add a goal that ends the loop
{
// Draw map
string buffer = "";
for (int row = 0; row < ROWS; row++)
{
string line = "";
for (int column = 0; column < COLUMNS; column++)
{
if (column == playerColumn && row == playerRow)
line += gubbe.printBlock();
else
line += map[column, row].printBlock();
}
//Console.WriteLine(line);
buffer += line + "\n";
}
Console.CursorLeft = 0;
Console.CursorTop = 0;
Console.Write(buffer);
var key = Console.ReadKey();
if (key.Key == ConsoleKey.W)
playerRow--;
else if (key.Key == ConsoleKey.A)
playerColumn--;
else if (key.Key == ConsoleKey.S)
playerRow++;
else if (key.Key == ConsoleKey.D)
playerColumn++;
}//while
}//Map
You could check the type in two different ways:
1st option:
if (map[column, row] is Wall)
{
// Do something
}
2nd option:
if (map[column, row].GetType() == typeof(Wall))
{
// Do something
}

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.
}
}
}
}
}
}

combine adjacent parallel lines

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.

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.

Categories

Resources