Step 4 - Randomize the grid¶
In this step, you learn how to define your own functions in a Lua script. First you define helper functions, then you use these functions to randomize the initial positions of the pieces in the grid.
To randomize the grid:
Define a function that returns an array of integers.
In Lua, you declare functions with the
functionkeyword.Add the function to the script before the
grid:removeAllChildren().Note
This function starts the array at index 1. This is customary in Lua, but is not required. Keep in mind that the Kanzi Engine functions, such as
getChild, start indexing at 0.-- Declare a function that returns a list of integers from 1 to length. local function createArray(length) -- Initialize a variable that contains an empty array. local array = {} -- Fill the array with integers. for i = 1,length do array[i] = i end return array end
Define a function that randomizes the given array of integers, and add it after the
createArrayfunction.You can use the built-in Lua Math library.
-- Declare a function that randomizes the array argument with Fisher-Yates shuffle. local function shuffleArray(array) -- Loop backward from array length to 2. for i = #array, 2, -1 do -- Use the Lua Math library to create a random integer. local j = math.random(i) -- j is in range [1,i] -- Swap the array items at index i and j. array[i], array[j] = array[j], array[i] end end
Not all puzzle configurations are solvable 15 puzzles. Define a function that checks whether a given permutation represents a solvable puzzle. If the puzzle is not solvable, this function modifies the permutation. Add the function after the
shuffleArrayfunction.-- Declare a function that modifies the given permutation to make it a solvable puzzle. local function makeSolvable(permutation) local n = #permutation -- Count the number of inversions in the permutation. local inversions = 0 for i = 1,n do for j = i+1,n do if permutation[i] > permutation[j] then inversions = inversions + 1 end end end -- If the puzzle is not solvable, swap two adjacent pieces to fix it. if inversions % 2 == 1 then permutation[1], permutation[2] = permutation[2], permutation[1] end end
To get a randomized grid, use the helper functions in the grid creation.
... -- Remove all grid items that were created in the project or by the earlier -- executions of the script. grid:removeAllChildren() -- Create a random permutation. local permutation = createArray(PieceCount) shuffleArray(permutation) -- Ensure that the permutation is a solvable puzzle. makeSolvable(permutation) ...
Modify the part of the script that populates the grid so that it applies the permutation.
... -- Create the grid children. for i = 1,PieceCount do -- Create a grid item. local piece = piecePrefab:instantiate("piece_" .. i) -- Assign the number to the piece. piece:setProperty(PieceIndexProperty, i) -- Set the grid coordinates of the new node. local p = permutation[i] -- Use integer division to get the row index and modulo to get the column index. local row = (p-1) // ColumnCount local column = (p-1) % ColumnCount ...
When you save the script and in the Preview click
, the script populates the grid with 15 pieces in random order.