using System; using System.Threading; const int width = 50; const int height = 10; const int Air = 0; const int Sand = 1; int[] grid = new int[width * height]; int spawnX = width / 2; int spawnY = 0; grid[spawnY * width + spawnX] = Sand; while (true) { // INPUT: while (Console.KeyAvailable) { var key = Console.ReadKey(intercept: true).Key; if (key == ConsoleKey.Spacebar) { int spawnIndex = spawnY * width + spawnX; if (grid[spawnIndex] == Air) grid[spawnIndex] = Sand; } if (key == ConsoleKey.RightArrow) spawnX += 1; if (key == ConsoleKey.LeftArrow) spawnX -= 1; spawnX = Math.Clamp(spawnX, 0, width - 1); } // UPDATE: Console.Clear(); for (int y = height - 2; y >= 0; y--) { int row = y * width; int rowBelow = (y + 1) * width; bool leftToRight = (y & 1) == 0; int xStart = leftToRight ? 0 : width - 1; int xEnd = leftToRight ? width : -1; int xStep = leftToRight ? 1 : -1; for (int x = xStart; x != xEnd; x += xStep) { int idx = row + x; if (grid[idx] != Sand) continue; int downIdx = rowBelow + x; if (grid[downIdx] == Air) { grid[downIdx] = Sand; grid[idx] = Air; continue; } bool canLeft = x > 0; bool canRight = x + 1 < width; int downLeftIdx = rowBelow + (x - 1); int downRightIdx = rowBelow + (x + 1); bool emptyLeft = canLeft && grid[downLeftIdx] == Air; bool emptyRight = canRight && grid[downRightIdx] == Air; if (!emptyLeft && !emptyRight) continue; bool goLeft = emptyLeft && (!emptyRight || ((x + y) & 1) == 0); int target = goLeft ? downLeftIdx : downRightIdx; grid[target] = Sand; grid[idx] = Air; } } // RENDER: for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int v = grid[y * width + x]; char c = v == Sand ? '#' : '.'; Console.Write(c); } Console.WriteLine(); } Thread.Sleep(25); }