Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Generate a rand array,please help! solved — Gideros Forum

Generate a rand array,please help! solved

alexzhengalexzheng Guru
edited March 2013 in General questions
I use this to generate a rand rows * columns array filled with random number from 1,2,3.
However I got stuck on how to make sure no 3 or more cells with the same value connected horizontally or vertically.
For example the following array filled with 4 numbers of '1' in row 9.

Any good ideas?

1 2 0 2 3 1 3 2 1 0
3 2 3 1 1 2 3 3 2 1
3 0 2 1 3 3 1 1 3 2
2 2 1 0 0 3 0 0 1 0
3 3 1 3 2 1 1 2 2 0
0 1 3 0 1 2 0 3 0 0
1 0 3 3 3 3 1 0 3 0
1 3 0 3 1 2 1 3 1 1
3 3 1 1 1 1 2 1 3 1
3 3 1 2 1 0 2 1 1 0
 
---create an rand rows * columns array filled with 1,2,3 in num cells  
local function randarray(rows, columns, num)
	math.randomseed(os.time())
 
	local array = {}
	local tmp = {}
 
	for i = 1, rows do
		tmp[i] = {}
		array[i] = {}
		for j = 1, columns do
			tmp[i][j] = {i, j}
			array[i][j] = 0
		end
	end
 
	for k = 1, num do
		local r = math.random(#tmp)
		local c = math.random(#tmp[r])
		--print(r..'|'..c)
 
		local r1, c1 = tmp[r][c][1], tmp[r][c][2],
 
		table.remove(tmp[r], c)
		if #tmp[r] == 0 then
			table.remove(tmp, r)
		end
 
		array[r1][c1] = math.random(3)
	end
 
	for i = 1, #array do
		print(unpack(array[i]))
	end
 
 
end
 
randarray(10, 10, 80)

Comments

  • Once you've generated the array, you need to "post process" it repeatedly until it passes the "no matching tiles" rule.

    To do that - run over the array and then for each cell, check it's (potentially) four neighbours, the easiest way is to call a function that just moves along the array in the given direction returning the number of continuous matches, if they are >= 3 then you have to change the value (ideally pick one that isn't one of the four neighbours) and start again at the beginning.

    Obviously when you can process the entire table and each function returns < 3 matches your job is done.

    It may take a few dozen iterations to get right to the end of the table, but considering the speed of Gideros you won't notice it.
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • alexzhengalexzheng Guru
    edited March 2013
    That 's the most straight way that I though of at first,but after replace one with another value, it may produce anorther mathch, and I'm afraid it will be endless in worst case.
    May be any clever way can do.
  • atilimatilim Maintainer
    If you have 4 different values (like 1, 2, 3, 4) instead of 3 (1, 2, 3), you can make sure that, your replacement doesn't produce another match. But I think with 3 values, it's hard to do.
  • alexzhengalexzheng Guru
    edited March 2013
    finally, I get what I expected,I checked each value before assign it and drop the cell if none of the value can be used.
     
    local function checkChain(array, row, column)
    	local paths = {
    		{{1, 0}, {-1, 0}},
    		{{0, 1}, {0, -1}},
    	}
     
    	local values = {1, 2, 3}
     
    	local rand1, rand2 = math.random(#values), math.random(#values)
    	values[rand1], values[rand2] = values[rand2], values[rand1]
     
    	for index = 1, #values do
    		local value = values[index]
    		local canUse = true
    		for i = 1, #paths do
    			local path = paths[i]
    			local set = {}
    			for j = 1, #path do
    				local r, c 
    				r, c = row + path[j][1], column + path[j][2]
     
    				local value2 = array[r] and array[r][c] 
    				while value == value2 do
    					set[#set + 1] = value2
    					r, c = r + path[j][1], c + path[j][2]
    					value2 = array[r] and array[r][c] 
    				end
    			end
     
    			if #set > 1 then
    				canUse = false
    			end	
    		end
     
    		if canUse then
    			return value
    		end
     
    	end
     
    	return nil
     
    end
     
    local function randarray(rows, columns, num)
    	math.randomseed(os.time())
     
    	local array = {}
    	local tmp = {}
     
    	for i = 1, rows do
    		tmp[i] = {}
    		array[i] = {}
    		for j = 1, columns do
    			tmp[i][j] = {i, j}
    			array[i][j] = 0
    		end
    	end
     
    	local count = 0
     
    	local total = rows * columns
    	for k = 1, total do
    		local r = math.random(#tmp)
    		local c = math.random(#tmp[r])
    		--print(r..'|'..c)
     
    		local r1, c1 = tmp[r][c][1], tmp[r][c][2],
     
    		table.remove(tmp[r], c)
    		if #tmp[r] == 0 then
    			table.remove(tmp, r)
    		end
     
     
    		local value = checkChain(array, r1, c1)
     
    		if value then
    			array[r1][c1] = value
    			count = count + 1
     
    			if count >= num then
    				break
    			end
    		end
    	end
     
    	print('---------------------------------------')
     
    	for i = 1, #array do
    		print(unpack(array[i]))
    	end
     
    	print('---------------------------------------')
     
     
    end
     
    for i = 1, 10 do
    	randarray(10, 10, 80)
     
     
    end
Sign In or Register to comment.