public bool Equals(PuzzleMove other) { if (other == null) { return false; } return other.StartingState == StartingState && other.GetEndingState() == GetEndingState(); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); KeyboardState keyboard = Keyboard.GetState(); if (keyboard.IsKeyDown(Keys.Escape)) Exit(); if (keyboard.IsKeyDown(Keys.F11) && prevKeyboardState.IsKeyUp(Keys.F11)) IsFullScreen = !IsFullScreen; //if (keyboard.IsKeyDown(Keys.A) && prevKeyboardState.IsKeyUp(Keys.A)) // isAnimating = !isAnimating; float movement = (float)gameTime.ElapsedGameTime.TotalMilliseconds * 0.02f; if (keyboard.IsKeyDown(Keys.PageUp)) { cameraPosition = new Vector3(cameraPosition.X, cameraPosition.Y, cameraPosition.Z - movement); } if (keyboard.IsKeyDown(Keys.PageDown)) { cameraPosition = new Vector3(cameraPosition.X, cameraPosition.Y, cameraPosition.Z + movement); } float rotation = (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f); if (keyboard.IsKeyDown(Keys.Left)) { rotationMatrix = rotationMatrix * Matrix.CreateRotationY(rotation); } if (keyboard.IsKeyDown(Keys.Right)) { rotationMatrix = rotationMatrix * Matrix.CreateRotationY(-rotation); } if (keyboard.IsKeyDown(Keys.Up)) { rotationMatrix = rotationMatrix * Matrix.CreateRotationX(rotation); } if (keyboard.IsKeyDown(Keys.Down)) { rotationMatrix = rotationMatrix * Matrix.CreateRotationX(-rotation); } bool commandForward = false; bool commandBack = false; bool commandResetView = false; #if WINDOWS_PHONE TouchCollection touches = TouchPanel.GetState(); if (touches.Count > 0) { foreach (TouchLocation touch in touches) { if (touch.Position.X <= _buttonTop) { _rotationVelocity = Vector2.Zero; } } } while (TouchPanel.IsGestureAvailable) { float factor = 0.01f; GestureSample gesture = TouchPanel.ReadGesture(); if (gesture.GestureType == GestureType.FreeDrag) { rotationMatrix = rotationMatrix * Matrix.CreateRotationX(gesture.Delta.X * factor) * Matrix.CreateRotationY(-gesture.Delta.Y * factor); } else if (gesture.GestureType == GestureType.Flick) { float seconds = (float)gameTime.ElapsedGameTime.TotalSeconds; _rotationVelocity = new Vector2(gesture.Delta.X * factor, -gesture.Delta.Y * factor); } else if (gesture.GestureType == GestureType.Tap) { //Debug.WriteLine("Tap " + gesture.Position); if (gesture.Position.X >= _buttonTop) { if (gesture.Position.Y <= GraphicsDevice.Viewport.Height / 3) { commandForward = true; } else if (gesture.Position.Y <= GraphicsDevice.Viewport.Height * 2 / 3) { commandResetView = true; } else { commandBack = true; } } } } #endif foreach (var kvp in _pieceKeyMapping) { if (keyboard.IsKeyDown(kvp.Key) && prevKeyboardState.IsKeyUp(kvp.Key)) { _pieceVisibility[kvp.Value] = !_pieceVisibility[kvp.Value]; } } if (keyboard.IsKeyDown(Keys.R) && prevKeyboardState.IsKeyUp(Keys.R)) { commandResetView = true; } if (keyboard.IsKeyDown(Keys.Space) && prevKeyboardState.IsKeyUp(Keys.Space)) { commandForward = true; } if (keyboard.IsKeyDown(Keys.B) && prevKeyboardState.IsKeyUp(Keys.B)) { commandBack = true; } if (keyboard.IsKeyDown(Keys.U) && prevKeyboardState.IsKeyUp(Keys.U)) { lock (_lockObject) { if (_solved) { _puzzleState = _moves[_moveIndex].PuzzleState; } else { _puzzleState = _solverState; } } } if (commandResetView) { rotationMatrix = Matrix.Identity; cameraPosition = new Vector3(0.0f, 0.0f, 30.0f); _rotationVelocity = Vector2.Zero; } lock (_lockObject) { if (_solved) { if (commandForward) { if (isAnimating) { EndAnimation(); } if (_moveIndex < _moves.Length - 1) { var move = _moves[_moveIndex + 1].BestSolutionPrevMove; if (move.IsRemoval) { _moveIndex++; _puzzleState = _moves[_moveIndex].PuzzleState; } else { SetupAnimation(move, gameTime.TotalGameTime, _moveIndex + 1); } } } if (commandBack) { if (isAnimating) { EndAnimation(); } if (_moveIndex > 0) { int newMoveIndex = _moveIndex - 1; var move = _moves[_moveIndex].BestSolutionPrevMove; if (move.IsRemoval) { _moveIndex--; _puzzleState = _moves[_moveIndex].PuzzleState; } else { var moveToReverse = move; PuzzleMove reverseMove = new PuzzleMove(moveToReverse.GetEndingState().Normalize(), moveToReverse.MovingPieces, moveToReverse.Direction.Negate()); SetupAnimation(reverseMove, gameTime.TotalGameTime, newMoveIndex); } } } } else { if (commandForward) { _showSolverProgress = !_showSolverProgress; } if (commandBack) { _showSolverProgress = false; _puzzleState = _initialState; } } } if (_rotationVelocity != Vector2.Zero) { rotationMatrix = rotationMatrix * Matrix.CreateRotationX(_rotationVelocity.X * (float)gameTime.ElapsedGameTime.TotalSeconds) * Matrix.CreateRotationY(_rotationVelocity.Y * (float)gameTime.ElapsedGameTime.TotalSeconds); float friction = 0.03f; _rotationVelocity *= 1f - (friction - (float)gameTime.ElapsedGameTime.TotalSeconds); } if (isAnimating) { if (gameTime.TotalGameTime >= _animationEnd) { EndAnimation(); } else { TimeSpan animationElapsed = gameTime.TotalGameTime - _animationStart; _animationPercent = (float)(animationElapsed.TotalMilliseconds / _animationLength.TotalMilliseconds); modelPosition = _animationStartModelPosition + (_animationEndModelPosition - _animationStartModelPosition) * _animationPercent; } } else { lock (_lockObject) { modelPosition = GetCenteringVector(_puzzleState); } } prevKeyboardState = keyboard; base.Update(gameTime); }
private void SetupAnimation(PuzzleMove move, TimeSpan totalGameTime, int endMoveIndex) { isAnimating = true; _puzzleAnimationDirection = move.Direction; _puzzlePiecesMoving = move.MovingPieces; _animationPercent = 0; _animationStart = totalGameTime; _animationEnd = totalGameTime.Add(_animationLength); _animationStartModelPosition = GetCenteringVector(move.StartingState); var nonNormalizedEndPosition = move.GetEndingState(); _animationEndModelPosition = GetCenteringVector(nonNormalizedEndPosition); _animationEndMoveIndex = endMoveIndex; }
private Point GetExitDirection(PuzzlePiecePosition piece) { Point minBounds; Point maxBounds; CalculateBounds(new[] { piece.Piece }, out minBounds, out maxBounds); foreach (var kvp in _exitTests) { Point direction = kvp.Key; var test = kvp.Value; var testPosition = piece; Point vector = Point.Zero; while (true) { if (test(testPosition.CurrentPoints, minBounds, maxBounds)) { return direction; } testPosition = testPosition.Move(direction); vector = Point.Add(vector, direction); PuzzleMove testMove = new PuzzleMove(this, piece.Piece, vector); if (!testMove.IsLegal()) { break; } } } //if (piece.CurrentPoints.All(p => p.X > maxBounds.X)) //{ // return new Point(1, 0, 0); //} //if (piece.CurrentPoints.All(p => p.X < minBounds.X)) //{ // return new Point(-1, 0, 0); //} //if (piece.CurrentPoints.All(p => p.Y > maxBounds.Y)) //{ // return new Point(0, 1, 0); //} //if (piece.CurrentPoints.All(p => p.Y < minBounds.Y)) //{ // return new Point(0, -1, 0); //} //if (piece.CurrentPoints.All(p => p.Z > maxBounds.Z)) //{ // return new Point(0, 0, 1); //} //if (piece.CurrentPoints.All(p => p.Z < minBounds.Z)) //{ // return new Point(0, 0, -1); //} return Point.Zero; }
public IEnumerable<PuzzleMove> GetLegalMoves() { Queue<PuzzleMove> potentialExitMoves = new Queue<PuzzleMove>(); Queue<PuzzleMove> potentialMoves = new Queue<PuzzleMove>(); List<PuzzleMove> ret = new List<PuzzleMove>(); foreach (var piece in Pieces) { Point exitDirection = GetExitDirection(piece); if (exitDirection != Point.Zero) { // If a piece can be removed, the only valid moves are removing it, and putting it back in the puzzle PuzzleMove removeMove = new PuzzleMove(this, piece.Piece, exitDirection, true); // We've already verified that the remove move is valid, and we want to take removal moves first anyway //ret.Add(removeMove); potentialExitMoves.Enqueue(removeMove); //PuzzleMove move = new PuzzleMove(this, piece.Piece, new Point(-exitDirection.X, -exitDirection.Y, -exitDirection.Z)); //potentialExitMoves.Enqueue(move); } else { foreach (var direction in Point.Directions) { PuzzleMove move = new PuzzleMove(this, piece.Piece, direction); potentialMoves.Enqueue(move); } } } if (potentialExitMoves.Any()) { // If any pieces can be removed from the puzzle, only consider those as valid moves potentialMoves = potentialExitMoves; } while (potentialMoves.Count > 0) { var move = potentialMoves.Dequeue(); if (move.IsLegal()) { if (!ret.Contains(move)) { ret.Add(move); } } else { var blockers = move.GetBlockingPieces(); var newMovePieces = move.MovingPieces.Concat(blockers); if (newMovePieces.Count() <= this.Pieces.Count() / 2) { var newMove = new PuzzleMove(this, newMovePieces, move.Direction); potentialMoves.Enqueue(newMove); } } } return ret; }
private void Push(PuzzleState newState, PuzzleMove move, SolverFrame prevFrame) { SolverFrame newFrame = new SolverFrame(); newFrame.PuzzleState = newState; newFrame.PrevFame = prevFrame; newFrame.BestSolutionPrevFrame = prevFrame; newFrame.BestSolutionPrevMove = move; newFrame.ChildFrames = new Dictionary<SolverFrame, object>(); newFrame.CalculateSolutionDepth(); var possibleMoves = newFrame.PuzzleState.GetLegalMoves(); WriteLine("Possible moves:"); foreach (var possible in possibleMoves) { WriteLine("\t" + possible.ToString()); } newFrame.PossibleMoves = new Queue<PuzzleMove>(possibleMoves); Stack.Push(newFrame); }