I recently came across a game that generates a NxN (2x2, 4x4...) board with numbered tiles (1, 2, 3...), where each number determines the allowed moves. Goal is to empty the whole board, if possible, while every tile can be used only once.
A small board could look like this:
| 1 1 |
| 1 1 |
larger board:
| 1 2 2 3 |
| 2 1 1 1 |
| 3 2 1 3 |
| 2 2 3 1 |
Since I often stumbled across the situation where a solution was not possible, I tried to write a short script that checks if a solution can be found or not before the board is used.
While this worked partially, checking every possible combination and storing all results separately became more complicated and I'm not even sure if this is possible at all.
Here's the simplified example:
$tiles[1][1] = 'p1';
$tiles[2][1] = 'p1';
$tiles[1][2] = 'p1';
$tiles[2][2] = 'p1';
$moves = array(
array('x' => -1, 'y' => -1),
array('x' => 0, 'y' => -1),
array('x' => 1, 'y' => -1),
array('x' => -1, 'y' => 0),
array('x' => 1, 'y' => 0),
array('x' => -1, 'y' => 1),
array('x' => 0, 'y' => 1),
array('x' => 1, 'y' => 1)
);
function nextMove($x, $y, &$visited)
{
global $moves;
$max_loops = count($moves);
$visited[] = $x. ', ' .$y;
for ($j = 0; $j < $max_loops; $j++)
{
$new_x = $x + $moves[$j]['x'];
$new_y = $y + $moves[$j]['y'];
if (($new_x >= 1) && ($new_x <= 2) && ($new_y >= 1) && ($new_y <= 2))
{
$new_pos = $new_x. ', ' .$new_y;
if (!in_array($new_pos, $visited))
{
$j = $max_loops - 1;
nextMove($new_x, $new_y, $visited);
}
}
}
}
nextMove(1, 1, $visited, $moves_done);
var_dump($visited);
So, what happens here is rather simple:
The function gets called with the initial coordinates, counts the maximum amount of moves (for that tile) and adds the current position to the $visited array.
After that, the for loop iteartes through the array of possible moves, generates new coordinates and checks if they are on the board or if that tile has been 'visited' before. If a valid move was found, the function gets called again with the new coordinates.
(As you can see $j = $max_loops - 1; ends the loop here to avoid wrong values added to $visited, if no valid move was found later)
This is what happens right now:
array(4) {
[0]=>
string(4) "1, 1"
[1]=>
string(4) "1, 2"
[2]=>
string(4) "2, 1"
[3]=>
string(4) "2, 2"
}
So far the script is working, but as soon as there's no possible move, the script ends and doesn't check further combinations (with $j = $max_loops - 1;) or adds wrong coordinates to $visited. To avoid this I either have to store the results separately or change the function and this is where I got stuck.
One big problem is the unknown amount of possible moves, because sometimes the game ends after 2 moves, sometimes the board can be cleared.
Is there any way to get the function to iterate through all possible combinations and store/return them separately (might be too much to handle and not neccesary, but could be interesting if only 1-2 tiles can't be used) OR at least check if the whole board can be cleared and return the solution (this is important, because the result should get stored and used later)?
The script should work this way:
array(4) {
[0]=>
string(4) "1, 1"
[1]=>
string(4) "1, 2"
[2]=>
string(4) "2, 1"
[3]=>
string(4) "2, 2"
}
array(4) {
[0]=>
string(4) "1, 1"
[1]=>
string(4) "1, 2"
[2]=>
string(4) "2, 2"
[3]=>
string(4) "2, 1"
}
array(4) {
[0]=>
string(4) "1, 1"
[1]=>
string(4) "2, 1"
[2]=>
string(4) "1, 2"
[3]=>
string(4) "2, 2"
}
array(4) {
[0]=>
string(4) "1, 1"
[1]=>
string(4) "2, 1"
[2]=>
string(4) "2, 2"
[3]=>
string(4) "1, 2"
}
array(4) {
[0]=>
string(4) "1, 1"
[1]=>
string(4) "2, 2"
[2]=>
string(4) "2, 1"
[3]=>
string(4) "1, 2"
}
array(4) {
[0]=>
string(4) "1, 1"
[1]=>
string(4) "2, 2"
[2]=>
string(4) "1, 2"
[3]=>
string(4) "2, 1"
}
[...]