您的位置:首页 > 其它

数独游戏求解:解法适用于任意阶数的数独

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#
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: