C# 实现数独游戏

news2024/11/18 1:28:11

1.数独单元

 public struct SudokuCell
    {
        public SudokuCell() : this(0, 0, 0)
        {
        }
        public SudokuCell(int x, int y, int number)
        {
            X = x; Y = y; Number = number;
        }
        public int X { get; set; }
        public int Y { get; set; }
        public int Number { get; set; }
    }

2.数独创建

public class SudokuGenerator
    {
        private const int BoardSize = 9;
        private const int EmptyCellValue = 0;

        private Random random;
        private readonly ChaosRandomEx chaosRandomEx;
        public SudokuGenerator()
        {
            random = new Random();
            chaosRandomEx = new ChaosRandomEx();
        }

        public SudokuCell[,] GenerateSudoku(DifficultyLevel difficulty)
        {
            SudokuCell[,] board = new SudokuCell[BoardSize, BoardSize];

            // 初始化数独网格
            for (int row = 0; row < BoardSize; row++)
            {
                for (int col = 0; col < BoardSize; col++)
                {
                    board[row, col] = new SudokuCell(row, col, EmptyCellValue);
                }
            }

            // 填充数独网格
            FillSudoku(board);

            // 根据难度要求移除部分单元格的值
            RemoveCells(board, difficulty);

            return board;
        }


        private void FillSudoku(SudokuCell[,] board)
        {
            SolveSudoku(board);
        }

        private bool SolveSudoku(SudokuCell[,] board)
        {
            int row = 0;
            int col = 0;

            if (!FindEmptyCell(board, ref row, ref col))
            {
                // 所有单元格都已填满,数独已解决
                return true;
            }

            List<int> numbers = GetRandomNumberSequence();

            foreach (int num in numbers)
            {
                if (IsValidMove(board, row, col, num))
                {
                    // 尝试填充数字
                    board[row, col].Number = num;

                    if (SolveSudoku(board))
                    {
                        // 递归解决剩余的单元格
                        return true;
                    }

                    // 回溯到上一个单元格
                    board[row, col].Number = EmptyCellValue;
                }
            }

            return false;
        }

        private bool FindEmptyCell(SudokuCell[,] board, ref int row, ref int col)
        {
            for (row = 0; row < BoardSize; row++)
            {
                for (col = 0; col < BoardSize; col++)
                {
                    if (board[row, col].Number == EmptyCellValue)
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        public bool IsValidMove(SudokuCell[,] board, int row, int col, int num)
        {
            // 检查行是否合法
            for (int i = 0; i < BoardSize; i++)
            {
                if (board[i, col].Number == num)
                {
                    return false;
                }
            }

            // 检查列是否合法
            for (int i = 0; i < BoardSize; i++)
            {
                if (board[row, i].Number == num)
                {
                    return false;
                }
            }

            // 检查子网格是否合法
            int subgridRow = (row / 3) * 3;
            int subgridCol = (col / 3) * 3;

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (board[subgridRow + i, subgridCol + j].Number == num)
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        private List<int> GetRandomNumberSequence()
        {
            List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            Shuffle(numbers);
            return numbers;
        }

        private void Shuffle<T>(List<T> list)
        {
            int n = list.Count;
            while (n > 1)
            {
                n--;
                int k = random.Next(n + 1);
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }

        private void RemoveCells(SudokuCell[,] board, DifficultyLevel difficulty)
        {
            int cellsToRemove = GetCellsToRemoveCount(difficulty);

            for (int i = 0; i < cellsToRemove; i++)
            {
                int row = random.Next(BoardSize);
                int col = random.Next(BoardSize);

                if (board[row, col].Number != EmptyCellValue)
                {
                    board[row, col].Number = EmptyCellValue;
                }
                else
                {
                    i--;
                }
            }
        }

        private int GetCellsToRemoveCount(DifficultyLevel difficulty)
        {
            return difficulty switch
            {
                DifficultyLevel.Medium => 32,
                DifficultyLevel.Hard => 44,
                DifficultyLevel.VeryHard => 56,
                DifficultyLevel.SuperHard => 68,
                DifficultyLevel.Insane => 80,
                _ => 20
            };
        }
    }

3.数独难度等级

public enum DifficultyLevel
    {
        /// <summary>
        /// 简单
        /// </summary>
        [Remark("简单")]
        Easy,
        /// <summary>
        /// 中等
        /// </summary>
        [Remark("中等")]
        Medium,
        /// <summary>
        /// 困难
        /// </summary>
        [Remark("困难")]
        Hard,
        /// <summary>
        /// 极难
        /// </summary>
        [Remark("极难")]
        VeryHard,
        /// <summary>
        /// 超难
        /// </summary>
        [Remark("超难")]
        SuperHard,
        /// <summary>
        /// 疯狂
        /// </summary>
        [Remark("疯狂")]
        Insane
    }

4.递归回溯算法寻找答案

/// <summary>
    /// 递归回溯算法
    /// </summary>
    public class SudokuSolver
    {
        public SudokuCell[,] SolveSudoku(SudokuCell[,] board)
        {
            var solution = new SudokuCell[board.GetLength(0), board.GetLength(1)];
            Array.Copy(board, solution, board.Length);
            if (BacktrackSolve(solution))
            {
                return solution;
            }
            else
            {
                // 没有找到解
                return null;
            }
        }

        private bool BacktrackSolve(SudokuCell[,] board)
        {
            for (int row = 0; row < 9; row++)
            {
                for (int col = 0; col < 9; col++)
                {
                    if (board[row, col].Number == 0)
                    {
                        for (int num = 1; num <= 9; num++)
                        {
                            if (IsValid(board, row, col, num))
                            {
                                board[row, col].Number = num;

                                if (BacktrackSolve(board))
                                {
                                    return true;
                                }

                                board[row, col].Number = 0; // 回溯
                            }
                        }

                        return false; // 所有数字都尝试过,没有找到合适的解
                    }
                }
            }

            return true; // 数独已经填满,找到解
        }

        private bool IsValid(SudokuCell[,] board, int row, int col, int num)
        {
            // 检查同行是否有重复数字
            for (int i = 0; i < 9; i++)
            {
                if (board[row, i].Number == num)
                {
                    return false;
                }
            }

            // 检查同列是否有重复数字
            for (int i = 0; i < 9; i++)
            {
                if (board[i, col].Number == num)
                {
                    return false;
                }
            }

            // 检查同九宫格是否有重复数字
            int startRow = row - row % 3;
            int startCol = col - col % 3;
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (board[startRow + i, startCol + j].Number == num)
                    {
                        return false;
                    }
                }
            }

            return true; // 没有重复数字
        }
    }

5.数独创建中心

public class SudokuCenter : IDisposable
    {
        public bool IsStart { get; set; } = false;
        private int _width;
        private int _height;
        public const int CELLSNUMBER = 9;
        public const int CELLSNUMBER2 = 20;
        private int _cellSize;
        private int _rowSize;
        public int CellSize=> _cellSize;
        public int RowSize => _rowSize;
        public int Height => _height;
        public int Width => _width;
        public int Padding => CELLSNUMBER2;
        private Bitmap _bitmap;
        public Bitmap GetBitmap
        {
            get=>(Bitmap)_bitmap?.Clone();
            private set => _bitmap = value;
        }
        public SudokuCell[,] Suduku { get;private set; }
        public SudokuCell[,] PlayerSuduku { get; private set; }
        /// <summary>
        /// 生成棋盘图
        /// </summary>
        /// <param name="w"></param>
        /// <param name="h"></param>
        public void InitCheckerBoard(int w, int h)
        {
            w -= (CELLSNUMBER2 * 2 + 1);
            h -= (CELLSNUMBER2 * 2 + 1);
            _width = w;
            _height = h;
            _cellSize = _width / CELLSNUMBER;
            _rowSize = _height / CELLSNUMBER;
            Bitmap bitmap = new Bitmap(_width + CELLSNUMBER2, _height + CELLSNUMBER2);
            using (var g = Graphics.FromImage(bitmap))
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;
                //g.Clear(Color.Gray);
                DrawCheckerBoard(g);
            }
            _bitmap?.Dispose();
            GetBitmap = bitmap;
        }
        public SudokuCell[,] GenerateSudoku(DifficultyLevel difficulty)
        {
            SudokuGenerator sudokuGenerator = new SudokuGenerator();
            Suduku = sudokuGenerator.GenerateSudoku(difficulty);
            PlayerSuduku = new SudokuCell[Suduku.GetLength(0), Suduku.GetLength(1)];
            Array.Copy(Suduku, PlayerSuduku, Suduku.Length);
            return Suduku;
        }
        public Color SudukuColor { get; set; }= Color.Black;
        public Color SolutionColor { get; set; } = Color.Red;
        public Color TransparentColor { get; } = Color.Transparent;
        public Font Font { get; set; }= new Font("Arial", 20, FontStyle.Bold);

        public Bitmap DrawSolution(SudokuCell[,] board)
        {
            using SolidBrush brush = new SolidBrush(SolutionColor);
            using SolidBrush brush2 = new SolidBrush(SudukuColor);
            var bm = GetBitmap;
            using var g = Graphics.FromImage(bm);
            for (int row = 0; row < CELLSNUMBER; row++)
            {
                for (int col = 0; col < CELLSNUMBER; col++)
                {
                   
                    int number = Suduku[row, col].Number;
                    if (number != 0)
                    {
                        DrawString(g, row, col, number.ToString(), brush2);
                    }
                    else
                    {
                        number = board[row, col].Number;
                        DrawString(g, row, col, number.ToString(), brush);
                    }
                }
            }
            return bm;
        }
        public void DrawSudoku(Graphics g, SudokuCell[,] board)
        {
            using SolidBrush brush = new SolidBrush(SudukuColor);


            for (int row = 0; row < CELLSNUMBER; row++)
            {
                for (int col = 0; col < CELLSNUMBER; col++)
                {
                   int num= board[row, col].Number;
                    if((num != 0))
                    {
                        DrawString(g,row,col,num.ToString(), brush);
                    }
                }
            }
        }
        public void DrawString(Graphics g,int row,int col,string number, SolidBrush brush)
        {
            int x = CELLSNUMBER2 + col * _cellSize + _cellSize / 2 - 8;
            int y = CELLSNUMBER2 + row * _rowSize + _rowSize / 2 - 10;
            g.DrawString(number, Font, brush, new Point(x, y));
           
        }
        public Rectangle DrawTransparent(Graphics g, int row, int col)
        {
            int off = 5;
            int off2 = 7;
            int x = CELLSNUMBER2 + col * _cellSize + off;
            int y = CELLSNUMBER2 + row * _rowSize+ off;
            using (SolidBrush brush = new SolidBrush(Color.White)) // 使用透明色进行擦除
            {
                var rec = new Rectangle(x, y, CellSize - off2, RowSize - off2);
                g.FillRectangle(brush, rec);
                return rec;
            }
        }
        public bool IsSolutionCorrect(SudokuCell[,] board, SudokuCell[,] solution)
        {
            for (int row = 0; row < CELLSNUMBER; row++)
            {
                for (int col = 0; col < CELLSNUMBER; col++)
                {
                    if (board[row, col].Number != solution[row, col].Number)
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        public bool IsValidMove(SudokuCell[,] board, int row, int col, int num)
        {
            // 检查行是否合法
            for (int i = 0; i < CELLSNUMBER; i++)
            {
                if (board[i, col].Number == num)
                {
                    return false;
                }
            }

            // 检查列是否合法
            for (int i = 0; i < CELLSNUMBER; i++)
            {
                if (board[row, i].Number == num)
                {
                    return false;
                }
            }

            // 检查子网格是否合法
            int subgridRow = (row / 3) * 3;
            int subgridCol = (col / 3) * 3;

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (board[subgridRow + i, subgridCol + j].Number == num)
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        private void DrawCheckerBoard(Graphics g)
        {
            using Pen pen = new Pen(Color.Black, 1);
            using Pen pen2 = new Pen(Color.Black, 2);
            using Font font = new Font("Arial", 10, FontStyle.Regular);
            using SolidBrush brush = new SolidBrush(Color.Black);

            for (int i = 0; i < CELLSNUMBER + 1; i++)
            {
                if (i == 0 || i % 3 == 0)
                {
                    g.DrawLine(pen2, new Point(CELLSNUMBER2, CELLSNUMBER2 + i * _rowSize), new Point(CELLSNUMBER2 + _cellSize * CELLSNUMBER, CELLSNUMBER2 + i * _rowSize));
                    g.DrawLine(pen2, new Point(CELLSNUMBER2 + i * _cellSize, CELLSNUMBER2 + 0), new Point(CELLSNUMBER2 + i * _cellSize, CELLSNUMBER2 + _rowSize * CELLSNUMBER));
                }
                else
                {
                    g.DrawLine(pen, new Point(CELLSNUMBER2, CELLSNUMBER2 + i * _rowSize), new Point(CELLSNUMBER2 + _cellSize * CELLSNUMBER, CELLSNUMBER2 + i * _rowSize));
                    g.DrawLine(pen, new Point(CELLSNUMBER2 + i * _cellSize, CELLSNUMBER2 + 0), new Point(CELLSNUMBER2 + i * _cellSize, CELLSNUMBER2 + _rowSize * CELLSNUMBER));
                }


                int x = CELLSNUMBER2 + i * _cellSize + _cellSize / 2 - 5;
                int y = 0;
                g.DrawString((i + 1).ToString(), font, brush, new Point(x, y));

                x = 0;
                y = CELLSNUMBER2 + i * _rowSize + _rowSize / 2 - 5;
                g.DrawString((i + 1).ToString(), font, brush, new Point(x, y));
            }
        }

        public void Dispose()
        {
            _bitmap?.Dispose();
        }
    }

 6.数字键盘

 

 public partial class FrmNumber : Form
    {
        public FrmNumber()
        {
            InitializeComponent();

            foreach (Control item in this.Controls)
            {
                item.Click += Item_Click;
            }
        }
        public Action<NumberArg> NumberCallback;
        public Point ClickPoint {  get; set; }
        public Point RowCell { get; set; }
        public Graphics Graphics { get; set; }
        private void Item_Click(object? sender, EventArgs e)
        {
            Button btn = sender as Button;
            NumberArg numberArg = new NumberArg();
            if (btn.Name == "btnClear")
            {
                numberArg.Type = NumberType.Clear;

            }
            else if (btn.Name == "btnClose")
            {
                numberArg.Type = NumberType.Close;
            }
            else
            {
                numberArg.Type = NumberType.Number;
                numberArg.Value = btn.Text;
            }
            numberArg.CllickPoint = ClickPoint;
            numberArg.RowCell = RowCell;
            numberArg.Graphics = Graphics;
            NumberCallback?.Invoke(numberArg);
            this.Close();
        }

        private void FrmNumber_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Dispose();
        }
    }
    public struct NumberArg
    {
        public NumberType Type { get; set; }
        public string Value { get; set; }
        public Point CllickPoint { get; set; }
        public Graphics Graphics { get; set; }
        public Point RowCell { get; set; }
    }
    public enum NumberType
    {
        Clear,
        Close,
        Number
    }

7.主窗体 

 

public partial class FrmMain : Form
    {
        private SudokuCenter _sudokuCenter;
        private System.Windows.Forms.Timer _timer;
        public FrmMain()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer |
              ControlStyles.UserPaint |
              ControlStyles.AllPaintingInWmPaint,
              true);
            this.UpdateStyles();
            this.DoubleBuffered = true;


            _sudokuCenter = new SudokuCenter();
            _sudokuCenter.InitCheckerBoard(this.pbGameBack.Width, this.pbGameBack.Height);
            BindType(typeof(DifficultyLevel), this.cbDifficultyLevel, "Easy");
        }
        private void BindType(Type type, ComboBox comboBox, string defaultValue)
        {
            var enumValues = Enum.GetValues(type);
            var list = new List<IdValues>();
            int index = 0, curIndex = 0;
            foreach (Enum value in enumValues)
            {
                int hc = value.GetHashCode();
                list.Add(new IdValues
                {
                    Id = hc.ToString(),
                    Value = value.ToString(),
                    Display= value.GetEnumDesc(),
                    Standby = hc
                });
                if (value.ToString() == defaultValue)
                    index = curIndex;

                curIndex++;
            }

            comboBox.ValueMember = "Id";
            comboBox.DisplayMember = "Display";
            comboBox.DataSource = list;
            comboBox.SelectedIndex = index;
        }
        private void pbGameBack_Paint(object sender, PaintEventArgs e)
        {
            if (sudukuBitmap != null)
            {
                e.Graphics.DrawImage(sudukuBitmap, 0, 0, pbGameBack.Width, pbGameBack.Height);
            }
        }
        public string Compute(long time)
        {
            if (time < 60)
                return $"00:{ChangeString(time)}";
            long minute = time / 60;
            if (minute < 60)
                return $"{ChangeString(minute)}:{ChangeString(time % 60)}";
            long hour = minute / 60;
            return $"{ChangeString(hour)}:{Compute(time - hour * 3600)}";
        }
        private string ChangeString(long val)
        {
            return val.ToString("D2");
        }

        /// <summary>
        /// 开始
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            StartGame();
        }
        Bitmap sudukuBitmap;
        private void StartGame()
        {
            if (_sudokuCenter.IsStart)
            {
                if (MessageBox.Show("你正在开始游戏,确认重新开始吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
            }

            if (_timer != null)
            {
                _timer.Stop();
                _timer.Dispose();
            }

            time = 0;
            _timer = new System.Windows.Forms.Timer();
            _timer.Interval = 1000;
            _timer.Tick += timer_Tick;
            _timer.Start();

            DifficultyLevel level = (DifficultyLevel)(this.cbDifficultyLevel.Items[cbDifficultyLevel.SelectedIndex] as IdValues).Standby;
            var sudoku = _sudokuCenter.GenerateSudoku(level);
            this.pbGameBack.Image?.Dispose();
            sudukuBitmap?.Dispose();
            sudukuBitmap = null;
            sudukuBitmap = _sudokuCenter.GetBitmap;
            using var g = Graphics.FromImage(sudukuBitmap);
            _sudokuCenter.DrawSudoku(g, sudoku);
            _sudokuCenter.IsStart = true;

            pbGameBack.Invalidate();
        }
        long time = 0;
        private void timer_Tick(object? sender, EventArgs e)
        {
            lblTime.ExecBeginInvoke(() =>
            {
                lblTime.Text = Compute(++time);

            });
        }

        /// <summary>
        /// 答案
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSolution_Click(object sender, EventArgs e)
        {
            if (!_sudokuCenter.IsStart)
            {
                return;
            }
            if (MessageBox.Show("你正在开始游戏,确认显示答案吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
            {
                return;
            }
            SudokuSolver sudokuSolver = new SudokuSolver();
            var solveSudoku = sudokuSolver.SolveSudoku(_sudokuCenter.Suduku);
            var bm = _sudokuCenter.DrawSolution(solveSudoku);

            pbGameBack.Image?.Dispose();
            sudukuBitmap?.Dispose();
            sudukuBitmap = null;
            sudukuBitmap = bm;
            //pbGameBack.Image = bm;
            _sudokuCenter.IsStart = false;
            pbGameBack.Invalidate();
        }

        private void pbGameBack_MouseDown(object sender, MouseEventArgs e)
        {
            if (_sudokuCenter.Suduku == null || !_sudokuCenter.IsStart)
                return;

            int row = (e.Y - _sudokuCenter.Padding * 2) / _sudokuCenter.RowSize;
            int col = (e.X - _sudokuCenter.Padding * 2) / _sudokuCenter.CellSize;
            // 检测鼠标是否在小方格内
            if (row >= 0 && row < 9 && col >= 0 && col < 9)
            {
                var number = _sudokuCenter.Suduku[row, col].Number;
                if (number != 0)
                    return;

                using (FrmNumber fn = new FrmNumber())
                {
                    fn.NumberCallback = NumberCallback;
                    Point p = pbGameBack.PointToScreen(Point.Empty);
                    fn.StartPosition = FormStartPosition.Manual;

                    fn.Location = new Point(p.X + e.X + (_sudokuCenter.CellSize >> 1), p.Y + e.Y + (_sudokuCenter.RowSize >> 1));
                    fn.ClickPoint = new Point(e.X, e.Y);
                    fn.RowCell = new Point(row, col);
                    fn.ShowDialog();
                }
               

            }
        }
        private void NumberCallback(NumberArg arg)
        {
            switch (arg.Type)
            {
                case NumberType.Number:
                    DrawString(arg.RowCell.X, arg.RowCell.Y, arg.Value);
                    int num = Convert.ToInt32(arg.Value);
                    if (cbPrompt.Checked)
                    {
                        bool status = _sudokuCenter.IsValidMove(_sudokuCenter.PlayerSuduku, arg.RowCell.X, arg.RowCell.Y, num);
                        lblPrompt.Text = status ? "你真棒!" : "重复了";
                    }
                    else
                    {
                        lblPrompt.Text = "已写入";
                    }
                    _sudokuCenter.PlayerSuduku[arg.RowCell.X, arg.RowCell.Y].Number = num;
                    pbGameBack.Invalidate(new Rectangle(SudokuCenter.CELLSNUMBER2 + arg.RowCell.Y * _sudokuCenter.CellSize, SudokuCenter.CELLSNUMBER2 + arg.RowCell.X * _sudokuCenter.RowSize, SudokuCenter.CELLSNUMBER2 + _sudokuCenter.CellSize, SudokuCenter.CELLSNUMBER2 + _sudokuCenter.RowSize));

                    break;
                case NumberType.Clear:
                    using (var g = Graphics.FromImage(sudukuBitmap))
                    {
                        _sudokuCenter.PlayerSuduku[arg.RowCell.X, arg.RowCell.Y].Number = 0;
                        var rec= _sudokuCenter.DrawTransparent(g, arg.RowCell.X, arg.RowCell.Y);
                        lblPrompt.Text = "已清除";
                        pbGameBack.Invalidate(rec);
                    }
                    break;
            }
        }
        private void DrawString(int row, int col, string num)
        {
            using (var g = Graphics.FromImage(sudukuBitmap))
            {
                using SolidBrush brush = new SolidBrush(_sudokuCenter.SolutionColor);
                _sudokuCenter.DrawTransparent(g, row, col);
                _sudokuCenter.DrawString(g, row, col, num, brush);
            }
        }
        private void DrawString(Graphics g, int row, int col, string num)
        {
            using SolidBrush brush = new SolidBrush(_sudokuCenter.SolutionColor);
            _sudokuCenter.DrawTransparent(g, row, col);
            _sudokuCenter.DrawString(g, row, col, num, brush);
            pbGameBack.Invalidate(new Rectangle(SudokuCenter.CELLSNUMBER2 + col * _sudokuCenter.CellSize, SudokuCenter.CELLSNUMBER2 + row * _sudokuCenter.RowSize, _sudokuCenter.CellSize, _sudokuCenter.RowSize));
        }

        /// <summary>
        /// 提交
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSubmit_Click(object sender, EventArgs e)
        {
            if (!_sudokuCenter.IsStart)
            {
                return;
            }
            if (MessageBox.Show("你正在开始游戏,确认提交答案吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
            {
                return;
            }

            _timer.Stop();

            SudokuSolver sudokuSolver = new SudokuSolver();
            var solveSudoku = sudokuSolver.SolveSudoku(_sudokuCenter.Suduku);
            bool status = _sudokuCenter.IsSolutionCorrect(_sudokuCenter.PlayerSuduku, solveSudoku);
            if (status)
            {
                lblPrompt.Text = "全对了,你真棒!";
                MessageBox.Show("全对了,你真棒!", "恭喜");
            }
            else
            {
                lblPrompt.Text = "很遗憾,有错误!";
                MessageBox.Show("很遗憾,有错误!", "失败");
                for (int row = 0; row < SudokuCenter.CELLSNUMBER; row++)
                {
                    for (int col = 0; col < SudokuCenter.CELLSNUMBER; col++)
                    {
                        if (solveSudoku[row, col].Number != _sudokuCenter.PlayerSuduku[row, col].Number)
                        {
                            this.DrawString(row, col, solveSudoku[row, col].Number.ToString());
                        }
                    }
                }
                pbGameBack.Invalidate();
            }
            _sudokuCenter.IsStart = false;
        }
        /// <summary>
        /// 重新开始
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRestart_Click(object sender, EventArgs e)
        {
            StartGame();
        }

        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            _sudokuCenter.Dispose();
            this.pbGameBack.Image?.Dispose();
            this.pbGameBack.Dispose();

            if (_timer != null)
            {
                _timer.Stop();
                _timer.Dispose();
            }
            this.Dispose();
        }
    }

8.其它

 public class RemarkAttribute : Attribute
    {
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }

        public RemarkAttribute(string remark)
        {
            this.Remark = remark;
        }
    }
    public static class EnumEx
    {
        /// <summary>
        /// 根据枚举元素,获取该枚举元素的描述信息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tField"></param>
        /// <returns></returns>
        public static string GetEnumDesc<T>(this T tField) where T : Enum
        {
            var description = string.Empty; //结果
            var inputType = tField.GetType(); //输入的类型
            var descType = typeof(RemarkAttribute); //目标查找的描述类型

            var fieldStr = tField.ToString();                //输入的字段字符串
            var field = inputType.GetField(fieldStr);        //目标字段

            var isDefined = field?.IsDefined(descType, false);//判断描述是否在字段的特性
            if (isDefined ?? false)
            {
                var enumAttributes = field.GetCustomAttributes(descType, false) as RemarkAttribute[];  //得到特性信息
                description = enumAttributes?.FirstOrDefault()?.Remark ?? string.Empty;
                //  description = string.Join(',', enumAttributes?.Select(t => t.Remark));
            }
            return description;
        }
    }

 

 public class IdValues
    {
        public string Id { get; set; }
        public string Value { get; set; }
        public string Value2 { get; set; }
        public string Value3 { get; set; }
        public string Value4 { get; set; }
        public string Value5 { get; set; }
        public int Standby { get; set; }
        public string Display { get; set; }
        public static bool operator ==(IdValues idValues, IdValues idValues2)
        {
            return idValues.Equals(idValues2);
        }
        public static bool operator !=(IdValues idValues, IdValues idValues2)
        {
            return !idValues.Equals(idValues2);
        }
        public override int GetHashCode()
        {
            var code = (Id, Value, Value2, Value3, Value4, Value5, Standby).GetHashCode();
            return code;
        }
        public override bool Equals(object? obj)
        {
            return obj?.GetHashCode() == GetHashCode();
        }
        const int TARGET = 0x1F;
        /// <summary>
        /// 将连续字段的哈希代码左移两位或更多位来加权各个哈希代码(最佳情况下,超出位 31 的位应环绕,而不是被丢弃)
        /// </summary>
        /// <param name="value"></param>
        /// <param name="positions"></param>
        /// <returns></returns>
        public int ShiftAndWrap(int value, int positions = 3)
        {
            positions &= TARGET;
            uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
            uint wrapped = number >> (32 - positions);
            return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
        }
    }

 

 internal static class SystemEx
    {
        /// <summary>
        /// 跨线程操作控件
        /// </summary>
        /// <param name="con"></param>
        /// <param name="action"></param>
        public static void ExecBeginInvoke(this Control con, Action action)
        {
            if (action == null) return;
            if (con.InvokeRequired)
            {
                con.BeginInvoke(new Action(action));
            }
            else
            {
                action();
            }
        }
        /// <summary>
        /// 跨线程操作控件
        /// </summary>
        /// <param name="con"></param>
        /// <param name="action"></param>
        public static void ExecInvoke(this Control con, Action action)
        {
            if (action == null) return;
            if (con.InvokeRequired)
            {
                con.Invoke(new Action(action));
            }
            else
            {
                action();
            }
        }
    }

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1032688.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM 参数详解

GC有两种类型&#xff1a;Scavenge GC 和Full GC 1、Scavenge GC 一般情况下&#xff0c;当新对象生成&#xff0c;并且在Eden申请空间失败时&#xff0c;就会触发Scavenge GC&#xff0c;堆的Eden区域进行GC&#xff0c;清除非存活对象&#xff0c;并且把尚且存活的对象移动到…

mysql 命令

1.以root身份登录MySQL服务器 mysql -u root -p 2.输入root用户密码 显示命令 1. 显示数据库列表 show databases; 刚开始时才两个数据库&#xff1a;mysql和test。mysql库很重要它里面有MYSQL的系统信息&#xff0c;我们改密码和新增用户&#xff0c;实际上就是用这个库进…

AUTOSAR词典:CAN驱动Mailbox配置技术要点全解析

AUTOSAR词典&#xff1a;CAN驱动Mailbox配置技术要点全解析 前言 首先&#xff0c;请问大家几个小小问题&#xff0c;你清楚&#xff1a; AUTOSAR框架下的CAN驱动关键词定义吗&#xff1f;是不是有些总是傻傻分不清楚呢&#xff1f;CAN驱动Mailbox配置过程中有哪些关键配置参…

操作系统--------调度算法篇

目录 一.先来先服务调度算法&#xff08;FCFS&#xff09; 二.短作业优先调度算法&#xff08;SJF&#xff09; 2.1.SJF调度算法缺点 三.优先级调度算法 3.1优先级调度算法的类型 1.非抢占优先级调度算法 2.抢占优先级调度算法 3.2优先级的类型 3.1静态优先级 3.2动态…

2101. 引爆最多的炸弹;752. 打开转盘锁;1234. 替换子串得到平衡字符串

2101. 引爆最多的炸弹 核心思想&#xff1a;枚举BFS。枚举每个炸弹最多引爆多少个炸弹&#xff0c;对每个炸弹进行dfs&#xff0c;一个炸弹能否引爆另一个炸弹是两个炸弹的圆心距离在第一个炸弹的半径之内。 752. 打开转盘锁 核心思想:典型BFS&#xff0c;就像水源扩散一样&a…

MySQL数据库 -- 入门篇

1. MySQL概述 1.1 数据库相关概念 三个概念&#xff1a;数据库、数据库管理系统、SQL。 目前主流的关系型数据库管理系统的市场占有率排名如下&#xff1a; Oracle&#xff1a;大型的收费数据库&#xff0c;Oracle公司产品&#xff0c;价格昂贵。MySQL&#xff1a;开源免费…

力扣刷题-数组-螺旋矩阵

模拟过程&#xff0c;但却十分考察对代码的掌控能力。 重点&#xff1a;循环不变量原则&#xff01; 第一条原则&#xff1a; 模拟顺时针画矩阵的过程&#xff1a; 填充上行从左到右填充右列从上到下填充下行从右到左填充左列从下到上 由外向内一圈一圈这么画下去。 第二条原…

【探索Linux世界|中秋特辑】--- 倒计时和进度条的实现与演示

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Linux专栏】&#x1f388; 本专栏旨在分享学习Linux的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 演示环境&#xff1…

PageHelp插件在复杂sql下引起的Having无法识别错误及其解决方案

1: 问题出现的场景 系统中有一个复杂SQL内嵌套了多个子查询.在改动时需要将SQL的最后一行加上having来做额外的过滤处理. 添加完having语句后发现SQL能够正常执行就直接将代码提交到了测试环境.结果在测试环境报错Unknown column ‘xxx‘ in ‘having clause. 2: 分析问题 1…

公众号留言功能怎么打开?有什么条件?

为什么公众号没有留言功能&#xff1f;2018年2月12日&#xff0c;TX新规出台&#xff1a;根据相关规定和平台规则要求&#xff0c;我们暂时调整留言功能开放规则&#xff0c;后续新注册帐号无留言功能。这就意味着2018年2月12日号之后注册的公众号不论个人主体还是组织主体&…

十四、MySql的用户管理

文章目录 一、用户管理二、用户&#xff08;一&#xff09;用户信息&#xff08;二&#xff09;创建用户1.语法&#xff1a;2.案例&#xff1a; &#xff08;三&#xff09; 删除用户1.语法&#xff1a;2.示例&#xff1a; &#xff08;四&#xff09;修改用户密码1.语法&#…

ps丢失d3dcompiler_47.dll怎么办,这四个方法都能解决

在当今的信息化社会&#xff0c;电脑已经成为我们生活和工作中不可或缺的一部分。然而&#xff0c;随着软件技术的不断发展&#xff0c;电脑在使用过程中也难免会遇到各种问题。其中&#xff0c;缺失d3dcompiler_47.dll文件是一个常见的问题。本文将为大家介绍如何修复电脑出现…

Python JS逆向之Ku狗,实现搜索下载功能(附源码)

今天用Python来实现一下酷狗JS逆向&#xff0c;实现搜索下载功能 1、环境使用 Python 3.8Pycharm 2、模块使用 import hashlib --> pip install hashlib import prettytable as pt --> pip install prettytable import requests --> pip install requests import…

深度学习从入门到入土

1. 数据操作 N维数组样例 N维数组是机器学习和神经网络的主要数据结构 0-d 一个类别&#xff1a; 1.0 1-d 一个特征向量(一维矩阵)&#xff1a;[1.0, 2.7, 3.4] 2-d 一个样本-特征矩阵-(二维矩阵) 3-d RGB图片 &#xff08;宽x高x通道&#xff09;- 三维数组 4-d 一个RGB…

selenium自动化测试入门,一篇足矣

Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。 Selenium是用于自动化控制浏览器做各种操作&#xff0c;打开网页&#xff0c;点击按钮&#xff0c;输入表单等等&#xff0c;可以模拟各种人工操作浏览器的功…

共享WiFi贴项目怎么实施与运营,微火为你提供高效解答!

共享WiFi贴是一项有前景的商业项目&#xff0c;不仅可以满足用户对网络的需求&#xff0c;还可以为创业者带来盈利的机会。那么&#xff0c;我们来看看如何有效地开展共享WiFi贴项目。 最重要的是选择合适的位置。共享WiFi贴项目的成功与否很大程度上取决于位置选择。优先选择人…

web前端之float布局与flex布局

float布局 <style>.nav {overflow: hidden;background-color: #6adfd0; /* 导航栏背景颜色 */}.nav a {float: left;display: block;text-align: center;padding: 14px 16px;text-decoration: none;color: #000000; /* 导航栏文字颜色 */}.nav a:hover {background-col…

示例-安装office2016图文教程简体中文下载安装包

目录 简介 步骤 总结 简介 Office 2016作为一款办公软件套件&#xff0c;下载和安装 都具有许多令人印象深刻的特点。让我来为你介绍一下&#xff1a;Office 2016注重实现跨平台的一致性。无论你是在Windows、Mac、iOS还是Android上使用Office&#xff0c;你都可以享受到相似…

软件测试之白盒测试

白盒测试 白盒测试&#xff08;White Box Testing&#xff09;又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试只测试软件产品的内部结构和处理过程&#xff0c;而不测试软件产品的功能&#xff0c;用于纠正软件系统在描述、表示和规格上的错误&#xff0c…

「回到县城」正成为大学生就业的无奈选择

现如今&#xff0c;上大学已经不再是当年的天之骄子&#xff0c;现在的大学升学率极高&#xff0c;而毕业就业率却与之相反。 只有少数人能成为优秀的人&#xff0c;而竞争激烈的结果只有更少的人获得胜利。 想象一下&#xff0c;在大城市里打拼&#xff0c;就像千军万马争夺…