Basically, I start with an xBudget for horizontal movements and yBudget for vertical movements. After each row/column iteration, corresponding budget is spend by 'one' amount.

We end when we are trying to make a horizontal movement but have no budget or when we try to make a vertical movement and have no budget.

We take turns between making horizontal movements and vertical movements.

We also take turns between moving right/left and moving down/up.

We start at an imaginary x=-1, y=0 location.

```
public class Solution {
public IList<int> SpiralOrder(int[,] matrix) {
IList<int> result = new List<int>();
if(matrix == null)
return result;
int xBudget = matrix.GetLength(1);
int yBudget = matrix.GetLength(0)-1;
bool xAsc = true;
bool yDesc = true;
bool xTurn = true;
int x = -1, y = 0;
while((xTurn && xBudget != 0) || (!xTurn && yBudget != 0))
{
if(xTurn)
{
xTurn = false;
if(xAsc)
{
xAsc = false;
for(int i = 0; i < xBudget; i++)
result.Add(matrix[y,++x]);
}
else
{
xAsc = true;
for(int i = 0; i < xBudget; i++)
result.Add(matrix[y,--x]);
}
--xBudget;
}
else
{
xTurn = true;
if(yDesc)
{
yDesc = false;
for(int i = 0; i < yBudget; i++)
result.Add(matrix[++y, x]);
}
else
{
yDesc = true;
for(int i = 0; i < yBudget; i++)
result.Add(matrix[--y, x]);
}
--yBudget;
}
}
return result;
}
```

}