A similar answer that utilizes Blender's Mathutils' Vector length property (prevents you from needing to calculate distances in all 3 axes individually):
import bpy
from random import random
from mathutils import Vector
cubeRadius = 0.25
maxIterations = 1000 # Max iterations to prevent while loop from running forever
# min and max values for each axis for the random numbers
ranges = {
'x' : { 'min' : -10, 'max' : 10 },
'y' : { 'min' : -10, 'max' : 10 },
'z' : { 'min' : -10, 'max' : 10 }
}
# Generates a random number within the axis minmax range
randLocInRange = lambda axis: ranges[axis]['min'] + random() * ( ranges[axis]['max'] - ranges[axis]['min'] )
size = 250 # Number of cubes
cubes = [] # Cube coordinates list
loopIterations = 0
while len( cubes ) < size and loopIterations < maxIterations:
loopIterations += 1
# Generate a random 3D coordinate
loc = Vector([ randLocInRange( axis ) for axis in ranges.keys() ])
if len( cubes ) > 0:
# Search for overlapping points (within the cube radius radius)
overlappingPoints = [ p for p in cubes if ( p - loc ).length < cubeRadius * 2 ]
# if any found, skip this location
if overlappingPoints: continue
# Add coordinate to cube list
cubes.append( loc )
# Add the first cube (others will be duplicated from it)
# Note: in blender 2.8 size arg is used instead of radius
bpy.ops.mesh.primitive_cube_add( radius = cubeRadius, location = cubes[0] )
cube = bpy.context.scene.objects['Cube']
# Add all other cubes
for c in cubes[1:]:
dupliCube = cube.copy()
dupliCube.location = c
bpy.context.scene.objects.link( dupliCube )
# in blender 2.8 an api change requires to use the collection instead of the scene
# bpy.context.collection.objects.link(dupliCube)