像蛇一样打印矩阵
Printing a matrix like a snake
我要像蛇一样在 C# 中打印一个矩阵,类似这样的东西。关于如何进行的任何建议?
1 2 3 4 5 6
6
1 2 3 4 6
1 4 6
1 4 6
1 4 6
1 3 4 6
1 6
1 2 3 4 5 6
这是我目前的代码。基本上我需要弄清楚如何跳过行和列。
Console.WriteLine("Enter your number: ");
int n = Convert.ToInt32(Console.ReadLine());
int[,] a = new int[n, n];
int printVal = 1;
int c1 = 0, c2 = n - 1;
while(printVal <= n * n)
{
//dvizenje na desno
for (int i = c1; i <= c2; i++)
a[c1, i] = printVal++;
//dvizenje nadolu
for (int j = c1 + 1; j <= c2; j++)
a[j, c2] = printVal++;
// dvizenje na levo
for (int i = c2 - 1; i >= c1; i--)
a[c2, i] = printVal++;
//dvizenje nagore
for (int j = c2 - 1; j >= c1 + 1; j--)
a[j, c1] = printVal++;
c1++;
c2--;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(a[i, j] + "\t");
}
Console.WriteLine();
}
类似的东西,它还没有完成,可以更有效,但它是想法(Builder Design Pattern)
public class NumberElement
{
private StringBuilder sb;
public NumberElement()
{
sb = new StringBuilder();
}
public void AddNumbers(int Numbers)
{
for(int i = 1; i < Numbers + 1; i++)
{
AddNumber(i);
}
}
public void AddSpaces(int SpaceNumber)
{
for (int i = 1; i < SpaceNumber + 1; i++)
{
AddSpace();
}
}
public void AddNumber(int number)
{
sb.Append(number + " ");
}
public void AddSpace()
{
sb.Append(" ");
}
public void AddNewLine()
{
sb.Append("\n");
}
public override string ToString()
{
return sb.ToString();
}
}
class Program
{
static public void Example(NumberElement ne)
{
//Line 1
ne.AddNumbers(6);
ne.AddNewLine();
//Line 2
ne.AddSpaces(5);
ne.AddNumber(6);
ne.AddNewLine();
//Line 3
ne.AddNumbers(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 4
ne.AddNumber(1);
ne.AddSpaces(2);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 5
ne.AddNumber(1);
ne.AddSpaces(2);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 6
ne.AddNumber(1);
ne.AddSpaces(2);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 6
ne.AddNumber(1);
ne.AddSpace();
ne.AddNumber(3);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 7
ne.AddNumber(1);
ne.AddSpaces(4);
ne.AddNumber(6);
ne.AddNewLine();
//Line 8
ne.AddNumbers(6);
}
static void Main(string[] args)
{
NumberElement ne = new NumberElement();
Example(ne);
Console.WriteLine(ne);
}
}
作为快速练习,我制作了完整版本。如果有人感兴趣,这里是:
enum Directions { Right, Down, Left, Up }
Dictionary<Directions, Point> moves = new Dictionary<Directions, Point>
{
{ Directions.Right, new Point(1, 0) },
{ Directions.Down, new Point(0, 1) },
{ Directions.Left, new Point(-1,0) },
{ Directions.Up, new Point(0,-1) },
};
int?[,] MakeSpiral(int rows, int columns)
{
int?[,] field = new int?[rows, columns];
Point current = new Point(0, 0);
Directions direction = Directions.Right;
while(true)
{
field[current.Y, current.X] = current.X + 1;
Point next = current + moves[direction];
if(!IsFieldPositionValid(next, current))
{
// If we can't make a move, change direction clockwise
direction = (Directions)((int)(direction + 1) % 4);
}
next = current + moves[direction];
if(!IsFieldPositionValid(next, current))
{
// If we can't make a move after changing the direction
// it means that we are stuck and we completed the spiral
return field;
}
current = next;
}
// Checks whether we can put a value in a given position
// taking into consideration whether it is out of bounds of the field
// and if it's too close to other values
bool IsFieldPositionValid(Point position, Point previous)
{
if(IsFieldPositionOutOfBounds(position))
return false;
if(!CheckSurroundings(position, point => !field[point.Y, point.X].HasValue, previous))
return false;
return true;
}
// Checks the positions in 4 directions using the isValid predicate.
// Doesn't check the point that is given as the exclude parameter:
// this is used so that we don't count the point we just moved from
bool CheckSurroundings(Point position, Predicate<Point> isValid, Point? exclude = null)
{
foreach(Point move in moves.Values)
{
Point newPosition = position + move;
if(IsFieldPositionOutOfBounds(newPosition))
continue;
if(!isValid(newPosition) && (!exclude.HasValue || exclude.Value != newPosition))
return false;
}
return true;
}
bool IsFieldPositionOutOfBounds(Point position)
{
return position.Y >= field.GetLength(0) || position.X >= field.GetLength(1) || position.Y < 0 || position.X < 0;
}
}
并打印结果:
var spiral = MakeSpiral(9, 6);
for(int i = 0; i < spiral.GetLength(0); i++)
{
for(int j = 0; j < spiral.GetLength(1); j++)
{
Console.Write(spiral[i, j]?.ToString() ?? " ");
Console.Write(" ");
}
Console.WriteLine();
}
输出:
1 2 3 4 5 6
6
1 2 3 4 6
1 4 6
1 4 6
1 4 6
1 3 4 6
1 6
1 2 3 4 5 6
它不适用于大于 11 的值。下一个版本,稍微复杂一些,可以工作:
var spiral = Spiral(14, 24);
for(int i = 0; i < spiral.GetLength(0); i++)
{
for(int j = 0; j < spiral.GetLength(1); j++)
{
Console.Write(spiral[i, j]?.ToString() ?? new string(' ', (j + 1).ToString().Length));
Console.Write(" ");
}
Console.WriteLine();
}
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 24
1 22 24
1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 24
1 3 20 22 24
1 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 22 24
1 3 5 18 20 22 24
1 3 5 20 22 24
1 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 24
1 3 22 24
1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 24
1 24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
它需要来自某处的 Point
结构,如果您不想导入任何依赖项,我也为此做了一个基本实现:
struct Point : IEquatable<Point>
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y) { X = x; Y = y; }
public static Point operator +(Point left, Point right) => new Point(left.X + right.X, left.Y + right.Y);
public static Point operator -(Point point) => new Point(-point.X, -point.Y);
public static Point operator -(Point left, Point right) => left + -right;
public static bool operator ==(Point left, Point right) => left.Equals(right);
public static bool operator !=(Point left, Point right) => !left.Equals(right);
public bool Equals(Point point) => this.X == point.X && this.Y == point.Y;
public override bool Equals(object other) => other is Point p ? Equals(p) : false;
public override int GetHashCode() => unchecked(17 * (X + 31 * Y));
}
我要像蛇一样在 C# 中打印一个矩阵,类似这样的东西。关于如何进行的任何建议?
1 2 3 4 5 6
6
1 2 3 4 6
1 4 6
1 4 6
1 4 6
1 3 4 6
1 6
1 2 3 4 5 6
这是我目前的代码。基本上我需要弄清楚如何跳过行和列。
Console.WriteLine("Enter your number: ");
int n = Convert.ToInt32(Console.ReadLine());
int[,] a = new int[n, n];
int printVal = 1;
int c1 = 0, c2 = n - 1;
while(printVal <= n * n)
{
//dvizenje na desno
for (int i = c1; i <= c2; i++)
a[c1, i] = printVal++;
//dvizenje nadolu
for (int j = c1 + 1; j <= c2; j++)
a[j, c2] = printVal++;
// dvizenje na levo
for (int i = c2 - 1; i >= c1; i--)
a[c2, i] = printVal++;
//dvizenje nagore
for (int j = c2 - 1; j >= c1 + 1; j--)
a[j, c1] = printVal++;
c1++;
c2--;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(a[i, j] + "\t");
}
Console.WriteLine();
}
类似的东西,它还没有完成,可以更有效,但它是想法(Builder Design Pattern)
public class NumberElement
{
private StringBuilder sb;
public NumberElement()
{
sb = new StringBuilder();
}
public void AddNumbers(int Numbers)
{
for(int i = 1; i < Numbers + 1; i++)
{
AddNumber(i);
}
}
public void AddSpaces(int SpaceNumber)
{
for (int i = 1; i < SpaceNumber + 1; i++)
{
AddSpace();
}
}
public void AddNumber(int number)
{
sb.Append(number + " ");
}
public void AddSpace()
{
sb.Append(" ");
}
public void AddNewLine()
{
sb.Append("\n");
}
public override string ToString()
{
return sb.ToString();
}
}
class Program
{
static public void Example(NumberElement ne)
{
//Line 1
ne.AddNumbers(6);
ne.AddNewLine();
//Line 2
ne.AddSpaces(5);
ne.AddNumber(6);
ne.AddNewLine();
//Line 3
ne.AddNumbers(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 4
ne.AddNumber(1);
ne.AddSpaces(2);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 5
ne.AddNumber(1);
ne.AddSpaces(2);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 6
ne.AddNumber(1);
ne.AddSpaces(2);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 6
ne.AddNumber(1);
ne.AddSpace();
ne.AddNumber(3);
ne.AddNumber(4);
ne.AddSpace();
ne.AddNumber(6);
ne.AddNewLine();
//Line 7
ne.AddNumber(1);
ne.AddSpaces(4);
ne.AddNumber(6);
ne.AddNewLine();
//Line 8
ne.AddNumbers(6);
}
static void Main(string[] args)
{
NumberElement ne = new NumberElement();
Example(ne);
Console.WriteLine(ne);
}
}
作为快速练习,我制作了完整版本。如果有人感兴趣,这里是:
enum Directions { Right, Down, Left, Up }
Dictionary<Directions, Point> moves = new Dictionary<Directions, Point>
{
{ Directions.Right, new Point(1, 0) },
{ Directions.Down, new Point(0, 1) },
{ Directions.Left, new Point(-1,0) },
{ Directions.Up, new Point(0,-1) },
};
int?[,] MakeSpiral(int rows, int columns)
{
int?[,] field = new int?[rows, columns];
Point current = new Point(0, 0);
Directions direction = Directions.Right;
while(true)
{
field[current.Y, current.X] = current.X + 1;
Point next = current + moves[direction];
if(!IsFieldPositionValid(next, current))
{
// If we can't make a move, change direction clockwise
direction = (Directions)((int)(direction + 1) % 4);
}
next = current + moves[direction];
if(!IsFieldPositionValid(next, current))
{
// If we can't make a move after changing the direction
// it means that we are stuck and we completed the spiral
return field;
}
current = next;
}
// Checks whether we can put a value in a given position
// taking into consideration whether it is out of bounds of the field
// and if it's too close to other values
bool IsFieldPositionValid(Point position, Point previous)
{
if(IsFieldPositionOutOfBounds(position))
return false;
if(!CheckSurroundings(position, point => !field[point.Y, point.X].HasValue, previous))
return false;
return true;
}
// Checks the positions in 4 directions using the isValid predicate.
// Doesn't check the point that is given as the exclude parameter:
// this is used so that we don't count the point we just moved from
bool CheckSurroundings(Point position, Predicate<Point> isValid, Point? exclude = null)
{
foreach(Point move in moves.Values)
{
Point newPosition = position + move;
if(IsFieldPositionOutOfBounds(newPosition))
continue;
if(!isValid(newPosition) && (!exclude.HasValue || exclude.Value != newPosition))
return false;
}
return true;
}
bool IsFieldPositionOutOfBounds(Point position)
{
return position.Y >= field.GetLength(0) || position.X >= field.GetLength(1) || position.Y < 0 || position.X < 0;
}
}
并打印结果:
var spiral = MakeSpiral(9, 6);
for(int i = 0; i < spiral.GetLength(0); i++)
{
for(int j = 0; j < spiral.GetLength(1); j++)
{
Console.Write(spiral[i, j]?.ToString() ?? " ");
Console.Write(" ");
}
Console.WriteLine();
}
输出:
1 2 3 4 5 6
6
1 2 3 4 6
1 4 6
1 4 6
1 4 6
1 3 4 6
1 6
1 2 3 4 5 6
它不适用于大于 11 的值。下一个版本,稍微复杂一些,可以工作:
var spiral = Spiral(14, 24);
for(int i = 0; i < spiral.GetLength(0); i++)
{
for(int j = 0; j < spiral.GetLength(1); j++)
{
Console.Write(spiral[i, j]?.ToString() ?? new string(' ', (j + 1).ToString().Length));
Console.Write(" ");
}
Console.WriteLine();
}
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 24
1 22 24
1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 24
1 3 20 22 24
1 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 22 24
1 3 5 18 20 22 24
1 3 5 20 22 24
1 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 24
1 3 22 24
1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 24
1 24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
它需要来自某处的 Point
结构,如果您不想导入任何依赖项,我也为此做了一个基本实现:
struct Point : IEquatable<Point>
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y) { X = x; Y = y; }
public static Point operator +(Point left, Point right) => new Point(left.X + right.X, left.Y + right.Y);
public static Point operator -(Point point) => new Point(-point.X, -point.Y);
public static Point operator -(Point left, Point right) => left + -right;
public static bool operator ==(Point left, Point right) => left.Equals(right);
public static bool operator !=(Point left, Point right) => !left.Equals(right);
public bool Equals(Point point) => this.X == point.X && this.Y == point.Y;
public override bool Equals(object other) => other is Point p ? Equals(p) : false;
public override int GetHashCode() => unchecked(17 * (X + 31 * Y));
}