【Silverlight】汉诺塔游戏,带AI
先看效果
完整代码在此下载/Aimeast/SLAnyHanoi.zip
简单的把设计说明一下
ViewModel 和 Model 的设计如下:
用到了其中的动画效果用的是自己实现的行为(Behavior)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | using System; using System.Windows; using System.Windows.Interactivity; using System.Windows.Media.Animation; namespace AnyHanoi { public class DiscFluidMoveBehavior : Behavior<FrameworkElement> { public Point Translate { get { return (Point)GetValue(TranslateProperty); } set { SetValue(TranslateProperty, value); } } // Using a DependencyProperty as the backing store for Translate. This enables animation, styling, binding, etc... public static readonly DependencyProperty TranslateProperty = DependencyProperty.Register( "Translate" , typeof (Point), typeof (DiscFluidMoveBehavior), new PropertyMetadata(Translate_PropertyChangedCallback)); private static void Translate_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { Point p = (Point)e.NewValue; DiscFluidMoveBehavior b = (DiscFluidMoveBehavior)d; try { b.Update(p); } catch { } } private void Update(Point p) { Storyboard storyboard = new Storyboard(); DoubleAnimation x = new DoubleAnimation(); DoubleAnimation y = new DoubleAnimation(); x.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath( "(UIElement.RenderTransform).(CompositeTransform.TranslateX)" )); y.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath( "(UIElement.RenderTransform).(CompositeTransform.TranslateY)" )); x.Duration = this .Duration; y.Duration = this .Duration; x.To = p.X; y.To = p.Y; Storyboard.SetTarget(x, base .AssociatedObject); Storyboard.SetTarget(y, base .AssociatedObject); storyboard.Children.Add(x); storyboard.Children.Add(y); storyboard.Begin(); } public Duration Duration { get { return (Duration)GetValue(DurationProperty); } set { SetValue(DurationProperty, value); } } // Using a DependencyProperty as the backing store for Duration. This enables animation, styling, binding, etc... public static readonly DependencyProperty DurationProperty = DependencyProperty.Register( "Duration" , typeof (Duration), typeof (DiscFluidMoveBehavior), new PropertyMetadata( new Duration(TimeSpan.FromSeconds(0.1)))); } } |
需要事先引用 Expression 的 System.Windows.Interactivity 程序集。
把这个行为应用到每个Items。
AI的设计如下:
方法是递归求解。
基本思想和标准状态的思想是一样的。把最大的盘子移动到某个目标柱子,需要找到一个暂存柱子。然后按照这一思想进行递归求解。直到剩下最后一个盘子,就可以直接移动。
递归求解的核心代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | private void RecSolve(Puzzle puzzle) { int max = 0; Peg maxPeg = null ; //找出当前状态下最大盘子所在的柱子 foreach (Peg peg in puzzle.PegCollection) { if (peg.Count > 0 && max < peg.Buttom) { max = peg.Buttom; maxPeg = peg; } } //当前状态只有一个盘子,直接移动 if (puzzle.PegA.Count + puzzle.PegB.Count + puzzle.PegC.Count == 1) { if (maxPeg.PegID != puzzle.DestPeg) Move(maxPeg, puzzle.GetPeg(puzzle.DestPeg)); return ; } //当前状态有多个盘子 if (maxPeg.PegID == puzzle.DestPeg) //最大的盘子就在目标柱子上,不需要移动 { RecSolve(puzzle.NewLevelPuzzle(maxPeg.PegID, puzzle.DestPeg)); } else //最大的盘子不在目标柱子上,需要移动 { //找出临时柱子,即 不是 目标柱子 也不是 最大盘子所在的柱子 Pegs tempPagID = Pegs.A; if (tempPagID == maxPeg.PegID || tempPagID == puzzle.DestPeg) tempPagID = Pegs.B; if (tempPagID == maxPeg.PegID || tempPagID == puzzle.DestPeg) tempPagID = Pegs.C; //把当前状态 去掉最大盘子以后的新状态 继续递归处理 //这一步把所有盘子都移动到临时柱子上 RecSolve(puzzle.NewLevelPuzzle(maxPeg.PegID, tempPagID)); //把当前最大盘子移动到目标柱子上 Move(maxPeg, puzzle.GetPeg(puzzle.DestPeg)); //把上一步处理好的状态 去掉最大的盘子以后的状态 //即 所有盘子都在临时柱子 的 状态移动到目标状态 RecSolve(puzzle.NewLevelPuzzle(puzzle.DestPeg, puzzle.DestPeg)); } } |
欢迎大家的评论!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异