Exemplo n.º 1
0
        public bool CanPush(Direction direction)
        {
            if (CellContents == null) //如果内容为空
            {
                return(false);        //不能推一个空的无内容的方块
            }
            Cell neighbour =          //获取邻近的方块
                             Level[Location.GetAdjacentLocation(direction)];

            return(neighbour != null && neighbour.CanEnter);
        }
Exemplo n.º 2
0
        public bool TryPushContents(Direction direction)
        {
            if (!CanPush(direction))//判断指定的方向是否可以推动
            {
                return(false);
            }
            Cell neighbour = //得到邻近的方格
                             Level[Location.GetAdjacentLocation(direction)];

            neighbour.TrySetContents(CellContents);//设置邻近方格的内容
            return(true);
        }
Exemplo n.º 3
0
        /// <summary>
        /// 使用特定的Jump对象进行跳转移动
        /// </summary>
        /// <param name="jump">指定如何移动的Jump对象</param>
        internal bool DoMove(Jump jump)
        {
            bool result = false; //初始化结果值

            if (jump.Undo)       //如果为撤消跳转
            {
                lock (moveLock)  //使用线程同步对象锁定线程
                {                //遍历移动路径
                    for (int i = jump.Route.Length - 1; i >= 0; i--)
                    {            //获得要移动的邻近的相反的方向
                        Location moveLocation = Location.GetAdjacentLocation
                                                    (jump.Route[i].Direction.GetOppositeDirection());
                        //得到目标Cell对象实例
                        Cell toCell = Level[moveLocation];
                        if (!toCell.TrySetContents(this)) //尝试设置方块内容
                        {                                 //如果放置失败,抛出异常
                            throw new SokobanException("不能到达指定的路径.");
                        }
                    }
                    MoveCount -= jump.Route.Length;//减少移动步骤
                    result     = true;
                }
            }
            else
            {  //使用ThreadPool接收的WaitCallback创建线程执行代码
                WaitCallback callback = delegate
                {
                    #region 匿名Jump方法.
                    lock (moveLock)
                    {   //使用SearchPathFinder查找最短移动路径
                        SearchPathFinder searchPathFinder =
                            new SearchPathFinder(Cell, jump.Destination);
                        if (searchPathFinder.TryFindPath()) //查找最短目标路径
                        {                                   //遍历结果路径
                            for (int i = 0; i < searchPathFinder.Route.Length; i++)
                            {
                                Move move = searchPathFinder.Route[i]; //得到路径中的Move对象
                                                                       /* 休眠线程指定的时长*/
                                Thread.Sleep(stepDelay);
                                Location moveLocation =                //获取移动的邻近位置
                                                        Location.GetAdjacentLocation(move.Direction);
                                Cell toCell = Level[moveLocation];     //得到目标Cell
                                if (!toCell.TrySetContents(this))      //设置目标Cell内容
                                {                                      //如果无法到达,则抛出异常
                                    throw new SokobanException("不能到达指定的路径.");
                                }
                                MoveCount++;//增加移动步长
                            }
                            /* 设置用于撤消跳转的Jump对象*/
                            Jump newMove = new Jump(searchPathFinder.Route)
                            {
                                Undo = true
                            };
                            moves.Push(newMove);//将对象压入堆栈
                            result = true;
                        }
                    }
                    #endregion
                };//将callback放入线程池,在后台执行跳转操作
                ThreadPool.QueueUserWorkItem(callback);
            }
            return(result);//返回执行结果
        }
Exemplo n.º 4
0
        /// <summary>
        /// Attempt to relocate to the another cell
        /// using the route in the specified <see cref="Push"/> instance.
        /// </summary>
        /// <param name="push">The push.</param>
        /// <returns><code>true</code> if the move succeeded,
        /// <code>false</code> otherwise.</returns>
        internal bool DoMove(Push push)
        {
            bool result = false;

            if (push.Undo)
            {
                lock (moveLock)
                {
                    for (int i = push.Route.Length - 1; i >= 0; i--)
                    {
                        Move     move         = push.Route[i];
                        Location moveLocation = Location.GetAdjacentLocation(push.Route[i].Direction.GetOppositeDirection());
                        Cell     toCell       = Level[moveLocation];
                        Cell     fromCell     = this.Cell;
                        if (!toCell.TrySetContents(this))
                        {
                            throw new SokobanException("Unable to follow route.");
                        }
                        if (move.PushedContents != null)
                        {
                            if (!fromCell.TrySetContents(move.PushedContents))
                            {
                                throw new SokobanException("Unable to undo set contents.");
                            }
                        }
                    }
                    MoveCount -= push.Route.Length;
                    result     = true;
                }
            }
            else
            {
                WaitCallback callback = delegate(object state)
                {
                    #region Anonymous Push method.
                    lock (moveLock)
                    {
                        PushPathFinder pathFinder = new PushPathFinder(Cell, push.Desrination);
                        if (pathFinder.TryFindPath())
                        {
                            for (int i = 0; i < pathFinder.Route.Length; i++)
                            {
                                Move move = pathFinder.Route[i];

                                /* Sleep for the stepDelay period. */
                                Thread.Sleep(stepDelay);
                                Location moveLocation = Location.GetAdjacentLocation(move.Direction);
                                Cell     toCell       = Level[moveLocation];
                                if (!toCell.CanEnter && toCell.CellContents is Treasure)
                                {
                                    move.PushedContents = toCell.CellContents;
                                    if (!toCell.TryPushContents(move.Direction))
                                    {
                                        throw new SokobanException("Unable to push contents.");
                                    }
                                }
                                if (!toCell.TrySetContents(this))
                                {
                                    throw new SokobanException("Unable to follow route.");
                                }
                                MoveCount++;
                            }
                            /* Set the undo item. */
                            Push newMove = new Push(pathFinder.Route)
                            {
                                Undo = true
                            };
                            moves.Push(newMove);
                            result = true;
                        }
                    }
                    #endregion
                };
                ThreadPool.QueueUserWorkItem(callback);
            }
            return(result);
        }
Exemplo n.º 5
0
        internal bool DoMoveAux(Move move)    //单步移动操作辅助方法
        {
            bool     result       = false;    //初始化返回值
            Location moveLocation = Location. //得到指定方向的邻近的一个位置
                                    GetAdjacentLocation(move.Direction);

            if (Level.InBounds(moveLocation))                      //判断位置是否在游戏区域内部
            {
                Cell         toCell         = Level[moveLocation]; //得到要移动位置的Cell对象
                Cell         fromCell       = Level[Location];     //得到来源位置的Cell对象
                CellContents toCellContents = toCell.CellContents; //获取移动位置的内容
                if (toCell.CanEnter)                               //如果目标Cell允许设置内容
                {                                                  //如果不是撤消操作而是一个标准移动
                    if (!move.Undo)
                    {                                              //设置目标Cell的方块内容
                        result = toCell.TrySetContents(this);
                        if (result)
                        {
                            Move newMove =  //为撤消操作指定相反的方向以备撤消
                                           new Move(move.Direction.GetOppositeDirection())
                            {
                                Undo = true
                            };
                            moves.Push(newMove); //向撤消堆栈中插入Move
                            MoveCount++;         //移动次数增加
                        }
                    }
                    //如果是撤消移动操作的话
                    else if (move.PushedContents != null) //如果角色推动的内容存在
                    {                                     //设置目标方块的推动内容
                        toCell.TrySetContents(this);
                        //然后向源方块设置推动的内容,因为单步移动操作
                        result = fromCell.TrySetContents(move.PushedContents);
                        if (result)
                        {   //移动次数减少
                            MoveCount--;
                        }
                    }
                    else
                    {   /* 如果没有推动内容,直接设置目标方块内容 */
                        result = toCell.TrySetContents(this);
                        if (result)
                        {   //移动次数减少
                            MoveCount--;
                        }
                    }
                }//如果目标方块有内容,则先将目标方块内容推动到邻近方块
                else if (toCell.TryPushContents(move.Direction))
                {   //如果不为撤消操作
                    if (!move.Undo)
                    {
                        Move newMove =  //实例化Move,并指定推动的内容以便撤消
                                       new Move(move.Direction.GetOppositeDirection())
                        {
                            Undo = true, PushedContents = toCellContents
                        };
                        moves.Push(newMove);//压入撤消堆栈
                    }
                    //设置目标方块的内容
                    result = toCell.TrySetContents(this);
                    if (result)
                    {   //移动次数增加
                        MoveCount++;
                    }
                }
            }
            return(result);//返回最终操作结果
        }