• C#输出N阶魔方方阵(带校验)[原创]


    昨天同事发了个图片过来,要求输出N阶魔方的,横竖跟对角线的和都相等!

    所以就研究了一下,感觉里面的算法比较容易把人搞晕,C#代码如下:

    using System;

    namespace MagiCube
    {
    class Program
    {
    static void Main(string[] args)
    {
    int n = 0;
    bool parseOK = false;
    bool exit = false;
    do
    {
    do
    {
    try
    {
    Console.Clear();
    Console.WriteLine(
    "请输入魔方的阶数:");
    n
    = Int32.Parse(Console.ReadLine());
    if (n < 3 || n > 99)
    {
    Console.WriteLine(
    "输入的数字不能小于3或大于99,请重试!");
    Console.ReadKey();
    parseOK
    = false;
    continue;
    }
    parseOK
    = true;
    }
    catch (FormatException)
    {
    Console.WriteLine(
    "输入的不是整数,请重试!");
    parseOK
    = false;
    Console.ReadKey();
    }
    }
    while (!parseOK);
    GetData(n,
    true);
    Console.WriteLine(
    "是否继续运行?(按“Y”继续,否则退出!)");
    exit
    = (Console.ReadKey().Key.ToString().ToLower() == "y" ? false : true);
    }
    while (!exit);
    }

    public static void GetData(int n,bool checkSum) //根据n的值决定调用的函数,并输出结果
    {
    int[,] N = new int[n, n];
    if (n % 2 != 0) //n为基数时
    {
    N
    = Odd(n);
    }
    else if (n % 4 == 0) //n为4的倍数时
    {
    N
    = Even(n);
    }
    else if (n % 4 == 2) //n为非4的倍数的其他偶数时(n%4==2)
    {
    N
    = Even2(n);
    }
    //else
    //{
    // Console.WriteLine("无法处理数字 {0} !", n);
    //}
    Console.WriteLine(new string('=', 50));
    Print(N);
    if (checkSum)
    {
    Console.WriteLine(
    new string('=', 50));
    CheckSum(N);
    }
    Console.WriteLine(
    new string('=', 50));
    }

    public static void CheckSum(int[,] N) //输出N阶魔方每行每列及对角线的和
    {
    int row = N.GetLength(0);
    int col = N.GetLength(1);
    int sumrow = 0;
    int sumcol = 0;
    int sumdia = 0;
    for (int x = 0; x < row; x++)
    {
    for (int y = 0; y < col; y++)
    {
    sumrow
    += N[x, y];
    sumcol
    += N[y, x];
    }
    Console.WriteLine(
    "行{0}:{1},列{0}:{1}", x + 1, sumrow, x + 1, sumcol);
    sumrow
    = 0;
    sumcol
    = 0;
    }
    for (int m = 0; m < row; m++)
    {
    sumdia
    += N[m, m];
    }
    Console.Write(
    "对角线1:{0},", sumdia);
    sumdia
    = 0;
    int i = 0;
    for (int j = (col - 1); j >= 0; j--)
    {
    sumdia
    += N[i, j];
    }
    Console.WriteLine(
    "对角线2:{0}", sumdia);
    }

    public static int[,] Odd(int n) //n为基数时
    {
    int[,] N = new int[n, n];
    int x = 0;
    int y = (n - 1) / 2;
    for (int i = 1; i <= n * n; i++)
    {
    x
    = (x < 0 ? (n + x) : (x > (n - 1) ? (x - n) : x));
    y
    = (y > (n - 1) ? (y - n) : (y < 0 ? (n + y) : y));
    if (N[x, y] == 0)
    {
    if ((i % n) == 0 && i != 1)
    {
    N[x
    ++, y] = i;
    }
    else
    {
    N[x
    --, y++] = i;
    }
    }
    }
    return N;
    }

    public static int[,] Even(int n) //n为4的倍数时
    {
    int[,] N = new int[n, n];
    /*消去对角线法
    * 适用:四之倍数阶魔方阵
    * 方法:(1)先将整个方阵划分成k*k个4阶方阵,然后在每个4阶方阵的对角线上做记号
    * (2)由左而右、由上而下,遇到没有记号的位置才填数字,但不管是否填入数字,每移动一格数字都要加1
    * (3)自右下角开始,由右而左、由下而上,遇到没有数字的位置就填入数字,但每移动一格数字都要加1
    * 参考:
    http://blog.dns0351.com/article/DailyBlog/479.htm
    */
    for (int x = 0; x < n; x += 4)
    {
    for (int y = 0; y < n; y += 4)
    {
    N[x, y]
    = 1;
    N[x
    + 3, y + 3] = 1;

    N[x
    + 1, y + 1] = 1;
    N[x
    + 2, y + 2] = 1;

    N[x, y
    + 3] = 1;
    N[x
    + 3, y] = 1;

    N[x
    + 1, y + 2] = 1;
    N[x
    + 2, y + 1] = 1;
    }
    }
    int m = n * n;
    for (int i = 1; i <= n * n; i++)
    {
    if (N[(i - 1) / n, (i - 1) % n] != 1)
    {
    N[(i
    - 1) / n, (i - 1) % n] = i;
    }
    else
    {
    N[(i
    - 1) / n, (i - 1) % n] = m;
    }
    m
    --;
    }
    return N;
    }

    public static int[,] Even2(int n) //n为非4的倍数的其他偶数时(n%4==2)
    {
    /* n为非4的倍数的其他偶数时,划分成四个奇数方阵示意图
    * |
    * B区(次小) | C区(次大)
    * ---------------------------
    * D区(最大) | A区(最小)
    * |
    */
    int[,] N = new int[n, n];
    int[,] initN = Odd(n / 2);
    int v = n * n / 4;
    for (int x = 0; x < n / 2; x++)
    {
    for (int y = 0; y < n / 2; y++)
    {
    N[x
    + n / 2, y + n / 2] = initN[x, y]; //A区
    N[x, y] = initN[x, y] + v; //B区
    N[x, y + n / 2] = initN[x, y] + 2 * v; //C区
    N[x + n / 2, y] = initN[x, y] + 3 * v; //D区
    }
    }
    int tmp;
    int m = (n - 2) / 4;
    if (m > 1)
    {
    for (int i = 0; i <= m - 2; i++)
    {
    for (int j = 0; j < n / 2; j++)
    {
    tmp
    = N[i, j];
    N[i, j]
    = N[i, n / 2 + j];
    N[i, n
    / 2 + j] = tmp;
    }
    }
    }
    for (int i = n - m; i < n; i++)
    {
    for (int j = 0; j < n / 2; j++)
    {
    tmp
    = N[i, j];
    N[i, j]
    = N[i, n / 2 + j];
    N[i, n
    / 2 + j] = tmp;
    }
    }
    tmp
    = N[n / 2 + m, m];
    N[n
    / 2 + m, m] = N[n / 2 + m, n / 2 + m];
    N[n
    / 2 + m, n / 2 + m] = tmp;
    tmp
    = N[n - 1, m];
    N[n
    - 1, m] = N[n - 1, n / 2 + m];
    N[n
    - 1, n / 2 + m] = tmp;
    return N;
    }

    public static void Print(int[,] N)
    {
    int maxLength = 4;
    int preLen = 0;
    for (int i = 0; i < N.GetLength(0); i++)
    {
    for (int j = 0; j < N.GetLength(1); j++)
    {
    Console.Write(
    new String(' ', maxLength - preLen));
    Console.Write(N[i, j]);
    preLen
    = N[i, j].ToString().Length;
    }
    for (int k = 0; k < maxLength - 2; k++)
    {
    Console.WriteLine(
    "");
    }
    preLen
    = 0;
    }
    }
    }
    }
  • 相关阅读:
    java调用oracle存储过程
    高富帅屌丝买房差异大 看看都该买什么房
    c#控制IE浏览器自动点击等事件WebBrowser,mshtml.IHTMLDocument2
    .net 实现微信公众平台的主动推送信息
    HTML+CSS面试知识点分享(一)
    JS面试知识点分享(一)
    HTML+CSS面试知识点分享(二)
    jQuery选择器学习理解
    PB程序系统错误处理记录
    sql server2000 直接读取excel2003文件的sheet
  • 原文地址:https://www.cnblogs.com/mic86/p/1905988.html
Copyright © 2020-2023  润新知