Game of Life - Dead - c#

I was bored and had only 30 minutes of free time so I decided to have a crack at making the game of life. I followed that rules on wikipedia and it doesn't seem to be working correctly. Could someone please tell me what I would be doing wrong?
Here are the rules:
Any live cell with fewer than two live neighbours dies, as if caused by under-population.
Any live cell with two or three live neighbours lives on to the next generation.
Any live cell with more than three live neighbours dies, as if by overcrowding.
Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
public void PerformLogic()
{
if (in_game)
{
time_elapsed += rate;
if (time_elapsed > frame_rate)
{
time_elapsed = 0;
for (int x = 0; x < board_width; x++)
{
for (int y = 0; y < board_height; y++)
{
if (board[x, y] == alive)
{
int surrounding_cells = 0;
for (int x2 = -1; x2 <= 1; x2++)
{
for (int y2 = -1; y2 <= 1; y2++)
{
if (!(x2 + x <= -1 || y2 + y <= -1 || x + x2 >= board_width || y + y2 >= board_height))
{
if (board[x + x2, y + y2] == alive)
{
surrounding_cells++;
}
}
}
}
if (surrounding_cells < 2)
{
board[x, y] = dead;
}
if (surrounding_cells == 2 ||
surrounding_cells == 3)
{
board[x, y] = alive;
}
if (surrounding_cells > 3)
{
board[x, y] = dead;
}
}
else if (board[x, y] == dead)
{
int surrounding_cells = 0;
for (int x2 = -1; x2 <= 1; x2++)
{
for (int y2 = -1; y2 <= ; y2++)
{
if (!(x2 + x <= -1 || y2 + y <= -1 || x + x2 >= board_width || y + y2 >= board_height))
{
if (board[x + x2, y + y2] == alive)
{
surrounding_cells++;
}
}
}
}
if (surrounding_cells == 3)
{
board[x, y] = alive;
}
}
}
}
}
}
}
Any ideas?

I believe you are updating the board too early. The game of life should update the board after it finishes scanning the whole board, rather than while scanning.
E.g.:
if (surrounding_cells > 3)
{
board[x, y] = dead;
}
After this, for the cell next to it, this cell would be treated as dead.
Marc is right, too.

for (int x2 = -1; x2 <= 1; x2++)
{
for (int y2 = -1; y2 <= 1; y2++)
{
looks to me like you're including the central cell in this loop, so 9 instead of 8.
I'm not sure the nested for is the best option, but if you are using that, add:
if(x2 == 0 && y2 == 0) continue;
at the start of the inner loop (i.e. after the last line that I've posted above)

Related

recursive stackoverflow minesweeper c#

I am writing a game of minesweeper. Below is code for 3 methods in minesweeper. The first method is to check all the spaces around the button pressed and to count how many bombs are around it. The next method is to be called recursively, in order that if the user pressed a button with 0 buttons around it, it will open all of the squares that also indicate 0 squares around it. The third method is to check that it will be in bound the check. The empty space recursive call is getting me a stackoverflow error, what am I doing wrong?
Thanks!
private int GameLogicChecker(int x, int y)
{
int count = 0;
if (_grid[x, y] != -1)
{
if (x + 1 < SizeX)
{ //Right
if (_grid[x + 1, y] == -1)
count++;
}
if (x - 1 > 0)
{ //Left
if (_grid[x - 1, y] == -1)
count++;
}
if (y + 1 < SizeY)
{ //Upper
if (_grid[x, y + 1] == -1)
count++;
}
if (y - 1 > 0)
{ //Lower
if (_grid[x, y - 1] == -1)
count++;
}
if (x + 1 < SizeX && y + 1 < SizeY)
{ //Right-Upper
if (_grid[x + 1, y + 1] == -1)
count++;
}
if (x + 1 < SizeX && y - 1 > 0)
{ //Right-Lower
if (_grid[x + 1, y - 1] == -1)
count++;
}
if (x - 1 > 0 && y + 1 < SizeY)
{ //Left-Upper
if (_grid[x - 1, y + 1] == -1)
count++;
}
if (x - 1 > 0 && y - 1 > 0)
{ //Left-Lower
if (_grid[x - 1, y - 1] == -1)
count++;
}
}
return count;
}
void OpenEmptySpace(int x, int y)
{
for (var k = -1; k <= 1; k++)
{
for (var l = -1; l <= 1; l++)
{
if (CheckBounds(x + k, y + l) && GameLogicChecker(x + k, y + l) == 0)
{
_buttons[x + k, y + l].Text = "0";
OpenEmptySpace(x + k, y + l);
}
}
}
}
private bool CheckBounds(int x, int y)
{
return x >= 0 && x < SizeX && y >= 0 && y < SizeY;
}
For k = 0 and l = 0, you are calling yourself again and again and again...
Thanks to #BenVoigt for pointing out that two zeroes adjacent to each other will also lead to infinite recursion. So, in order to solve that one method is to create a boolean grid too and set a particular cell's value to true if it has been run through once. Assuming the grid is called Explored, I've added the condition for it in the code below.
If you insist on your current code, try changing the condition to:
if (CheckBounds(x + k, y + l)
&& GameLogicChecker(x + k, y + l) == 0
&& !(k == 0 && l == 0)
&& !Explored[x + k, y + l])
{
Explored[x + k, y + l] = true;
_buttons[x + k, y + l].Text = "0";
OpenEmptySpace(x + k, y + l);
}
Here is another answer for you, rewriting your methods one-by-one following better coding practices. Like in the other answer, a boolean grid called Explored[SizeX, SizeY] has been assumed.
1. GameLogicChecker()
private int GameLogicChecker(int x, int y)
{
if (_grid[x, y] == -1) return 0;
int count = 0;
if (x + 1 < SizeX && _grid[x + 1, y] == -1) //Right
{
count++;
}
if (x - 1 > 0 && _grid[x - 1, y] == -1) //Left
{
count++;
}
if (y + 1 < SizeY && _grid[x, y + 1] == -1) //Upper
{
count++;
}
if (y - 1 > 0 && _grid[x, y - 1] == -1) //Lower
{
count++;
}
if (x + 1 < SizeX && y + 1 < SizeY && _grid[x + 1, y + 1] == -1) //Right-Upper
{
count++;
}
if (x + 1 < SizeX && y - 1 > 0 && _grid[x + 1, y - 1] == -1) //Right-Lower
{
count++;
}
if (x - 1 > 0 && y + 1 < SizeY && _grid[x - 1, y + 1] == -1) //Left-Upper
{
count++;
}
if (x - 1 > 0 && y - 1 > 0 && _grid[x - 1, y - 1] == -1) //Left-Lower
{
count++;
}
return count;
}
What's better? Quicker returning from the method for special case. Reduced nesting in If(...) blocks.
2. OpenEmptySpace()
public/private void OpenEmptySpace(int x, int y)
{
for (var deltaX = -1; deltaX <= 1; deltaX += 2)
{
for (var deltaY = -1; deltaY <= 1; deltaY += 2)
{
var thisX = x + deltaX;
var thisY = y + deltaY;
if (OpeningNotNeeded(thisX, thisY))
{
continue;
}
Explored[thisX, thisY] = true;
_buttons[thisX, thisY].Text = "0";
OpenEmptySpace(thisX, thisY);
}
}
}
private bool OpeningNotNeeded(int x, int y)
{
return !CheckBounds(x, y)
|| GameLogicChecker(x, y) != 0
|| Explored[x, y];
}
What's better? Properly named indexing variables in both loops. Properly written condition (+= 2 instead of ++). Reduced nesting in If(...). Easier to read method call in the If(...) instead of three predicates. Useful temporary variables added which make it clear what x + k and y + l were in the code written earlier.
3. CheckBounds() is written fine.

Knapsack FPTAS and dynamic programming by profit

I'm writing an FPTAS algorithm for Knapsack problem, and found out that I need to implement dynamic programming by profit for that. I have found many resources for dynnamic programming by weight (O(n * W), n - number of items, W - max capacity), but very little for profit based (O(n^2 * C), n - number of items, C highest profit from one item).
I have found only one source with pseudo code here (it's in Polish, but you can see code and functions starting at page 7):
http://www.asdpb.republika.pl/wyk78.pdf
My code:
F = new int[items.Count + 1, (Pmax * items.Count) + 1];
int y;
int k;
int profit = 0;
for (k = 0; k < items.Count; k++)
{
for (y = 0; y < (Pmax * items.Count); y++)
{
if (y == 0 && k >= 1)
F[k, y] = 0;
else if (y >= 1 && k == 0)
F[k, y] = int.MaxValue;
else if (k >= 1 && y >= 1)
{
if (y - items[k].profit < 0)
F[k, y] = (int)Math.Min(F[k - 1, y], int.MaxValue);
else
F[k, y] = (int)Math.Min(F[k - 1, y], F[k - 1, y - items[k].profit] + items[k].weight);
}
}
}
y = 0;
do
{
y++;
for (k = 1; k < items.Count; k++)
{
if (y - items[k].profit < 0)
F[k, y] = F[k - 1, y];
else if (F[k - 1, y - items[k].profit] == int.MaxValue)
F[k, y] = F[k - 1, y];
else
F[k, y] = (int)Math.Min(F[k - 1, y], F[k - 1, y - items[k].profit] + items[k].weight);
if(F[items.Count,y] <= maxCapacity)
profit = y;
}
} while (y < Pmax * items.Count);
I'm using sample data from website linked before:
n = 3
profits = [2,3,1]
weights = [1,3,3]
capacity = 5
But it returns profit = 9 and entirely diffrent table F.
What's wrong with my code? Are there any other good sources for this?
Alternatively I can implement PTAS algorithm but I could not find any good sources either.

Go Board Game - Recursive board group check

Creating a Go Board Game but I'm stuck at checking the board for groups of stones that have been surrounded. To do this I thought I'd need to come up with some recursive functionality:
(Updated)
public List<Point> FindSurrounded(Board board, Point p, Player player, List<Point> group)
{
int[,] b = board.board;
for (int dx = -1; dx <= 1; dx++){
for (int dy = -1; dy <= 1; dy++)
{
//check if group allready contain this spot
if (p.X + dx < board.width && p.Y + dy < board.height && p.X + dx > 0 && p.Y + dy > 0 && (dy == 0 || dx == 0) && !(dy == 0 && dx == 0) && !group.Contains(new Point(p.X + dx, p.Y + dy)))
{
// is the spot empty
if (b[p.X + dx, p.Y + dy] == 0)
return null;
//check the suroundings of this spot and add them to the group
//if(b[p.X + dx, p.Y + dy] != player.Identifier)// is there an enemy on this spot
// return new List<Point>();
if (b[p.X + dx, p.Y + dy] != player.Identifier)
{
group.Add(new Point(p.X + dx, p.Y + dy));
List<Point> temp = FindSurrounded(board, new Point(p.X + dx, p.Y + dy), player, new List<Point>());
if (temp == null)
return null;
//group.AddRange(temp);
}
}
}
}
return group;
}
This code however gives me a System.StackOverFlowException error when I put a stone that surrounds stones of the opponent. The error would concern the following line:
if (p.X + dx < board.width && p.Y + dy < board.height && p.X + dx > 0 && p.Y + dy > 0 && (dy == 0 || dx == 0) && !(dy == 0 && dx == 0) && !group.Contains(new Point(p.X + dx, p.Y + dy)))
But I have no idea why.
Does anyone know a way in which I can check whether a group of stones on the board is surrounded?
Thanks in advance!
Best regards,
Skyfe.
EDIT: Forgot to mention I still have to create an array to temporarily store all found stones that form a group together in order to remove them from the board when they're surrounded.
Answer to the specific question:
Does anyone know a way in which I can check whether a group of stones on the board is surrounded?
Try this approach:
Board b;
int N, M; // dimensions
int timer;
int[,] mark; // assign each group of stones a different number
int[,] mov = // constant to look around
{
{ 0, -1 }, { 0, +1 },
{ -1, 0 }, { +1, 0 }
};
// Checks for a group of stones surrounded by enemy stones
// Returns the first group found or null if there is no such group.
public List<Point> CheckForSurrounded()
{
mark = new int[N,M];
for (int i = 0; i < b.SizeX; ++i)
for (int j = 0; j < b.SizeX; ++j)
if (mark[i, j] == 0) // not visited
{
var l = Fill(i, j);
if (l != null)
return l;
}
return null;
}
// Marks all neighboring stones of the same player in cell [x,y]
// Returns the list of stones if they are surrounded
private List<Point> Fill(int x, int y)
{
int head = 0;
int tail = 0;
var L = new List<Point>();
mark[x, y] = ++timer;
L.Add(new Point(x,y));
while (head < tail)
{
x = L[head].X;
y = L[head].Y;
++head;
for (int k = 0; k < 4; ++k)
{
// new coords
int xx = x + mov[k,0];
int yy = y + mov[k,1];
if (xx >= 0 && xx < N && yy >= 0 && yy < M) // inside board
{
if (mark[xx, yy] == 0) // not visited
{
if (b[xx, yy].IsEmpty) // if empty square => not surrounded
return null;
if (b[xx, yy].IsMine)
{
L.Add(new Point(xx,yy)); // add to queue
mark[xx, yy] = timer; // visited
++tail;
}
}
}
}
}
// the group is surrouneded
return L;
}
This method doesn't use recursion so you don't have to deal with stack overflow (the exception not the site).
You could do it with code that does something like this.
pseudocode
isSurrounded(stone){
//mark that you have seen the stone before
stone.seen = true;
//check if all the surrounding spots are surrounded
for(spot in surrounded.getSpotsAround){
//An empty spot means the stone is not surrounded
if(spot = empty){
return false;
}
else{
//don't recheck stones you have seen before or opponents stones
if(spot.stone.seen != true || !stone.belongsToOpponent){
//recursively call this method, if it returns false your stone is not surrounded
if(!isSurrounded(spot.stone){
return false;
}
}
}
}
//if all of the surrounding stones are surrounded,seen already, or belong to other players, this stone is surrounded
return true;
}
Then you would have to remove all the stones where seen = true or reset seen on all stones.
I came up with this
(Updated)
public List<Point> FindSurrounded(int[,] b, Point p, Player player, List<Point> group)
{
for (int dx = -1; dx <= 1; dx++){
for (int dy = -1; dy <= 1; dy++)
{
//check if group allready contain this spot
if ((dy == 0 || dx == 0) && !(dy == 0 && dx == 0) && !group.Contains(new Point(p.X + dx, p.Y + dy))
{
// is the spot empty
if( b[p.X + dx, p.Y + dy] == 0)
return null;
if(b[p.X + dx, p.Y + dy] == player.Identifier)// is this your own stone
{
//If this is my stone add it to the list and check for it
group.Add( new Point( p.X + dx, p.Y + dy ) );
List<Point> temp = removeSurrounded(b, new Point(p.X + dx, p.Y + dy), player, group);
if(temp == null)
return null;
}
}
}
}
return group;
}
This returns null if there is any empty spot near your group else it will return a list of Points which represents your group.
Afterwards you can remove them like that
List<Point> group = FindSurrounded(b, p, player, new List<Point>());
if(group != null)
foreach(Point point in group)
b[point.x, point.y] = 0;

Console Write to cursor position

I'm drawing a cross in the console. Here's my code:
for (int x = 0; x < 320; x++)
{
for (int y = 0; y < 100; y++)
{
Console.SetCursorPosition(Convert.ToInt32(x / 4),Convert.ToInt32(y / 4));
if (x == 160)
{
if (y == 50)
{
Console.Write("┼");
}
else
{
Console.Write("│");
}
}
else
{
if (y == 50)
{
Console.Write("─");
}
}
}
}
The console draws the cross except the middle "┼" symbol. When I debugged the program it hit the Console.Write("┼"); line. Instead the program written the "─" symbol. What I'm doing wrong and how to solve this problem?
The problem seems to be that you are writing to each location multiple times because of the part where you divide by 4.
When (x, y) is (160, 50) you write a cross at (40, 12). Then (x, y) is (160, 51) so you write a vertical pipe at the same location, overwriting the cross. Then later when (x, y) becomes (161, 50) you overwrite the pipe with a dash.
Try this instead:
for (int x = 0; x < 80; x++)
{
Console.SetCursorPosition(x, 12);
Console.Write("─");
}
for (int y = 0; y < 25; y++)
{
Console.SetCursorPosition(40, y);
Console.Write("|");
}
Console.SetCursorPosition(40, 12);
Console.Write("┼");

Edge detection on C#

I have a black and white image like this (color overlays are mine, and can be removed):
I need to figure out the edge of the hand shown, how can I do that?
My current algorithm:
List<Point> edgePoints = new List<Point>();
for (int x = 0; x < largest.Rectangle.Width && edgePoints.Count == 0; x++) {
//top
for (int y = 0; y < largest.Rectangle.Height - 3 && edgePoints.Count == 0; y++) {
if (colorGrid[x, y].ToArgb() == Color.White.ToArgb() &&
colorGrid[x, y + 1].ToArgb() == Color.White.ToArgb() &&
colorGrid[x, y + 2].ToArgb() == Color.White.ToArgb() &&
colorGrid[x, y + 3].ToArgb() == Color.White.ToArgb()
) {
edgePoints.Add(new Point(x, y));
//g.DrawLine(new System.Drawing.Pen(Color.Orange), new Point(largest.Rectangle.X + x, largest.Rectangle.Y + y), new Point(largest.Rectangle.X + x, largest.Rectangle.Y + y + 3));
break;
}
}
//bottom
for (int y = largest.Rectangle.Height - 1; y > 3 && edgePoints.Count == 0; y++) {
if (colorGrid[x, y].ToArgb() == Color.White.ToArgb() &&
colorGrid[x, y - 1].ToArgb() == Color.White.ToArgb() &&
colorGrid[x, y - 2].ToArgb() == Color.White.ToArgb() &&
colorGrid[x, y - 3].ToArgb() == Color.White.ToArgb()
) {
edgePoints.Add(new Point(x, y));
//g.DrawLine(new System.Drawing.Pen(Color.Orange), new Point(largest.Rectangle.X + x, largest.Rectangle.Y + y), new Point(largest.Rectangle.X + x, largest.Rectangle.Y + y + 3));
break;
}
}
}
Results in a fairly well defined outline, but if the and curves in anywhere, that edge is not detected. I.E., if I held my hand sideways, I'd get the edge of the top finger and bottom finger, but that's it.
What can I do to correct this and get a real edge?
Have a look on projects like this: http://code.google.com/p/aforge/ that will help you a lot and you dont have to reinvent the wheel!
There is a solution on C++ http://outliner.codeplex.com/
But it will not be an easy task to convert it to C#, the algorithm is quite complex.

Categories