娱人生Silverlight(6) – 贪吃蛇[Silverlight 3.0(c#)]

[索引页]
[源码下载]

铆劲姑娘

娱乐人生Silverlight(6) – 贪吃蛇[Silverlight 3.0(c#)]

一样、迈出第一步,其实很粗略

这天下班,照例刷门禁卡进家,楼下就混熟了之保安欲言又止,最终要不禁发问了出来:“你每一日就是一个人数迈入出入出,自己跟和气以说些什么吧?”我醒来,接着情不自禁地笑笑有声来,原来自己天天一边走,一边一个丁自言自语地说英语,已经深受人家用特别意外的视力来拘禁自己了。

那段日子,除了要旨的翻训练,我哉开学习口语,制止自己还陷落哑巴乌Crane语的困境。总不可知每一回用为此讲话加泰罗尼亚语的上,我都只可以难堪地说:“我会写,但我弗碰面说?我们所以画互换可以为?”想想都认为糟糕意思。

而是,比由打开总括机直接以起材料与词典进行翻译,对于我这样一个从同开头就屡见不鲜了“静默式”学习菲律宾语的口来说,开口言语日语在心情及是一个壮烈的挑衅。

是!我对口语有特别严重的心思恐惧与阻力,能因此写自己相对不会合用“说”!这不过大凡针对即刻同高达吃的这么些调侃的极端消极的影响,尽管这一个奚弄有所谓“恶意”,也起所谓的“善意”。而自我,接纳了那种沉默而绝无用的方来维护自己。

庆幸的凡,在展开着英相译的长河中,我能感受及祥和之进步。这种发展让自家的踏实感激发了自身寻求改变之引力。我非情愿继承举办一个“不能言语言语”的人口。我还记第一不良讲话复述一首作品时,我把团结一个总人口关在房里,但却觉得像是当给千万私房开展同样摆没有出过任何准备的讲演,充满了压力感和沉重负担。我倒反复复阅读这篇小说,可能那多少个句子已经映入了自之脑际,可自己要么花费了长久时间才以下了录音键,用结结巴巴之语调录下了自身自己磨练口语的首先句话。播放的时刻,我闻了一个抖的响声。啊!我之响声依旧是如此?好喜感!不行,重来!这样我之不安甚至给自己放在还不禁笑的动静让驱散了。

原本,做小事情太特别之拦路特斯就是迈出第一步。因为我们天性惧怕改变,而首先步会揭开我们具有的害怕和怕的面罩,让咱解,原来下周害怕与恐怖而这样概括。迈出第一步,转头就会合发现自己已身处其余一番天地。

footstep

新兴一发不可收拾,下载了一部分发声视频后就练发音,我还自己打了一个小镜子查看自己的口型对怪,也于拍了许多神夸张的磨炼习照,录下的音标磨练音频更是妙趣横生有趣。这个还成为了苦学路上的自娱自乐。

作者:webabcd

其次、做一个晨型的总人口

荷兰语听、读与描写都是一个不息不断地欲独处的历程。不过“说”相对很。说话是一个互相的长河。经过一段时间的“自言自语式”训练,我精晓一个人数前仆后继像锻练翻译这样坏歌“独角戏”,我的口语学习决定会折戟沉沙,最后狗带。

自我初始把对象瞄向了线下之各类培训机构。通晓一番,决定吐弃。在自家所当的城,我并从未遇上令自己满足的作育机构。大致原因如下:

首先,距离最远,上课时没有保险。开课时间都是自夜间7点钟初阶。而自我六点钟下班,只要稍加一堵车,或者小延迟下班,这立节课就夺了。

亚,课程安排僵化。上课时间在多数上是因老师的大运来布局的。而且只要通上课,不可撤除。而旅长便也颇少选在星期开课。

老三,学习内容未极端相符职场人员。大多数念内容依旧按照各个培训证书设置,侧重于笔试内容,更合乎给学生。

遂,兜兜转转,我拿目的瞄向在线培训。在线培训恰恰弥补了线下之先天不足,可以在家学习,只要保证网速流畅就足以。其次,学习者可以好挑选任课时间。假设发生突发事件,提前4-6只钟头都得以收回课程。最终,学习内容也很灵的,可以遵照自己的院所兴趣与对象选拔上之情节版块。

而,我不“董卿”可以来当托。我这么些年在线上铸就为花了众钱,这是自己之真实性感受。线上树的优势而比线下造使多,可是焦点问题在于讲师力量的参差和非稳定。我以反复寒不同的养机构中境遇了这些好之民办讲师,也碰着过给人直接抓起电话投诉之渣人物。这虽是考验大家挑选老师的见解。这么些线上铸就机构的老师多仍旧全职人士,可能麻烦长久与一个稳住的老师上课。由于大使用预约制上课,很多学生当抢占优质老师的开课时间段,激烈程度可以可以比春运抢票。

可,线达铸就要被了自非凡老的声援。经过将课预约到上午,我大多可以做到永不动摇的早于。想想一节课来了那么基本上之费,而提早预定好的课在上午清醒的上曾了了好撤废操作的辰限定了。不上,就意味着我拿人民币白白地丢给了店。这样固然足以强制自己早于学,不用带在“埋怨自己从不就”的心情郁闷一上。从深夜启幕,我虽满载鸡血复活,应针对同一上之办事同习。

morning

更为紧要的打算是,这到底清除了自我称言语法语的担心。这多少个导师态度便很是好,讲得了之后就会合顿时告诉你发出哪些地点讲错了,有哪些地方的表明情势错误,课后好团结开展重复磨炼。而且我意识和洋人的互换并无是那么难,也许我们的语法表达并无是那么的高精度,用词连无是那么可以,可是对于一个芬兰语不是母语的人吧,这样的公布水平是可以解的,并无耽搁外国人通晓我们表达的意思。倘诺同起先之时段就是觉得好说话爱沙尼亚语的水准极没有了,倒霉意思开口,就永远体会不至提升,得不顶我们想倘若的进阶水平。

我此前以的艺术是使跟读软件拓展跟读和复述。这种模式也蛮锻练人,尤其是在进展作品复述的上,锻练的凡利用英文进行较长时间表明的力量,一首著作的复述一般会跨同样分钟。而当课堂上以及老师举办谈话,更如是一般的互换,知道在平日状态下好用马耳他语进行表述的本来反应能力,在是历程被,老师吗会晤指出有您没有察觉的小题目。更为首要的是,举办自我复述可以察觉部分问题,带在这一个题材活动至课堂奔法语老师举行求解,会多和谐修之效能,老师也会以课堂举办解答,提升教学的性价比。

在与这一个外教执教的进程中,我啊触发了广大上口语的点子。比如,有一个外教老师以同我合计之后,大家不再以培训机构提供的课本。每一遍上课总是让我训练各类海外的缠绕口令,这给自身以为眼前一亮。这种演习的道有趣又特别,但对习发音更加实用。

口语不同让翻译,总是要谋一下以外的资源,而且汲取了习着译英时候的训诫,我舍得在口语上进展自我投资。我从落业内的见及点着确实收益匪浅。不过在线爱尔兰语培训机构吗来一对题目,除了前边说到之教职工力量良莠不齐和免平稳,还在于这些行业自身的鱼龙混杂。因而,我们以增选在线培训机构的当儿,一定假诺优先精晓了然这家单位的读本研发力量、履约能力、服务态度、售后服务响应能力与退款事宜。现在大部分底在线培训机构还爆发分外的试听服务,学员可基本上放几小开展打探。顶使慎重考虑的一些是,确定好是休是真的愿意交一笔画钱举办上,虽然多数机关还爆发所谓的“犹豫期”,在几上内学员不合意可以展开退费,但差不多没有耳闻哪家培训机构爽快地举办退款。一定会设法的拖延了是犹豫期,使得学生无法用要求退款。要明,掏出来的钱,就未是和谐之钱了。

末,关于作育,还有一两独小秘诀。市面上之作育助教有菲律宾外教与欧美外教的分,菲律宾外教便宜,欧美外教费用高昂,假设心有余力,最好接纳欧美外教。欧美外教负总责之发出,不过态度随便的也罢不丢掉,遇到态度随便的只要学会投诉,并争取重临课时。在授课过程被,有些上居然感受得到欧美外教对华夏丁的敌意。这一个时段得到在一个姿态,你才是出钱的食指,投诉到底。末,假诺当无异针对性平极致昂贵,可以挑选一对N的讲解情势。不过一旦将教学时预定及早7点左右。我用此微智,把一对N改为了一对2,甚至是出色,得到了重新多的对话时。

介绍
使用 Silverlight 3.0(c#) 开发一个贪吃蛇游戏

其三、我的阿拉伯语口语表明方法总结

当学习口语往日,我之辰安排是上午7点交8触及,用来坐单词和语句,并拓展跟读复述。清晨八点至十一点进展中花互译,并举办速记。最先念口语之后,我之工夫部署就改成上午6点半至8触及,扩张了大体上个钟头。一节省课的光阴一般是半只钟头要45分钟,这样的年中兴丰富了。

经过在四下之造机构上(前后持续一年多),我的芬兰语终于离了哑巴级别,进入了足出口的级别,非凡满面红光,还有外教说我之语调比一般的中原生好听。嘚瑟了长时间。期间,也总括出了有的好之心端庄会。

先是,是在勉强态度的主动上。我出同样不好上课的早晚,感觉这位外教当怪消沉。暖场过后,因为凡同等节约free
talk。她才告知以前四节课往学生问:“这无异于天了得咋样?”学生还在诉苦,她看十分惊讶,为啥那么些学员都这么消极?这个时刻,我才幡然醒悟,保加利亚语口语在互换过程被也唯有是均等派系语言,表明的内容并非过度被动,而是一旦具有爱。后来,在雅思口语备考中,也感受及当下或多或少。一定假如吃的聆听者一种植积极的发,尽管你的活着或的确正处在困难无比之阶段

次,不要说得过于复杂。嗤笑一下,英语是木头的言语,即使大家还有很四人学不佳。咱们不少上便拿要描述的事物想得过分复杂。比如雅思口语考题中来同等道问题:“Describe
a time you decided to wait for
something。”我看到第一独反应是等待,人生之等?这自己之所以中文可以写上十篇,可是就此英英文怎么讲?后来题材读懂了,才意识而大凡言语航班延误、交通堵塞、朋友约晤面迟那个普通琐事。还有一个地方类题材叫做进和的地A
Place Near
沃特er。许多丁虽然想只要湖泊、大海等等,其实我们全也可以说话在湖边的房舍,湖边的一律座花园,甚至是湖水被的一个小岛。

其三,要学会词义替换。同一首西班牙语小说中,甚至是一个名词的叙述,都晤面发生好多不比之抒发,就是“同义不重”。由此,在马耳他语的创作和口语中,都使学会词义替换。此前自己推荐学习者使用英英在线词典,进行查词。除了提升词汇明白能力,加强英英思维,其实还得学会用英文举行词汇替换。甚至小上不极端知道一个歌词汇该怎么说,能够使一个句子举办分解。这吗是一个口译老师提到过的救场方法。

季,要搭建自己之逻辑架构。爱尔兰语的发挥其实相当注重逻辑的。比如许多口语话题可分为人事地物四类(雅思口语话题呢是这样划分)。人物之叙说就是足以望名字、背景音、外貌、个性、工作和上学、生活格局、对君的影响、取得的成就、你爱或非喜的地点这一个地点开展描述。事件类的话题就是足以用我们广大的5W1H分析法,说说怎么来,在啥地方出,有如何人,对自己或有关人的熏陶。物品类的话题可说说背景音,比如是友好请还会见外人送你的,外形,有啊效果,你喜爱用其来做呀,优点和短是什么?地点类的题目可以讲的点再度多,有地理地方、景象、景点、工业、设施、人、食物、历史或利害。

高中的上看到过相同句话称“不要怕,不要后悔。”这些时段因简单的人生阅历我连无领悟其中的含义,只是当有趣,从来记在了心。然则通过这多少个年之斯洛伐克语死磕历程,我才知道了中含有的意思。这么些自当我永不得企及的地点实在非常接近,只在于自身愿不愿意迈出第一步,踏上连无深远的征途。只有无害怕,不曾动摇,我们才免会合否认自己,不会见犹豫在横跨第一步以及坚持与舍弃之间,任由时间流走后,再后悔光阴离去,悲叹自己平转业管成。庆幸的凡,我已起,尽管要倒以难堪的路上,自言自语地游说在,沾沾自喜地笑着,不偏离不弃地死磕着。

请求看我不错的硬挺

玩法
W/S/A/D 或 ↑/↓/←/→ 控制蛇的移动

在线DEMO
图片 1

思路
1、贪吃蛇的各类一样段子也 16×16 像素,场景呢 640×480 像素,也就说网格为 40×30
只,每个网格的边长为 16
2、食物的出现岗位和贪吃蛇的运动方向的反都要当连带的网格内展开
3、贪吃蛇的倒之所以即时运算的方算,当贪吃蛇运动到网格内(蛇有同截的如素地点%网格的边长<蛇在某某日单位下的活动偏移量)时做如下工作:修正蛇的职要其刚在网格内,更新蛇的各一样段的倒方向,判断是否吃到了食品、是否来了冲击等
4、贪吃蛇的每一样段的走方向的改动:蛇头的倒方向冲用户之操作改变,蛇的各级一样截的移动方向设置也这段子的面前同段的活动方向(总计时如若打尾部朝着头部逐段总计)(注:运动方向的更动假如在蛇移动及网格内时举行。其中倘蛇的某个平等段落移动到了网格内,则阐明其余各段都在网格内)

首要代码

图片 2图片 3打之骨干算法
/*
 * 游戏的基本算法
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using System.Windows.Media.Imaging;
using System.Threading;

namespace YYSnake.Core
{
    public partial class Main : UserControl
    {
        private int _columns; // 网格列数
        private int _rows; // 网格行数

        private Dictionary<Body, CellPoint> _bodies = new Dictionary<Body, CellPoint>(); // 贪吃蛇每一样段的集合
        private Dictionary<Bean, CellPoint> _beans = new Dictionary<Bean, CellPoint>(); // 豆的汇聚
        private Dictionary<Skin, CellPoint> _skins = new Dictionary<Skin, CellPoint>(); // 蜕下来的皮的聚集

        private List<CellPoint> _emptyCells = new List<CellPoint>(); // 空网格的汇

        private bool _enabled = false; // 游戏是否运行
        private double _dt = 0.01; // 多少皮秒总计同一不善
        private int _decimals = 1; // 总括小数时所保存的微数位
        private double _speed = 80; // 蛇的运转速度
        private Direction _moveDirection = Direction.Up; // 蛇的运作趋势
        private int _selfLength = 5; // 蛇的无比小长
        private int _beansCount = 5; // 豆的最好特别起数
        private int _ateCapacity = 10; // 食量(抢先则蜕皮)

        private bool _needRaiseAte伊芙nt = false; // 在“蛇头所处职上了网格点区域外”时是不是要触发吃豆事件
        private int _needBeansCount = 0; // 还得追加的豆子的多少

        Random _random = new Random();

        public Main()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Main_Loaded);
        }

        void Main_Loaded(object sender, RoutedEventArgs e)
        {
            this.Width = App.Width; // 640
            this.Height = App.Height; // 480

            _columns = (int)(Width / App.CellSize); // 40
            _rows = (int)(Height / App.CellSize); // 30

            // 防止动画飞出去
            RectangleGeometry rg = new RectangleGeometry();
            rg.Rect = new Rect(0, 0, App.Width, App.Height);
            LayoutRoot.Clip = rg;

            bg.Width = App.Width;
            bg.Height = App.Height;

            ripple.RippleBackground = bg;

            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            _enabled = false;

            canvasBean.Children.Clear();
            canvasSnake.Children.Clear();
            canvasSkin.Children.Clear();
            _beans.Clear();
            _bodies.Clear();
            _skins.Clear();

            _emptyCells.Clear();
            for (int i = 0; i < _columns; i++)
            {
                for (int j = 0; j < _rows; j++)
                {
                    _emptyCells.Add(new CellPoint(i, j));
                }
            }

            _moveDirection = Direction.Up;

            InitSnake();
        }

        /// <summary>
        /// 蛇的初步化
        /// </summary>
        private void InitSnake()
        {
            InitHead();

            for (int i = 0; i < _selfLength – 1; i++)
                AddTail();

            for (int i = 0; i < _beansCount; i++)
                AddBean();
        }

        /// <summary>
        /// 蛇头的开端化
        /// </summary>
        private void InitHead()
        {
            Body head = new Body(BodyType.Head);
            head.MoveDirection = _moveDirection;

            CellPoint point = new CellPoint((int)(_columns / 2), (int)(_rows / 2));
            head.SetValue(Canvas.LeftProperty, point.X * App.CellSize);
            head.SetValue(Canvas.TopProperty, point.Y * App.CellSize);

            _bodies.Add(head, point);
            canvasSnake.Children.Add(head);
        }

        /// <summary>
        /// 扩张一个尾巴
        /// </summary>
        private void AddTail()
        {
            var prevBody = _bodies.Last().Key;
            var prevBodyPoint = _bodies.Last().Value;

            Body tail = new Body(BodyType.Tail);
            tail.MoveDirection = prevBody.MoveDirection;
            CellPoint tailPoint = new CellPoint(prevBodyPoint.X, prevBodyPoint.Y);

            switch (prevBody.MoveDirection)
            {
                case Direction.Up:
                    tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty));
                    tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty) + App.CellSize);
                    tailPoint.Y++;
                    break;
                case Direction.Down:
                    tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty));
                    tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty) – App.CellSize);
                    tailPoint.Y–;
                    break;
                case Direction.Left:
                    tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty) + App.CellSize);
                    tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty));
                    tailPoint.X++;
                    break;
                case Direction.Right:
                    tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty) – App.CellSize);
                    tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty));
                    tailPoint.X–;
                    break;
            }

            tailPoint = CorrectCellPoint(tailPoint);

            _bodies.Add(tail, tailPoint);
            canvasSnake.Children.Add(tail);
        }

        /// <summary>
        /// 扩张一个豆类
        /// </summary>
        private void AddBean()
        {
            if (_needBeansCount < _beansCount)
                _needBeansCount++;
        }

        private DateTime _prevAddBeanDateTime = DateTime.Now;
        /// <summary>
        /// 生成豆
        /// </summary>
        void UpdateBean()
        {
            if (_needBeansCount > 0 && (DateTime.Now – _prevAddBeanDateTime).TotalSeconds > 3)
            {
                List<CellPoint> emptyCells = GetEmptyCells();
                if (emptyCells.Count == 0)
                {
                    GameOver(this, EventArgs.Empty);
                    return;
                }
                CellPoint point = emptyCells[_random.Next(0, emptyCells.Count)];

                Bean bean = new Bean();
                bean.SetValue(Canvas.LeftProperty, point.X * App.CellSize);
                bean.SetValue(Canvas.TopProperty, point.Y * App.CellSize);
                _beans.Add(bean, point);
                canvasBean.Children.Add(bean);

                bean.ani.Completed += delegate
                {
                    ripple.ShowRipple(new Point(point.X * App.CellSize + App.CellSize / 2, point.Y * App.CellSize + App.CellSize / 2));
                    player.PlayDrop();
                };

                _needBeansCount–;
                _prevAddBeanDateTime = DateTime.Now;
            }
        }

        private DateTime _prevDateTime = DateTime.Now;
        private double _leftoverLength = 0d;
        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            double length = (DateTime.Now – _prevDateTime).TotalSeconds + _leftoverLength;
            while (length > _dt)
            {
                Update();
                length -= _dt;
            }

            _leftoverLength = length;
            _prevDateTime = DateTime.Now;
        }

        /// <summary>
        /// 即平时算
        /// </summary>
        private void Update()
        {
            if (!_enabled)
                return;

            double offset = Math.Round(_speed * _dt, _decimals);

            // 蛇头所处地点上了网格点区域外
            if (Math.Abs(Math.Round((double)_bodies.First().Key.GetValue(Canvas.TopProperty) % App.CellSize, _decimals)) < offset && Math.Abs(Math.Round((double)_bodies.First().Key.GetValue(Canvas.LeftProperty) % App.CellSize, _decimals)) < offset)
            {
                UpdateDirection();

                CorrectPosition();

                UpdateBodyCell();

                CheckEat();

                CheckSkin();

                CheckCollision();

                UpdateBean();

                if (_needRaiseAteEvent)
                {
                    Ate(this.Ate, EventArgs.Empty);
                    _needRaiseAteEvent = false;
                }
            }

            UpdatePosition();
        }

        /// <summary>
        /// 蜕皮
        /// </summary>
        private void CheckSkin()
        {
            if (_bodies.Count >= _ateCapacity + _selfLength)
                AddSkin(_ateCapacity);
        }

        /// <summary>
        /// 碰撞检测
        /// </summary>
        private void CheckCollision()
        {
            if (_skins.Any(p => p.Value == _bodies.First().Value) || _bodies.Where(p => p.Key.BodyType == BodyType.Tail).Any(p => p.Value == _bodies.First().Value))
            {
                _enabled = false;
                player.PlayOver();

                GameOver(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 吃豆
        /// </summary>
        private void CheckEat()
        {
            // 是否发吃吃的豆
            var bean = _beans.FirstOrDefault(p => p.Value == _bodies.First().Value).Key;
            if (bean != null)
            {
                _beans.Remove(bean);
                canvasBean.Children.Remove(bean);

                player.PlayEat();

                AddTail();
                AddBean();

                _needRaiseAteEvent = true;
            }
        }

        /// <summary>
        /// 更新蛇的诸一样段落的倒方向
        /// </summary>
        private void UpdateDirection()
        {
            for (int i = _bodies.Count – 1; i > -1; i–)
            {
                if (i == 0)
                    _bodies.ElementAt(i).Key.MoveDirection = _moveDirection;
                else
                    _bodies.ElementAt(i).Key.MoveDirection = _bodies.ElementAt(i – 1).Key.MoveDirection;
            }
        }

        /// <summary>
        /// 更新蛇的各国一样截的职务
        /// </summary>
        private void UpdatePosition()
        {
            double offset = Math.Round(_speed * _dt, _decimals);

            foreach (var body in _bodies.Keys)
            {
                if (body.MoveDirection == Direction.Up)
                    body.SetValue(Canvas.TopProperty, Math.Round((double)body.GetValue(Canvas.TopProperty) – offset, _decimals));
                else if (body.MoveDirection == Direction.Down)
                    body.SetValue(Canvas.TopProperty, Math.Round((double)body.GetValue(Canvas.TopProperty) + offset, _decimals));
                else if (body.MoveDirection == Direction.Left)
                    body.SetValue(Canvas.LeftProperty, Math.Round((double)body.GetValue(Canvas.LeftProperty) – offset, _decimals));
                else if (body.MoveDirection == Direction.Right)
                    body.SetValue(Canvas.LeftProperty, Math.Round((double)body.GetValue(Canvas.LeftProperty) + offset, _decimals));
            }
        }

        /// <summary>
        /// 蜕指定数量的调皮
        /// </summary>
        private void AddSkin(int count)
        {
            player.PlaySkin();

            while (count > 0)
            {
                KeyValuePair<Body, CellPoint> body = _bodies.ElementAt(_bodies.Count – 1);

                CellPoint skinPoint = body.Value;
                Skin skin = new Skin();
                skin.SetValue(Canvas.LeftProperty, skinPoint.X * App.CellSize);
                skin.SetValue(Canvas.TopProperty, skinPoint.Y * App.CellSize);
                _skins.Add(skin, skinPoint);
                canvasSkin.Children.Add(skin);

                _emptyCells.Remove(skinPoint);

                canvasSnake.Children.Remove(body.Key);
                _bodies.Remove(body.Key);
                count–;
            }
        }

        #region 襄助方法
        /// <summary>
        /// 修正指定的岗位音信呢整数
        /// </summary>
        private int CorrectPosition(double position)
        {
            double result;
            double offset = Math.Round(_speed * _dt, _decimals);

            double temp = Math.Round(position % App.CellSize, _decimals);
            if (Math.Abs(temp) < offset)
                result = Math.Round(position – temp);
            else
                result = Math.Round(position – temp) + Math.Sign(temp) * App.CellSize;

            return (int)result;
        }

        /// <summary>
        /// 修正蛇的各级一样段子的地点吗整数
        /// </summary>
        private void CorrectPosition()
        {
            foreach (Body body in _bodies.Keys)
            {
                double x = CorrectPosition((double)body.GetValue(Canvas.LeftProperty));
                double y = CorrectPosition((double)body.GetValue(Canvas.TopProperty));

                if (x == App.Width)
                    x = 0d;
                else if (x == -App.CellSize)
                    x = App.Width – App.CellSize;
                else if (y == App.Height)
                    y = 0d;
                else if (y == -App.CellSize)
                    y = App.Height – App.CellSize;

                body.SetValue(Canvas.LeftProperty, x);
                body.SetValue(Canvas.TopProperty, y);
            }
        }

        /// <summary>
        /// 更新蛇的诸一样段落的网格地点新闻
        /// </summary>
        private void UpdateBodyCell()
        {
            for (int i = 0; i < _bodies.Count; i++)
            {
                UpdateBodyCell(_bodies.ElementAt(i).Key);
            }
        }

        /// <summary>
        /// 更新指定的 Body 的网格地方消息
        /// </summary>
        private void UpdateBodyCell(Body body)
        {
            CellPoint point = new CellPoint((int)((double)body.GetValue(Canvas.LeftProperty) / App.CellSize), (int)((double)body.GetValue(Canvas.TopProperty) / App.CellSize));
            if (body.MoveDirection == Direction.Up)
                point.Y–;
            else if (body.MoveDirection == Direction.Down)
                point.Y++;
            else if (body.MoveDirection == Direction.Left)
                point.X–;
            else if (body.MoveDirection == Direction.Right)
                point.X++;

            point = CorrectCellPoint(point);

            _bodies[body] = point;
        }

        /// <summary>
        /// 修正网格地方
        /// </summary>
        private CellPoint CorrectCellPoint(CellPoint point)
        {
            if (point.X > _columns – 1)
                point.X = _columns – point.X;
            else if (point.X < 0)
                point.X = point.X + _columns;

            if (point.Y > _rows – 1)
                point.Y = _rows – point.Y;
            else if (point.Y < 0)
                point.Y = point.Y + _rows;

            return point;
        }

        /// <summary>
        /// 获取空网格集合
        /// </summary>
        private List<CellPoint> GetEmptyCells()
        {
            List<CellPoint> emptyCells = new List<CellPoint>();

            List<CellPoint> aroundHeadCells = new List<CellPoint>();
            CellPoint headPoint = _bodies.First().Value;
            for (int i = -5; i < 5; i++)
            {
                for (int j = -5; j < 5; j++)
                {
                    CellPoint point = new CellPoint(headPoint.X + i, headPoint.Y + j);
                    point = CorrectCellPoint(point);

                    aroundHeadCells.Add(point);
                }
            }

            // skin 的占位情状为确定了便无移了,所以当 AddSkin() 处总结
            // 为了以下 LINQ 的可用,需要再写 CellPoint 的 public override bool Equals(object obj)
            emptyCells = _emptyCells.Where(p => !_bodies.Select(x => x.Value).Contains(p)).ToList();
            emptyCells = emptyCells.Where(p => !_beans.Select(x => x.Value).Contains(p)).ToList();
            emptyCells = emptyCells.Where(p => !aroundHeadCells.Contains(p)).ToList();

            return emptyCells;
        }
        #endregion

        #region 属性
        public Direction MoveDirection
        {
            set
            {
                Body head = _bodies.First().Key;

                if (head.MoveDirection == Direction.Up && value == Direction.Down)
                    return;
                if (head.MoveDirection == Direction.Down && value == Direction.Up)
                    return;
                if (head.MoveDirection == Direction.Left && value == Direction.Right)
                    return;
                if (head.MoveDirection == Direction.Right && value == Direction.Left)
                    return;

                _moveDirection = value;
            }
        }

        public bool Enabled
        {
            get { return _enabled; }
            set { _enabled = value; }
        }

        public double Speed
        {
            get { return _speed; }
            set { _speed = value; }
        }

        public int AteCapacity
        {
            get { return _ateCapacity; }
            set { _ateCapacity = value; }
        }
        #endregion

        #region 事件 GameOver 和 Ate
        public event EventHandler GameOver;

        public event EventHandler Ate;
        #endregion
    }
}

OK
[源码下载]