【Silverlight】汉诺塔游戏,带AI

先看效果

 

 

完整代码在此下载/Aimeast/SLAnyHanoi.zip

 

简单的把设计说明一下

ViewModel 和 Model 的设计如下:

【Silverlight】汉诺塔游戏,带AI

 

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

【Silverlight】汉诺塔游戏,带AI

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的设计如下:

【Silverlight】汉诺塔游戏,带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));

            }

        }

 

欢迎大家的评论!

你可能感兴趣的:(silverlight)