Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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);
        }
    }
share|improve this question

1 Answer 1

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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