0
\$\begingroup\$

I am making a 15 Puzzle game in C# that allows the user to enter a custom row and column value up to a maximum of a 10 x 10 puzzle. I am having problems with the shuffle method.

I want to make it so the puzzle is always solvable by first creating a winning puzzle then shuffling the empty space. The problem is it is too inefficient to call every click event each time. I need a way to invoke the click event of a button adjacent to the empty space but not diagonal. I also use an invisible static button for the empty spot. The PuzzlePiece class inherits from Button. I am not too sure how to do this.

Here is what I have:

private void shuffleBoard()
    {
        //5 is just for test purposes
        for (int i = 0; i < 5; i++)
        {
            foreach (Control item in this.Controls)
            {
                if (item is PuzzlePiece)
                {
                    ((PuzzlePiece)item).PerformClick();
                }
            }
        }
    }

 void PuzzlePiece_Click(object sender, EventArgs e)
    {
        PuzzlePiece piece = (PuzzlePiece)sender;

        if (piece.Right == puzzleForm.emptyPiece.Left && piece.Top == puzzleForm.emptyPiece.Top)
        {
            movePiece(piece);
        }
        else if (piece.Left == puzzleForm.emptyPiece.Right && piece.Top == puzzleForm.emptyPiece.Top)
        {
            movePiece(piece);
        }
        else if (piece.Top == puzzleForm.emptyPiece.Bottom && piece.Left == puzzleForm.emptyPiece.Left)
        {
            movePiece(piece);
        }
        else if (piece.Bottom == puzzleForm.emptyPiece.Top && piece.Left == puzzleForm.emptyPiece.Left)
        {
            movePiece(piece);
        }
    }
\$\endgroup\$
7
\$\begingroup\$

Separation of Concern, shuffling the board shouldn't be done by simulating a user, it should be done directly with the model (as in Model-View-Presenter)

class Puzzle
{
  IList<Direction> GetValidMoves();
  void MakeMove(Direction);
  enum Direction {Up, Left, Down, Right};
}

With a class similar to the one above you could shuffle the board in this manner (for instance):

Random random = new Random();
for (int i=0; i<ShufflingThoroughness; i++)
{
  var moves = puzzle.GetValidMoves();
  int chosenIndex = random.Next(moves.Count);
  puzzle.MakeMove(moves[chosenIndex]);
}

This is untested code, but would randomly pick any of the valid directions from the current puzzle state. You could remove the opposite of the previous move to prevent it from going back and forth, but it would be premature optimization (simply running the loop extra times would counter this and is probably faster than keeping track of the previous move and excluding it from the random sequence).

Once you have shuffled the board you read the internal state of the board (expose it through public properties on the puzzle) and set the view to match the model. Each time the player clicks one of the tiles next to the empty slot it would call Puzzle.MakeMove(...) using the direction to the empty tile. After each move you can call Puzzle.IsSolved() which would check if the puzzle is, in fact, solved.

This way your view can hold only the code necessary for rendering your puzzle nicely. Your presenter handles the mouse clicks as well as updates the view (PuzzleView.ShowPiece(row, column, puzzlePiece) would make a good start), and the model solves the core of the game. How you can move the empty piece around, and gives you the methods for moving it.

|improve this answer|||||
\$\endgroup\$
4
\$\begingroup\$

The solvability of an n puzzle can be tested (after shuffling) by computing the permutations of the puzzle.

"While odd permutations of the puzzle are impossible to solve, all even permutations are solvable."

For the math behind this, please see http://mathworld.wolfram.com/15Puzzle.html

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ I consider myself a professional at 3x3 and 4x4. I never knew there were unsolvable permutations. Makes me wonder how the developers of Mickey's Ultimate Challenge (SNES) or Universal Studios (Gamecube) went through on their 15-Puzzle implementations. \$\endgroup\$ – Nathan Goings Jan 3 '19 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.