public bool CanPush(Direction direction) { if (CellContents == null) //如果内容为空 { return(false); //不能推一个空的无内容的方块 } Cell neighbour = //获取邻近的方块 Level[Location.GetAdjacentLocation(direction)]; return(neighbour != null && neighbour.CanEnter); }
public bool TryPushContents(Direction direction) { if (!CanPush(direction))//判断指定的方向是否可以推动 { return(false); } Cell neighbour = //得到邻近的方格 Level[Location.GetAdjacentLocation(direction)]; neighbour.TrySetContents(CellContents);//设置邻近方格的内容 return(true); }
/// <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);//返回执行结果 }
/// <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); }
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);//返回最终操作结果 }