• c# 陈景润 15 子问题


    初学编程时在 csdn 上写过一个陈景润 15 子问题的项目,https://blog.csdn.net/weixin_41628344/article/details/79171846

    当时的主要精力都放在学习编程上,并未对陈景润的算法进行研究,今天故地重游,重新整理一下。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace FifteenButtons
    {
        class Program
        {
            static void Main(string[] args)
            {
                (new FrmMain()).ShowDialog();
            }
        }
        public class ChessMan : Button
        {
            public int RowIndex { get; set; }
            public int ColumnIndex { get; set; }
            public int Index { get; set; }
        }
    
        class FrmMain : Form
        {
            private List<ChessMan> chessManList;
            private int N = 4;       //边长
            private int X0 = 20;    //横向起始坐标
            private int Y0 = 20;    //竖向起始坐标
            private int Step = 50;   //按钮间距
            private int CmWidth = 45;    //按钮宽度
            private int MoveCount = 200; //移动次数
            private ChessMan hiddenCm;
            public FrmMain()
            {
                Start();
            }
            #region Event
            //开始
            private void Start()
            {
                if (chessManList == null)
                {
                    InitChessMan();
                }
                //MoveCm();
                MoveCm2();
            }
    
            //点击按钮
            private void ChessMan_Click(object sender, EventArgs e)
            {
                ChessMan cm = sender as ChessMan;
                int differ = Math.Abs(cm.Index - hiddenCm.Index);
                if (differ == 1 || differ == N)
                {
                    ExChange(ref hiddenCm, cm);
                }
                if (GameOver())
                {
                    MessageBox.Show("游戏结束");
                    Start();
                }
            }
            #endregion
    
            #region Method
            //初始化所有按钮
            private void InitChessMan()
            {
                chessManList = new List<ChessMan>();
                for (int i = 0; i < N * N; i++)
                {
                    ChessMan cm = new ChessMan();
                    cm.Text = (i + 1).ToString();
                    cm.RowIndex = i / N;
                    cm.ColumnIndex = i % N;
                    cm.Index = i;
                    cm.Width = CmWidth;
                    cm.Height = CmWidth;
                    cm.Top = Y0 + cm.RowIndex * Step;
                    cm.Left = X0 + cm.ColumnIndex * Step;
                    if (i == (N * N - 1))
                    {
                        cm.Visible = false;
                        this.hiddenCm = cm;
                    }
                    else
                    {
                        cm.Visible = true;
                    }
                    chessManList.Add(cm);
                    cm.Click += new EventHandler(ChessMan_Click);
                    this.Controls.Add(cm);
                }
            }
    
            //打乱所有按钮
            private void MoveCm()
            {
                Random rnd = new Random();
                for (int i = 0; i < MoveCount; i++)
                {
                    int direction = rnd.Next(4);
                    switch (direction)
                    {
                        //
                        case 0:
                            {
                                if (this.hiddenCm.RowIndex == 0)
                                {
                                    break;
                                }
                                int index = this.hiddenCm.ColumnIndex + N * (this.hiddenCm.RowIndex - 1);
                                ChessMan cm = chessManList[index];
                                ExChange(ref this.hiddenCm, cm);
                                break;
                            }
                        //
                        case 1:
                            {
                                if (this.hiddenCm.RowIndex == (N - 1))
                                {
                                    break;
                                }
                                int index = this.hiddenCm.ColumnIndex + N * (this.hiddenCm.RowIndex + 1);
                                ChessMan cm = chessManList[index];
                                ExChange(ref this.hiddenCm, cm);
                                break;
                            }
                        //
                        case 2:
                            {
                                if (this.hiddenCm.ColumnIndex == 0)
                                {
                                    break;
                                }
                                int index = this.hiddenCm.ColumnIndex - 1 + N * (this.hiddenCm.RowIndex);
                                ChessMan cm = chessManList[index];
                                ExChange(ref this.hiddenCm, cm);
                                break;
                            }
                        //
                        case 3:
                            {
                                if (this.hiddenCm.ColumnIndex == (N - 1))
                                {
                                    break;
                                }
                                int index = this.hiddenCm.ColumnIndex + 1 + N * (this.hiddenCm.RowIndex);
                                ChessMan cm = chessManList[index];
                                ExChange(ref this.hiddenCm, cm);
                                break;
                            }
                    }
                }
            }
    
            //打乱所有按钮       
            //陈景润方法
            //http://www.doc88.com/p-7092015263762.html
            private void MoveCm2()
            {
                Random rnd = new Random();
                List<int> list = new List<int>();
                for (int i = 0; i < N * N; i++)
                {
                    list.Add(i);
                }
                List<int> list2 = new List<int>();
                while (list.Count > 0)
                {
                    int i = list[rnd.Next(list.Count)];
                    list.Remove(i);
                    list2.Add(i);
                }
    
                //计算倒置数
                int count = 0;
                for (int i = 0; i < list2.Count; i++)
                {
                    if (list2[i] != list2.Count - 1)
                    {
                        for (int j = i + 1; j < list2.Count; j++)
                        {
                            if (list2[i] > list2[j])
                            {
                                count++;
                            }
                        }
                    }
                }
                //空白所在行号
                int rowIndex = 0;
                for (int i = 0; i < list2.Count; i++)
                {
                    if (list2[i] == N * N - 1)
                    {
                        rowIndex = i / N;
                        break;
                    }
                }
                bool list2IsOdd = (count % 2 == 0) ? false : true;
                bool rowIsOdd = (rowIndex % 2 == 0) ? true : false;         //0行为奇数,1行为偶数
                if (N % 2 == 0) //N为偶数:序列为偶置序列,空格必须在偶数行。序列为奇置序列,空格必须在奇数行。
                {
                    if (!list2IsOdd && rowIsOdd) //偶置序列   空格行号为奇数
                    {
                        int temp = list2[list2.Count - 1];       //交换后两个元素,改变奇偶性
                        list2[list2.Count - 1] = list2[list2.Count - 2];
                        list2[list2.Count - 2] = temp;
                    }
                    else if (list2IsOdd && !rowIsOdd)//奇置序列   空格行号为偶数
                    {
                        int temp = list2[0];    //交换前两个元素,改变奇偶性
                        list2[0] = list2[1];
                        list2[1] = temp;
                    }
                }
                else //N为奇数,序列必须为偶置序列
                {
                    if (list2IsOdd)
                    {
                        if (rowIsOdd)
                        {
                            int temp = list2[N];       //交换后两个元素,改变奇偶性
                            list2[N] = list2[N + 1];
                            list2[N + 1] = temp;
                        }
                        else
                        {
                            int temp = list2[0];    //交换前两个元素,改变奇偶性
                            list2[0] = list2[1];
                            list2[1] = temp;
                        }
                    }
                }
    
    
                for (int i = 0; i < chessManList.Count; i++)
                {
                    chessManList[i].Text = (list2[i] + 1).ToString();
                    if (list2[i] == chessManList.Count - 1)
                    {
                        chessManList[i].Visible = false;
                        hiddenCm = chessManList[i];
                    }
                    else
                    {
                        chessManList[i].Visible = true;
                    }
                }
            }
            //交换按钮
            private void ExChange(ref ChessMan hiddenCm, ChessMan cm)
            {
                string str = hiddenCm.Text;
                hiddenCm.Text = cm.Text;
                cm.Text = str;
    
                hiddenCm.Visible = true;
                cm.Visible = false;
                hiddenCm = cm;
                this.hiddenCm = hiddenCm;
            }
    
            //游戏结束
            private bool GameOver()
            {
                for (int i = 0; i < chessManList.Count; i++)
                {
                    if (chessManList[i].Text != (i + 1).ToString())
                    {
                        return false;
                    }
                }
                return true;
            }
            #endregion
        }
    }
  • 相关阅读:
    为IIS站点启用SSL加密
    SQL Server Analysis Service身份验证
    安装规划服务器(PPS 2007)
    用SQL Server Compact Edition创建移动应用程序 【转载】
    在Web Service中使用Windows验证的方式
    巧用Excel去除数据表中的重复行
    如何动态切换报表中的图表类型
    使用链接维度
    如何配置订阅以使用 Web 同步(RMO 编程)【转载】
    如何对数据进行合并及分组
  • 原文地址:https://www.cnblogs.com/aitong/p/10972588.html
Copyright © 2020-2023  润新知