user151496
user151496

Reputation: 1985

A good randomizer for puzzle-15

I have implemented a puzzle 15 for people to compete online. My current randomizer works by starting from the good configuration and moving tiles around for 100 moves (arbitrary number)

Everything is fine, however, once in a little while the tiles are shuffled too easy and it takes only a few moves to solve the puzzle, therefore the game is really unfair for some people reaching better scores in a much higher speed.

What would be a good way to randomize the initial configuration so it is not "too easy"?

Upvotes: 3

Views: 3165

Answers (2)

zegkljan
zegkljan

Reputation: 8401

You can generate a completely random configuration (that is solvable) and then use some solver to determine the optimal sequence of moves. If the sequence is long enough for you, good, otherwise generate a new configuration and repeat.

Update & details

There is an article on Wikipedia about the 15-puzzle and when it is (and isn't) solvable. In short, if the empty square is in the lower-right corner, then the puzzle is solvable if and only if the number of inversions (an inversion is a swap of two elements in the sequence, not necessarily adjacent elements) with respect to the goal permutation is even.

You can then easily generate a solvable start state by doing an even number of inversions, which may lead to a not-so-easy-to-solve state far quicker than by doing regular moves, and it is guaranteed that it will remain solvable.

In fact, you don't need to use a search algorithm as I mentioned above, but an admissible heuristic. Such one always underestimates never overestimates the number of moves needed to solve the puzzle, i.e. you are guaranteed that it will not take less moves that the heuristic tells you.

A good heuristic is the sum of manhattan distances of each number to its goal position.

Summary

In short, a possible (very simple) algorithm for generating starting positions might look like this:

1: current_state <- goal_state
2: swap two arbitrary (randomly selected) pieces
3: swap two arbitrary (randomly selected) pieces again (to ensure solvability)
4: h <- heuristic(current_state)
5: if h > desired threshold
6:     return current_state
7: else
8:   go to 2.

To be absolutely certain about how difficult a state is, you need to find the optimal solution using some solver. Heuristics will give you only an estimate.

Upvotes: 5

Spektre
Spektre

Reputation: 51845

I would do this

  1. start from solution (just like you did)
  2. make valid turn in random direction

    so you must keep track where the gap is and generate random direction (N,E,S,W) and do the move. I think this part you have done too.

  3. compute the randomness of your placements

    So compute some coefficient dependent on the order of the array. So ordered (solved) solutions will have low values and random will have high values. The equation for the coefficiet however is a matter of trial and error. Here some ideas what to use:

    • correlation coefficient
    • sum of average difference of value and its neighbors

      1 2 4
      3 6 5
      9 8 7
      
      coeff(6)= (|6-3|+|6-5|+|6-2|+|6-8|)/4
      coeff=coeff(1)+coeff(2)+...coeff(15)
      
    • abs distance from ordered array

    You can combine more approaches together. You can divide this to separated rows and columns and then combine the sub coefficients together.

  4. loop #2 unit coefficient from #3 is high enough (treshold)

    The treshold can be used also to change the difficulty.

Upvotes: 2

Related Questions