上接游戏人生Silverlight(6) - 贪吃蛇[Silverlight 3.0(c#)]

本文详细解析了一款游戏蛇的AI算法实现,包括蛇的移动、吃豆、碰撞检测等功能的具体实现方式,以及如何通过定时生成豆子增加游戏挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/// <summary> 
InBlock.gif                 /// 生成豆 
InBlock.gif                 /// </summary> 
InBlock.gif                 void UpdateBean() 
InBlock.gif                { 
InBlock.gif                         if (_needBeansCount > 0 && (DateTime.Now - _prevAddBeanDateTime).TotalSeconds > 3) 
InBlock.gif                        { 
InBlock.gif                                List<CellPoint> emptyCells = GetEmptyCells(); 
InBlock.gif                                 if (emptyCells.Count == 0) 
InBlock.gif                                { 
InBlock.gif                                        GameOver( this, EventArgs.Empty); 
InBlock.gif                                         return
InBlock.gif                                } 
InBlock.gif                                CellPoint point = emptyCells[_random.Next(0, emptyCells.Count)]; 
InBlock.gif 
InBlock.gif                                Bean bean =  new Bean(); 
InBlock.gif                                bean.SetValue(Canvas.LeftProperty, point.X * App.CellSize); 
InBlock.gif                                bean.SetValue(Canvas.TopProperty, point.Y * App.CellSize); 
InBlock.gif                                _beans.Add(bean, point); 
InBlock.gif                                canvasBean.Children.Add(bean); 
InBlock.gif 
InBlock.gif                                bean.ani.Completed +=  delegate 
InBlock.gif                                { 
InBlock.gif                                        ripple.ShowRipple( new Point(point.X * App.CellSize + App.CellSize / 2, point.Y * App.CellSize + App.CellSize / 2)); 
InBlock.gif                                        player.PlayDrop(); 
InBlock.gif                                }; 
InBlock.gif 
InBlock.gif                                _needBeansCount--; 
InBlock.gif                                _prevAddBeanDateTime = DateTime.Now; 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 private DateTime _prevDateTime = DateTime.Now; 
InBlock.gif                 private  double _leftoverLength = 0d; 
InBlock.gif                 void CompositionTarget_Rendering( object sender, EventArgs e) 
InBlock.gif                { 
InBlock.gif                         double length = (DateTime.Now - _prevDateTime).TotalSeconds + _leftoverLength; 
InBlock.gif                         while (length > _dt) 
InBlock.gif                        { 
InBlock.gif                                Update(); 
InBlock.gif                                length -= _dt; 
InBlock.gif                        } 
InBlock.gif 
InBlock.gif                        _leftoverLength = length; 
InBlock.gif                        _prevDateTime = DateTime.Now; 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 即时计算 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void Update() 
InBlock.gif                { 
InBlock.gif                         if (!_enabled) 
InBlock.gif                                 return
InBlock.gif 
InBlock.gif                         double offset = Math.Round(_speed * _dt, _decimals); 
InBlock.gif 
InBlock.gif                         // 蛇头所处位置进入了网格点区域内 
InBlock.gif                         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) 
InBlock.gif                        { 
InBlock.gif                                UpdateDirection(); 
InBlock.gif 
InBlock.gif                                CorrectPosition(); 
InBlock.gif 
InBlock.gif                                UpdateBodyCell(); 
InBlock.gif 
InBlock.gif                                CheckEat(); 
InBlock.gif 
InBlock.gif                                CheckSkin(); 
InBlock.gif 
InBlock.gif                                CheckCollision(); 
InBlock.gif 
InBlock.gif                                UpdateBean(); 
InBlock.gif 
InBlock.gif                                 if (_needRaiseAteEvent) 
InBlock.gif                                { 
InBlock.gif                                        Ate( this.Ate, EventArgs.Empty); 
InBlock.gif                                        _needRaiseAteEvent =  false
InBlock.gif                                } 
InBlock.gif                        } 
InBlock.gif 
InBlock.gif                        UpdatePosition(); 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 蜕皮 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void CheckSkin() 
InBlock.gif                { 
InBlock.gif                         if (_bodies.Count >= _ateCapacity + _selfLength) 
InBlock.gif                                AddSkin(_ateCapacity); 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 碰撞检测 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void CheckCollision() 
InBlock.gif                { 
InBlock.gif                         if (_skins.Any(p => p.Value == _bodies.First().Value) || _bodies.Where(p => p.Key.BodyType == BodyType.Tail).Any(p => p.Value == _bodies.First().Value)) 
InBlock.gif                        { 
InBlock.gif                                _enabled =  false
InBlock.gif                                player.PlayOver(); 
InBlock.gif 
InBlock.gif                                GameOver( this, EventArgs.Empty); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 吃豆 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void CheckEat() 
InBlock.gif                { 
InBlock.gif                         // 是否有被吃的豆 
InBlock.gif                        var bean = _beans.FirstOrDefault(p => p.Value == _bodies.First().Value).Key; 
InBlock.gif                         if (bean !=  null
InBlock.gif                        { 
InBlock.gif                                _beans.Remove(bean); 
InBlock.gif                                canvasBean.Children.Remove(bean); 
InBlock.gif 
InBlock.gif                                player.PlayEat(); 
InBlock.gif 
InBlock.gif                                AddTail(); 
InBlock.gif                                AddBean(); 
InBlock.gif 
InBlock.gif                                _needRaiseAteEvent =  true
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 更新蛇的每一段的运动方向 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void UpdateDirection() 
InBlock.gif                { 
InBlock.gif                         for ( int i = _bodies.Count - 1; i > -1; i--) 
InBlock.gif                        { 
InBlock.gif                                 if (i == 0) 
InBlock.gif                                        _bodies.ElementAt(i).Key.MoveDirection = _moveDirection; 
InBlock.gif                                 else 
InBlock.gif                                        _bodies.ElementAt(i).Key.MoveDirection = _bodies.ElementAt(i - 1).Key.MoveDirection; 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 更新蛇的每一段的位置 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void UpdatePosition() 
InBlock.gif                { 
InBlock.gif                         double offset = Math.Round(_speed * _dt, _decimals); 
InBlock.gif 
InBlock.gif                         foreach (var body  in _bodies.Keys) 
InBlock.gif                        { 
InBlock.gif                                 if (body.MoveDirection == Direction.Up) 
InBlock.gif                                        body.SetValue(Canvas.TopProperty, Math.Round(( double)body.GetValue(Canvas.TopProperty) - offset, _decimals)); 
InBlock.gif                                 else  if (body.MoveDirection == Direction.Down) 
InBlock.gif                                        body.SetValue(Canvas.TopProperty, Math.Round(( double)body.GetValue(Canvas.TopProperty) + offset, _decimals)); 
InBlock.gif                                 else  if (body.MoveDirection == Direction.Left) 
InBlock.gif                                        body.SetValue(Canvas.LeftProperty, Math.Round(( double)body.GetValue(Canvas.LeftProperty) - offset, _decimals)); 
InBlock.gif                                 else  if (body.MoveDirection == Direction.Right) 
InBlock.gif                                        body.SetValue(Canvas.LeftProperty, Math.Round(( double)body.GetValue(Canvas.LeftProperty) + offset, _decimals)); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 蜕指定数量的皮 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void AddSkin( int count) 
InBlock.gif                { 
InBlock.gif                        player.PlaySkin(); 
InBlock.gif 
InBlock.gif                         while (count > 0) 
InBlock.gif                        { 
InBlock.gif                                KeyValuePair<Body, CellPoint> body = _bodies.ElementAt(_bodies.Count - 1); 
InBlock.gif 
InBlock.gif                                CellPoint skinPoint = body.Value; 
InBlock.gif                                Skin skin =  new Skin(); 
InBlock.gif                                skin.SetValue(Canvas.LeftProperty, skinPoint.X * App.CellSize); 
InBlock.gif                                skin.SetValue(Canvas.TopProperty, skinPoint.Y * App.CellSize); 
InBlock.gif                                _skins.Add(skin, skinPoint); 
InBlock.gif                                canvasSkin.Children.Add(skin); 
InBlock.gif 
InBlock.gif                                _emptyCells.Remove(skinPoint); 
InBlock.gif 
InBlock.gif                                canvasSnake.Children.Remove(body.Key); 
InBlock.gif                                _bodies.Remove(body.Key); 
InBlock.gif                                count--; 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif辅助方法 #region 辅助方法 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 修正指定的位置信息为整数 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  int CorrectPosition( double position) 
InBlock.gif                { 
InBlock.gif                         double result; 
InBlock.gif                         double offset = Math.Round(_speed * _dt, _decimals); 
InBlock.gif 
InBlock.gif                         double temp = Math.Round(position % App.CellSize, _decimals); 
InBlock.gif                         if (Math.Abs(temp) < offset) 
InBlock.gif                                result = Math.Round(position - temp); 
InBlock.gif                         else 
InBlock.gif                                result = Math.Round(position - temp) + Math.Sign(temp) * App.CellSize; 
InBlock.gif 
InBlock.gif                         return ( int)result; 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 修正蛇的每一段的位置为整数 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void CorrectPosition() 
InBlock.gif                { 
InBlock.gif                         foreach (Body body  in _bodies.Keys) 
InBlock.gif                        { 
InBlock.gif                                 double x = CorrectPosition(( double)body.GetValue(Canvas.LeftProperty)); 
InBlock.gif                                 double y = CorrectPosition(( double)body.GetValue(Canvas.TopProperty)); 
InBlock.gif 
InBlock.gif                                 if (x == App.Width) 
InBlock.gif                                        x = 0d; 
InBlock.gif                                 else  if (x == -App.CellSize) 
InBlock.gif                                        x = App.Width - App.CellSize; 
InBlock.gif                                 else  if (y == App.Height) 
InBlock.gif                                        y = 0d; 
InBlock.gif                                 else  if (y == -App.CellSize) 
InBlock.gif                                        y = App.Height - App.CellSize; 
InBlock.gif 
InBlock.gif                                body.SetValue(Canvas.LeftProperty, x); 
InBlock.gif                                body.SetValue(Canvas.TopProperty, y); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 更新蛇的每一段的网格位置信息 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void UpdateBodyCell() 
InBlock.gif                { 
InBlock.gif                         for ( int i = 0; i < _bodies.Count; i++) 
InBlock.gif                        { 
InBlock.gif                                UpdateBodyCell(_bodies.ElementAt(i).Key); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 更新指定的 Body 的网格位置信息 
InBlock.gif                 /// </summary> 
InBlock.gif                 private  void UpdateBodyCell(Body body) 
InBlock.gif                { 
InBlock.gif                        CellPoint point =  new CellPoint(( int)(( double)body.GetValue(Canvas.LeftProperty) / App.CellSize), ( int)(( double)body.GetValue(Canvas.TopProperty) / App.CellSize)); 
InBlock.gif                         if (body.MoveDirection == Direction.Up) 
InBlock.gif                                point.Y--; 
InBlock.gif                         else  if (body.MoveDirection == Direction.Down) 
InBlock.gif                                point.Y++; 
InBlock.gif                         else  if (body.MoveDirection == Direction.Left) 
InBlock.gif                                point.X--; 
InBlock.gif                         else  if (body.MoveDirection == Direction.Right) 
InBlock.gif                                point.X++; 
InBlock.gif 
InBlock.gif                        point = CorrectCellPoint(point); 
InBlock.gif 
InBlock.gif                        _bodies[body] = point; 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 修正网格位置 
InBlock.gif                 /// </summary> 
InBlock.gif                 private CellPoint CorrectCellPoint(CellPoint point) 
InBlock.gif                { 
InBlock.gif                         if (point.X > _columns - 1) 
InBlock.gif                                point.X = _columns - point.X; 
InBlock.gif                         else  if (point.X < 0) 
InBlock.gif                                point.X = point.X + _columns; 
InBlock.gif 
InBlock.gif                         if (point.Y > _rows - 1) 
InBlock.gif                                point.Y = _rows - point.Y; 
InBlock.gif                         else  if (point.Y < 0) 
InBlock.gif                                point.Y = point.Y + _rows; 
InBlock.gif 
InBlock.gif                         return point; 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 /// <summary> 
InBlock.gif                 /// 获取空网格集合 
InBlock.gif                 /// </summary> 
InBlock.gif                 private List<CellPoint> GetEmptyCells() 
InBlock.gif                { 
InBlock.gif                        List<CellPoint> emptyCells =  new List<CellPoint>(); 
InBlock.gif 
InBlock.gif                        List<CellPoint> aroundHeadCells =  new List<CellPoint>(); 
InBlock.gif                        CellPoint headPoint = _bodies.First().Value; 
InBlock.gif                         for ( int i = -5; i < 5; i++) 
InBlock.gif                        { 
InBlock.gif                                 for ( int j = -5; j < 5; j++) 
InBlock.gif                                { 
InBlock.gif                                        CellPoint point =  new CellPoint(headPoint.X + i, headPoint.Y + j); 
InBlock.gif                                        point = CorrectCellPoint(point); 
InBlock.gif 
InBlock.gif                                        aroundHeadCells.Add(point); 
InBlock.gif                                } 
InBlock.gif                        } 
InBlock.gif 
InBlock.gif                         // skin 的占位情况因为确定了就不变了,所以在 AddSkin() 处计算 
InBlock.gif                         // 为了以下 LINQ 的可用,需要重写 CellPoint 的 public override bool Equals(object obj) 
InBlock.gif                        emptyCells = _emptyCells.Where(p => !_bodies.Select(x => x.Value).Contains(p)).ToList(); 
InBlock.gif                        emptyCells = emptyCells.Where(p => !_beans.Select(x => x.Value).Contains(p)).ToList(); 
InBlock.gif                        emptyCells = emptyCells.Where(p => !aroundHeadCells.Contains(p)).ToList(); 
InBlock.gif 
InBlock.gif                         return emptyCells; 
InBlock.gif                } 
InBlock.gif                #endregion 
InBlock.gif 
InBlock.gif属性 #region 属性 
InBlock.gif                 public Direction MoveDirection 
InBlock.gif                { 
InBlock.gif                        set 
InBlock.gif                        { 
InBlock.gif                                Body head = _bodies.First().Key; 
InBlock.gif 
InBlock.gif                                 if (head.MoveDirection == Direction.Up && value == Direction.Down) 
InBlock.gif                                         return
InBlock.gif                                 if (head.MoveDirection == Direction.Down && value == Direction.Up) 
InBlock.gif                                         return
InBlock.gif                                 if (head.MoveDirection == Direction.Left && value == Direction.Right) 
InBlock.gif                                         return
InBlock.gif                                 if (head.MoveDirection == Direction.Right && value == Direction.Left) 
InBlock.gif                                         return
InBlock.gif 
InBlock.gif                                _moveDirection = value; 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 public  bool Enabled 
InBlock.gif                { 
InBlock.gif                        get {  return _enabled; } 
InBlock.gif                        set { _enabled = value; } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 public  double Speed 
InBlock.gif                { 
InBlock.gif                        get {  return _speed; } 
InBlock.gif                        set { _speed = value; } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                 public  int AteCapacity 
InBlock.gif                { 
InBlock.gif                        get {  return _ateCapacity; } 
InBlock.gif                        set { _ateCapacity = value; } 
InBlock.gif                } 
InBlock.gif                #endregion 
InBlock.gif 
InBlock.gif事件 GameOver 和 Ate #region 事件 GameOver 和 Ate 
InBlock.gif                 public  event EventHandler GameOver; 
InBlock.gif 
InBlock.gif                 public  event EventHandler Ate; 
InBlock.gif                #endregion 
InBlock.gif        } 
InBlock.gif}
 



     本文转自webabcd 51CTO博客,原文链接: http://blog.51cto.com/webabcd/345619 ,如需转载请自行联系原作者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值