数独游戏求解:解法适用于任意阶数的数独
2015-09-25 21:13
477 查看
0.数独简介
数独(すうどく,Sūdoku)是一种运用纸、笔进行演算的逻辑游戏。以九阶数独为例,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。1)4阶(可填数字范围1~4,宫格2阶)
using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; public class SudokuClass { public int Rank { //数独的阶数 get { return GridRank; } set { GridRank = value; SubGridRank = Convert.ToInt32(Math.Sqrt(value)); SubGridIncludeRank = SubGridRank; DataMaxValue = value; DataMinValue = 1; } } public int?[,] GridData { get; set; } //数独的数据 //数独的阶数 private int GridRank; //子数独(宫)的阶数 private int SubGridRank; //数独包含子数独(宫)的阶数 private int SubGridIncludeRank; //数独可填最大数值 private int DataMaxValue; //数独可填最小数值 private int DataMinValue; /// <summary> /// 实例化一个指定阶数的数独类 /// </summary> /// <param name="nRank">指定的阶数</param> public SudokuClass(int nRank) { this.Rank = nRank; } public int?[,] GenerateInitialNumbers() { GridData = new Nullable<int>[GridRank, GridRank]; for (i = 0; i <= GridRank - 1; i++) { for (j = 0; j <= GridRank - 1; j++) { GridData[i, j] = 0; //暂无初始数字生成规则,请从数独文件导入 } } return GridData; //返回一个空白数独 } public bool IsImpossible(int?[,] Numbers) { int? temp = default(int?); for (i = 0; i <= GridRank - 1; i++) { for (j = 0; j <= GridRank - 1; j++) { if (!(Numbers[i, j] == 0)) { temp = Numbers[i, j]; Numbers[i, j] = 0; if (GetExisting(ref Numbers, i, j, Convert.ToInt32(temp))){Numbers[i, j] = temp;return true;} Numbers[i, j] = temp; } } } return false; } public bool IsWin(int?[,] Numbers) { for (i = 0; i <= GridRank - 1; i++) { for (j = 0; j <= GridRank - 1; j++) { if (!Numbers[i, j].HasValue) return false; //出现空格 } } List<int> TempInt = new List<int>(); //判断行重复 for (i = 0; i <= GridRank - 1; i++) { TempInt.Clear(); for (j = 0; j <= GridRank - 1; j++) { TempInt.Add(Convert.ToInt32(Numbers[i, j])); } if (IsDuplicate(TempInt.ToArray())) return false; } //判断列重复 for (j = 0; j <= GridRank - 1; j++) { TempInt.Clear(); for (i = 0; i <= GridRank - 1; i++) { TempInt.Add(Convert.ToInt32(Numbers[i, j])); } if (IsDuplicate(TempInt.ToArray())) return false; } //判断宫格重复 for (i = 0; i <= GridRank - 1; i += SubGridRank) { for (j = 0; j <= GridRank - 1; j += SubGridRank) { TempInt.Clear(); for (i2 = 0; i2 <= SubGridRank - 1; i2++) { for (j2 = 0; j2 <= SubGridRank - 1; j2++) { TempInt.Add(Convert.ToInt32(Numbers[i + i2, j + j2])); } } if (IsDuplicate(TempInt.ToArray())) return false; } } return true; } /// <summary> /// 判断一个序列是否有重复数字 /// </summary> /// <param name="Numbers"></param> /// <returns></returns> private bool IsDuplicate(int[] Numbers) { Array.Sort(Numbers); if (Numbers.Length > 1) { for (i = 0; i <= Numbers.Length - 2; i++) { if (Numbers[i] == Numbers[i + 1]) return true; } } return false; } /// <summary> /// 返回指定位置的所有可填数字的序列 /// </summary> /// <param name="Numbers">原数组</param> /// <param name="gX">指定的位置的X值,从0开始</param> /// <param name="gY">指定的位置的Y值,从0开始</param> /// <returns></returns> public int[] GetEnabledNum(int?[,] Numbers, int gX, int gY) { List<int> NumList = new List<int>(); for (i = DataMinValue; i <= DataMaxValue; i++) { if (GetExisting(ref Numbers, gX, gY, i) == false) NumList.Add(i); } return NumList.ToArray(); } //递归求解数独 private List<int?[,]> GetValue(int?[,] gData) { List<int?[,]> ResultList = new List<int?[,]>(); int i = 0; int j = 0; Point tempPoint = getStartPoint(ref gData); i = tempPoint.X; j = tempPoint.Y; if (i >= 0 && j >= 0) { for (value = DataMinValue; value <= DataMaxValue; value++) { if (GetExisting(ref gData, i, j, value) == false) { gData[i, j] = value; GetValue(gData); gData[i, j] = 0; } } } else { //新增一个结果 ResultList.Add(gData); } return ResultList; } //查找当前空白格(最佳格) private Point getStartPoint(ref int?[,] data) { Point gPoint = default(Point); int tempValue = 0; int maxValue = 0; //查找限制最多的空白格 for (i = 0; i <= GridRank - 1; i++) { for (j = 0; j <= GridRank - 1; j++) { if (data[i, j] == 0) { tempValue = 0; for (k = 0; k <= GridRank - 1; k++) { if (data[i, k] > 0) tempValue += 1; if (data[k, j] > 0) tempValue += 1; if (data[(i / SubGridIncludeRank) * SubGridIncludeRank + k / SubGridIncludeRank, (j / SubGridIncludeRank) * SubGridIncludeRank + (k % SubGridIncludeRank)] > 0) tempValue += 1; } if (tempValue > maxValue) { maxValue = tempValue; gPoint.X = i; gPoint.Y = j; } } } } if (maxValue > 0) { return gPoint; } else { gPoint.X = -1; gPoint.Y = -1; return gPoint; } } //判断同行同列同宫是否已经存在 private bool GetExisting(ref int?[,] data, int gX, int gY, int gValue) { for (k = 0; k <= GridRank - 1; k++) { if (data[gX, k] == gValue || data[k, gY] == gValue || data[(gX / SubGridIncludeRank) * SubGridIncludeRank + k / SubGridIncludeRank, (gY / SubGridIncludeRank) * SubGridIncludeRank + (k % SubGridIncludeRank)] == gValue) { return true; } } return false; } }
C#
相关文章推荐
- Python命令 (if __name__=="__main__":)
- 并发2
- 2013金山西山居创意游戏程序挑战赛---链接
- 解决idea中执行maven命令失败的问题
- 和为0的最长子序列
- 【mongoDB基础篇①】安装与常用操作语句
- Install jdk8 on Ubuntu 14.04
- 数据库存储手机emoji表情
- varnish 4.0强制gzip压缩
- mongodb db.serverStatus()解析 详解
- 字符串(1)题集
- Intellij14解决C:\Users\Administrator\.IntelliJIdea14存放路径
- 指针常量与常指针
- 上传图片至多服务器,图片共享问题
- [LeetCode]H-Index II
- java+jsp实现分页查询
- CSS框架960Grid从入门到精通一步登天
- 黑盒测试、灰盒测试、白盒测试
- 联赛联考3
- Servlet 上传文件