数独解密小程序

本程序为C#控制台(.Net Framework 目标框架)
使用方法在data.csv中填好已有的数据,需要解密的数据空着不填。运行程序前一定要关闭data.csv数据文件。

using System;
using System.Diagnostics;
using System.IO;

namespace 数独解密
{
    class Program
    {
        static void Main()
        {
            // 动态确定数独板的大小
            int size = GetBoardSizeFromCsv("data.csv");

            // 创建一个动态大小的二维数组来表示数独板
            int[,] board = new int[size, size];

            // 从CSV文件读取数独板的初始值
            ReadFromCsv(board, "sudoku.csv");

            // 创建一个 Stopwatch 实例用于计时
            Stopwatch stopwatch = new Stopwatch();

            // 开始计时
            stopwatch.Start();

            // 调用递归函数尝试解决数独
            if (SolveSudoku(board, size))
            {
                // 如果成功解决数独,则打印结果
                PrintBoard(board, size);
            }
            else
            {
                // 如果没有解,则打印消息
                Console.WriteLine("没有解");
            }

            // 停止计时
            stopwatch.Stop();

            // 输出耗时
            Console.WriteLine($"耗时: {stopwatch.Elapsed.TotalMilliseconds} 毫秒");

            Console.ReadKey();
        }

        // 从CSV文件中获取数独板的大小
        static int GetBoardSizeFromCsv(string filePath)
        {
            int maxValue = 0; // 初始化最大值为0
            using (var reader = new StreamReader(filePath))
            {
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine(); // 读取一行
                    var values = line.Split(','); // 按逗号分割该行

                    // 遍历该行中的每个值
                    foreach (var value in values)
                    {
                        if (!string.IsNullOrEmpty(value)) // 如果值不为空
                        {
                            int num = int.Parse(value); // 将字符串转换为整数
                            if (num > maxValue) // 更新最大值
                            {
                                maxValue = num;
                            }
                        }
                    }
                }
            }
            return maxValue; // 返回最大值,作为数独板的大小
        }

        // 从CSV文件读取数独板的初始值
        static void ReadFromCsv(int[,] board, string filePath)
        {
            using (var reader = new StreamReader(filePath))
            {
                int row = 0;
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine(); // 读取一行
                    var values = line.Split(','); // 按逗号分割该行

                    // 遍历该行中的每个值
                    for (int col = 0; col < values.Length; col++)
                    {
                        if (values[col] != "") // 如果值不为空
                        {
                            board[row, col] = int.Parse(values[col]); // 将值赋给数独板
                        }
                    }
                    row++; // 行索引递增
                }
            }
        }

        // 递归函数:尝试解决数独
        static bool SolveSudoku(int[,] board, int size)
        {
            // 遍历每一行和每一列
            for (int row = 0; row < size; row++)
            {
                for (int col = 0; col < size; col++)
                {
                    // 如果当前位置是0,表示需要填充
                    if (board[row, col] == 0)
                    {
                        // 尝试填入1到size的数字
                        for (int num = 1; num <= size; num++)
                        {
                            // 检查填入的数字是否有效
                            if (IsValid(board, row, col, num, size))
                            {
                                // 填入数字
                                board[row, col] = num;

                                // 递归调用解决剩余部分
                                if (SolveSudoku(board, size))
                                {
                                    return true; // 如果成功,返回true
                                }
                                else
                                {
                                    // 如果失败,重置当前位置为0
                                    board[row, col] = 0;
                                }
                            }
                        }
                        // 如果1到size的数字都不能填入,返回false
                        return false;
                    }
                }
            }
            // 如果没有空位置,说明解决成功
            return true;
        }

        // 检查在给定位置填入数字是否有效
        static bool IsValid(int[,] board, int row, int col, int num, int size)
        {
            // 检查同一行是否有相同的数字
            for (int i = 0; i < size; i++)
            {
                if (board[row, i] == num)
                {
                    return false; // 如果有相同的数字,则无效
                }
            }

            // 检查同一列是否有相同的数字
            for (int i = 0; i < size; i++)
            {
                if (board[i, col] == num)
                {
                    return false; // 如果有相同的数字,则无效
                }
            }

            // 检查子宫格中是否有相同的数字
            int boxSize = (int)Math.Sqrt(size); // 子宫格的大小
            int startRow = row - row % boxSize; // 子宫格的起始行
            int startCol = col - col % boxSize; // 子宫格的起始列
            for (int i = 0; i < boxSize; i++)
            {
                for (int j = 0; j < boxSize; j++)
                {
                    if (board[i + startRow, j + startCol] == num)
                    {
                        return false; // 如果有相同的数字,则无效
                    }
                }
            }

            // 如果没有相同的数字,则有效
            return true;
        }

        // 打印数独板
        static void PrintBoard(int[,] board, int size)
        {
            for (int row = 0; row < size; row++)
            {
                for (int col = 0; col < size; col++)
                {
                    Console.Write(board[row, col] + " "); // 打印数字
                }
                Console.WriteLine(); // 打印换行符
            }
        }
    }
}
View Code

 

 

posted @ 2024-07-30 09:52  阿坦  阅读(26)  评论(0编辑  收藏  举报