前一段時間迷上數獨,於是自己做了一個,仿MetroUI,看着蠻簡單。如下:
支持自定義背景,快捷鍵等!
由於自知算法不是很好,所以在做這個的時候,使用了一些小技術!
大概說一下,具體的結構!
有四個小項目,從上到下,分別是:
Sudoku.CodeMonk(我自己實現的一個數獨)
Sudoku.Common(數獨接口和其他的公用類)
Sudoku.Test(測試項目)
Sudoku.WinForm(WinForm版的數獨)
當然最關鍵的肯定是那個ISudoku接口,它定義了一系列的數獨操作,比如生成數獨,打開和保存數獨,撤銷重復等!具體如下:

using System;
using System.Collections.Generic;
namespace Sudoku.Common
{
public delegate void FinishHandler();
/// <summary>
/// 數獨接口
/// </summary>
public interface ISudoku:IDisposable
{
event FinishHandler OnInitializeFinish;
event FinishHandler OnLoadFinish;
/// <summary>
/// 設置點
/// </summary>
/// <param name="x">x坐標</param>
/// <param name="y">y坐標</param>
/// <returns>點</returns>
byte this[byte x, byte y] { get; set; }
/// <summary>
/// 載入數獨
/// </summary>
/// <param name="path">路徑</param>
void Load(string path);
/// <summary>
/// 保存數獨
/// </summary>
/// <param name="path">路徑</param>
void Save(string path);
/// <summary>
/// 撤銷
/// </summary>
void Undo();
/// <summary>
/// 重復
/// </summary>
void Redo();
/// <summary>
/// 重置
/// </summary>
void Reset();
/// <summary>
/// 初始化數獨
/// </summary>
void Initialize();
/// <summary>
/// 獲取數獨數據
/// </summary>
/// <returns></returns>
byte[,] Current { get; }
/// <summary>
/// 原數組
/// </summary>
byte[,] Original { get; }
/// <summary>
/// 等級
/// </summary>
byte Level { get; set; }
/// <summary>
/// 是否完成
/// </summary>
bool IsFinish { get; }
/// <summary>
/// 設置或獲取數獨的解決方法
/// </summary>
ISudokuSolution Solution { get; set; }
/// <summary>
/// 使用內置的解決方法解決當前數獨
/// </summary>
void Solve();
/// <summary>
/// 檢測該位置的點是否能放置
/// </summary>
/// <param name="row">行坐標</param>
/// <param name="col">列坐標</param>
/// <param name="value">值</param>
/// <returns>如果能放置則返回true</returns>
bool CanSet(byte row, byte col, byte value);
/// <summary>
/// 獲取該位置放置的值集合
/// </summary>
/// <param name="row">行坐標</param>
/// <param name="col">列坐標</param>
/// <returns>放置值的集合</returns>
List<byte> CanSetValues(byte row, byte col);
}
}
里面的ISudokuSolution定義了一些解數獨的方法:

using System.Collections.Generic;
namespace Sudoku.Common
{
/// <summary>
/// 數獨解決方法實例
/// </summary>
public interface ISudokuSolution
{
/// <summary>
/// 設置或獲取要解決的數獨
/// </summary>
ISudoku Sudoku { get; set; }
/// <summary>
/// 解決數獨
/// </summary>
/// <returns>解決完成的數獨</returns>
ISudoku Solve();
/// <summary>
/// 檢測該位置的點是否能放置
/// </summary>
/// <param name="row">行坐標</param>
/// <param name="col">列坐標</param>
/// <param name="value">值</param>
/// <returns>如果能放置則返回true</returns>
bool CanSet(byte row, byte col,byte value);
/// <summary>
/// 獲取該位置放置的值集合
/// </summary>
/// <param name="row">行坐標</param>
/// <param name="col">列坐標</param>
/// <returns>放置值的集合</returns>
List<byte> CanSetValues(byte row, byte col);
}
}
為了簡單起見,還有一些公用的函數或利用配置文件生成數獨或數獨解決方案的實例!
Sudoku.CodeMonk代碼的實現邏輯比較清晰,用的挖洞法來生成數獨的!沒有寫什么具體的數獨解決方法。撤銷和重復使用Stack做的,沒有什么Command模式,覺得比較麻煩。保存和讀取是拿xml序列化和反序列化做的。其他的都是窮舉等笨方法!
比較復雜的一部分就只能算是WinForm項目里的GDI+操作,自定義控件等。
為了讓窗體看起來更Metro一些,我找了些微軟官方的WP開發圖標。並自定義了一個PicButton,有點小動畫的效果(小動畫哈)。
復雜一點就是自定義的SudokuLabel,具體的話看代碼吧!
Release包下載:sudoku-release.zip
源碼下載:http://files.cnblogs.com/wushilonng/Sudoku.zip
Codeplex地址:http://longsudoku.codeplex.com/
其他:
(1)自定義背景,刪除掉目錄下的background.jpg就會回到默認背景,放一個background.jpg到目錄下就是背景了!
(2)Ctrl+Z撤銷,Ctrl+Y重復,Ctrl+O打開,Ctrl+S保存,Ctrl+N新建,Ctrl+H輔助解答,Ctrl+R重置!
(3)右側的幾個數是用來說明當前格子里可以的填寫的哪些數。
(4)所謂的小動畫就是圖標稍稍轉一下!
(5)默認難度是1級(比較弱智),還沒做難度調節,需要改代碼(囧)。