博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Silverlight】汉诺塔游戏,带AI
阅读量:5044 次
发布时间:2019-06-12

本文共 4341 字,大约阅读时间需要 14 分钟。

先看效果

 

 

完整代码在此下载

 

简单的把设计说明一下

ViewModel 和 Model 的设计如下:

 

用到了其中的动画效果用的是自己实现的行为(Behavior)。

using System;using System.Windows;using System.Windows.Interactivity;using System.Windows.Media.Animation;namespace AnyHanoi{    public class DiscFluidMoveBehavior : Behavior
{ 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的设计如下:

 

方法是递归求解。

基本思想和标准状态的思想是一样的。把最大的盘子移动到某个目标柱子,需要找到一个暂存柱子。然后按照这一思想进行递归求解。直到剩下最后一个盘子,就可以直接移动。

 

递归求解的核心代码如下

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));            }        }

 

欢迎大家的评论!

转载于:https://www.cnblogs.com/Aimeast/archive/2011/04/02/2003917.html

你可能感兴趣的文章