码迷,mamicode.com
首页 > Web开发 > 详细

数独解算器(ASP.NET 2.0)

时间:2015-08-04 08:13:40      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:

数独游戏 在9x9的方格内进行, 分为3x3的小方格,被称为“区”。
数独游戏首先从已经填入数字的格子开始。
数独游戏的目的是根据下列规则,用1至9之间的数字填满空格:
每个数字在每一行、每一列和每一区只能出现一次。
我在 Linux 服务器(请参见“在 Linux 下运行 ASP.NET 2.0”)上用 ASP.NET 2.0 实现了一个数独解算器
http://www.sudoku.name 网站上也有一个用户界面相当不错的“数独解算器” ,但是其算法太差了,运算速度比我的算法慢多了。以其网站上的“#5328”谜题(也是我的数独解算器的例题)为例,它需要大约四个小时才能给出答案,而我的解算器不到一秒钟就可以给出答案。从它的运算过程来算,估计是逐个空格进行解算。而我的算法是先找出能填入数字个数最少的空格进行解算。算法这个微小的改进,就极大地提高了计算效率。好了,废话少说,下面就是源程序:

1. sudoku.aspx:
 1技术分享<%@ Page Language="C#" inherits="Skyiv.Ben.Web.SudokuPage" %>
 2技术分享<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
 3技术分享<html xmlns="http://www.w3.org/1999/xhtml" >
 4技术分享<head runat="server">
 5技术分享  <title>银河 - 数独</title>
 6技术分享</head>
 7技术分享<body>
 8技术分享  <form id="form1" runat="server">
 9技术分享  <asp:Button Text="返回" OnClick="BtnUriHome_Click" runat="server" />
10技术分享  <asp:Button Text="开始" OnClick="BtnSubmit_Click" runat="server" />
11技术分享  <hr />
12技术分享  <div>
13技术分享  <href="http://www.sudoku.name/index-cn.php" target="_blank">数独游戏</a>
14技术分享  在9x9的方格内进行, 分为3x3的小方格,被称为“区”。<br />
15技术分享  数独游戏首先从已经填入数字的格子开始。<br />
16技术分享  数独游戏的目的是根据下列规则,用1至9之间的数字填满空格:<br />
17技术分享  每个数字在每一行、每一列和每一区只能出现一次。<br />
18技术分享  </div>
19技术分享  <div>
20技术分享  <asp:TextBox Runat="Server" Id="tbxInput" MaxLength="512" Wrap="False"
21技术分享    TextMode="MultiLine" Columns="15" Rows="14" />
22技术分享  <asp:TextBox Runat="Server" Id="tbxOutput" ReadOnly="True" Wrap="False"
23技术分享    TextMode="MultiLine" Columns="15" Rows="14" />
24技术分享  </div>
25技术分享  </form>
26技术分享</body>
27技术分享</html>
28技术分享

2. sudoku.aspx.cs:
 1技术分享using System;
 2技术分享using System.IO;
 3技术分享using System.Web.UI;
 4技术分享using System.Web.UI.WebControls;
 5技术分享using Skyiv.Ben.Etc;
 6技术分享
 7技术分享namespace Skyiv.Ben.Web
 8技术分享{
 9技术分享  public class SudokuPage : Page
10技术分享  {
11技术分享    protected TextBox tbxInput;
12技术分享    protected TextBox tbxOutput;
13技术分享
14技术分享    public void Page_Load(object sender, EventArgs e)
15技术分享    {
16技术分享      if (IsPostBack) return;
17技术分享      tbxInput.Text =    "+---+---+---+\n|2..|技术分享|技术分享|\n|8..|1..|.2.|\n"
18技术分享        + "|..5|.7.|.3.|\n+---+---+---+\n|.7.|.3.|1..|\n|.9.|.4.|.8.|\n"
19技术分享        + "|..4|技术分享|.7.|\n+---+---+---+\n|.3.|.9.|6..|\n|.8.|..5|..3|\n"
20技术分享        + "|技术分享|技术分享|..5|\n+---+---+---+";
21技术分享    }

22技术分享
23技术分享    public void BtnUriHome_Click(object sender, EventArgs e)
24技术分享    {
25技术分享      Response.Redirect(Pub.UriHome);
26技术分享    }

27技术分享
28技术分享    public void BtnSubmit_Click(object sender, EventArgs e)
29技术分享    {
30技术分享      try
31技术分享      {
32技术分享        Sudoku sudoku = new Sudoku(new StringReader(tbxInput.Text));
33技术分享        StringWriter writer = new StringWriter();
34技术分享        sudoku.Out(writer);
35技术分享        tbxOutput.Text = writer.ToString();
36技术分享      }

37技术分享      catch (Exception ex)
38技术分享      {
39技术分享        tbxOutput.Text = "Error: " + ex.Message;
40技术分享      }

41技术分享    }

42技术分享  }

43技术分享}

44技术分享

3. sudoku.cs:
  1技术分享using System;
  2技术分享using System.IO;
  3技术分享using System.Collections.Generic;
  4技术分享
  5技术分享namespace Skyiv.Ben.Etc
  6技术分享{
  7技术分享  sealed class Sudoku
  8技术分享  {
  9技术分享    byte[,] input, output;
 10技术分享    int steps = 0;
 11技术分享
 12技术分享    public Sudoku(TextReader reader)
 13技术分享    {
 14技术分享      input = new byte[99];
 15技术分享      for (int y = 0; y < 9; )
 16技术分享      {
 17技术分享        string s = reader.ReadLine();
 18技术分享        if (s == nullbreak;
 19技术分享        s = s.Replace(.0);
 20技术分享        int x = 0;
 21技术分享        for (int i = 0; i < s.Length; i++)
 22技术分享          if (Char.IsDigit(s, i) && x < 9) input[x++, y] = (byte)(s[i] - 0);
 23技术分享        if (x != 0) y++;
 24技术分享      }

 25技术分享    }

 26技术分享
 27技术分享    public void Out(TextWriter writer)
 28技术分享    {
 29技术分享      Compute(input);
 30技术分享      Out(writer, output);
 31技术分享    }

 32技术分享
 33技术分享    void Out(TextWriter writer, byte[,] output)
 34技术分享    {
 35技术分享      for (int y = 0; y <= output.GetLength(1); y++)
 36技术分享      {
 37技术分享        if (y % 3 == 0) writer.WriteLine("+---+---+---+");
 38技术分享        if (y >= output.GetLength(1)) break;
 39技术分享        for (int x = 0; x <= output.GetLength(0); x++)
 40技术分享        {
 41技术分享          if (x % 3 == 0) writer.Write(|);
 42技术分享          if (x >= output.GetLength(0)) break;
 43技术分享          writer.Write((output[x, y] == 0? . : (char)(output[x, y] + 0));
 44技术分享        }

 45技术分享        writer.WriteLine();
 46技术分享      }

 47技术分享    }

 48技术分享
 49技术分享    bool Compute(byte[,] input)
 50技术分享    {
 51技术分享      List<byte[,]> list = StepIt(input);
 52技术分享      if (list == nullreturn true;
 53技术分享      foreach (byte[,] temp in list) if (Compute(temp)) return true;
 54技术分享      return false;
 55技术分享    }

 56技术分享
 57技术分享    // return null for finish
 58技术分享    List<byte[,]> StepIt(byte[,] input)
 59技术分享    {
 60技术分享      if (steps++ > 100000throw new Exception("太复杂了");
 61技术分享      output = input;
 62技术分享      int theX = -1, theY = -1;
 63技术分享      byte[] theDigits = null;
 64技术分享      for (int y = 0; y < input.GetLength(1); y++)
 65技术分享      {
 66技术分享        for (int x = 0; x < input.GetLength(0); x++)
 67技术分享        {
 68技术分享          if (input[x, y] != 0continue;
 69技术分享          byte[] digits = GetDigits(input, x, y);
 70技术分享          if (digits.Length == 0return new List<byte[,]>();
 71技术分享          if (theDigits != null && theDigits.Length <= digits.Length) continue;
 72技术分享          theX = x;
 73技术分享          theY = y;
 74技术分享          theDigits = digits;
 75技术分享        }

 76技术分享      }

 77技术分享      if (theDigits == nullreturn null;
 78技术分享      List<byte[,]> result = new List<byte[,]>();
 79技术分享      foreach (byte digit in theDigits)
 80技术分享      {
 81技术分享        byte[,] temp = (byte[,])input.Clone();
 82技术分享        temp[theX, theY] = digit;
 83技术分享        result.Add(temp);
 84技术分享      }

 85技术分享      return result;
 86技术分享    }

 87技术分享
 88技术分享    byte[] GetDigits(byte[,] input, int x, int y)
 89技术分享    {
 90技术分享      bool[] mask = new bool[10];
 91技术分享      for (int i = 0; i < 9; i++)
 92技术分享      {
 93技术分享        mask[input[x, i]] = true;
 94技术分享        mask[input[i, y]] = true;
 95技术分享      }

 96技术分享      for (int i = x / 3 * 3; i < x / 3 * 3 + 3; i++)
 97技术分享        for (int j = y / 3 * 3; j < y / 3 * 3 + 3; j++)
 98技术分享          mask[input[i, j]] = true;
 99技术分享      List<byte> list = new List<byte>();
100技术分享      for (int i = 1; i < mask.Length; i++if (!mask[i]) list.Add((byte)i);
101技术分享      return list.ToArray();
102技术分享    }

103技术分享  }

104技术分享}

105技术分享

以上代码都很简单,也不需要再另外解说了。

版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。

数独解算器(ASP.NET 2.0)

标签:

原文地址:http://blog.csdn.net/u013948190/article/details/47271015

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!