Minecraft Menger Sponge – STEAM project.

What has zero volume and an infinite surface area? A Menger Sponge of course. If your child is a Minecraft fan like my 7 year old, then this simple fractal can be used to make a good afternoon STEAM project that teaches math and programming concepts. (Note you should already know how to modify Minecraft code. That would take more than afternoon to get a grip on. And of course you should know Java).

First we built a Level 1 Menger cube with snap cubes. Then we came up with the X,Y, and Z coordinates for each of the 20 blocks that make up the Level 1 cube. This was a major goal of our project: increased fluency with 3-d coordinates.

Screen Shot 2014-11-11 at 11.51.32 PM

Then it was not a difficult leap to see how our Java code used these 20 coordinates to place blocks.

    public static void drawblock(World world, int x, int y, int z, int startx, int starty, int startz) {
        int metadata = world.getBlockMetadata(x, y, z);
        Block block = Block.getBlockById(35);
        boolean res = world.setBlock(startx + x, starty + y, startz +  z+5, block, metadata, 3);
        System.out.println("Placing block at " + x + "," + y + ", res = " + res);
    }
    public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World world,
                             int startx, int starty, int startz, int par7, float par8, float par9, float par10) {

        Menger1Item.drawLevel1Cube(world, startx, starty, startz);
        return true;
    }
    public static void drawLevel1Cube(World world, int startx, int starty, int startz) {
        drawblock(world, 0, 0, 0, startx, starty, startz);
        drawblock(world, 1, 0, 0, startx, starty, startz);
        drawblock(world, 2, 0, 0, startx, starty, startz);
        drawblock(world, 0, 1, 0, startx, starty, startz);
        drawblock(world, 2, 1, 0, startx, starty, startz);
        drawblock(world, 0, 2, 0, startx, starty, startz);
        drawblock(world, 1, 2, 0, startx, starty, startz);
        drawblock(world, 2, 2, 0, startx, starty, startz);

        drawblock(world, 0, 0, 1, startx, starty, startz);
        drawblock(world, 0, 2, 1, startx, starty, startz);
        drawblock(world, 2, 0, 1, startx, starty, startz);
        drawblock(world, 2, 2, 1, startx, starty, startz);

        drawblock(world, 0, 0, 2, startx, starty, startz);
        drawblock(world, 1, 0, 2, startx, starty, startz);
        drawblock(world, 2, 0, 2, startx, starty, startz);
        drawblock(world, 0, 1, 2, startx, starty, startz);
        drawblock(world, 2, 1, 2, startx, starty, startz);
        drawblock(world, 0, 2, 2, startx, starty, startz);
        drawblock(world, 1, 2, 2, startx, starty, startz);
        drawblock(world, 2, 2, 2, startx, starty, startz);
    }

Here is the Level 1 Cube in Minecraft:

Level1

At this point we wanted to make higher level cubes. A simple recursive algorithm was called for. This was too much for my son, not surprisingly. It is excerpted below if you want to do something similar. The main concept I tried to convey was that each level was a new power of 20.

Level 1 = 20^1 = 20. Length of side: 3 blocks.
Level 2 = 20^2 = 400. Length of side: 9 blocks.
Level 3 = 20^3 = 8000. Length of side: 27 blocks.
Level 4 = 20^4 = 160,000. Length of side: 81 blocks.
Level 5 = 20^5 = 3,200,000. Length of side 243 blocks.
At this point you could point out how the volume is shrinking with each level. E.g: 400/9^3 < 3200000/243^3. Over time the volume will approach zero! Ah, the mysteries of fractals and limits. Back to the concrete: We started with a level 2 cube. Exploring this next level up was important to understand recursion. My son kindly illuminated the structure with torches as night fell: Level2Night

We skipped right to Level 4 which was beautiful and impressive. When night fell in our Minecraft world, the local wild-life (mobs) colonized our structure and served to give a nice sense of scale and depth.

Level3

Level3Mobs

Level3Sunrise

Take a tour of this level 4 Menger Cube:

Level 4 Menger Cube from Robert Woodley on Vimeo.

Could Minecraft handle a Level 5 cube? That was the question on our minds. 3,200,000 blocks. It took about 5 minutes and the laptop labored mightily. But it worked! There were nice glitch effects as Minecraft struggled to build out the structure. Also the top was truncated as Minecraft prevented us from going into outer space.

sunrise

This incredible fractal structure is best understood through video:

Level 5 Menger Cube in Minecraft from Robert Woodley on Vimeo.

Complete Java class to build a level 5 Menger Cube:

package com.example.examplemod;

import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;

public class Menger1Item extends Item {

    public Menger1Item() {
        setMaxStackSize(64);
        setCreativeTab(CreativeTabs.tabMisc);
        setUnlocalizedName("MengaLevel1Cube");
    }
    public static void drawblock(World world, int x, int y, int z, int startx, int starty, int startz) {
        int metadata = world.getBlockMetadata(x, y, z);
        Block block = Block.getBlockById(35);
        boolean res = world.setBlock(startx + x, starty + y, startz +  z+5, block, metadata, 3);
        System.out.println("Placing block at " + x + "," + y + ", res = " + res);
    }
    public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World world,
                             int startx, int starty, int startz, int par7, float par8, float par9, float par10) {

        Menger1Item.drawLevel1Cube(world, startx, starty, startz);
        return true;
    }
    public static void drawLevel1Cube(World world, int startx, int starty, int startz) {
        int[][] i5coords = returnCoords(81);
        for (int i5 = 0; i5 < 20; i5++) {
            int[][] i4coords = returnCoords(27);
            for (int i4 = 0; i4 < 20; i4++) {
                int[][] i3coords = returnCoords(9);
                for (int i3 = 0; i3 < 20; i3++) {
                    int[][] i2coords = returnCoords(3);
                    for (int i2 = 0; i2 < 20; i2++) {
                        int[][] coords = returnCoords(1);
                        for (int i1 = 0; i1 < 20; i1++) {
                            drawblock(world,
                                    i5coords[i5][0] + i4coords[i4][0] + i3coords[i3][0] + i2coords[i2][0] + coords[i1][0],
                                    i5coords[i5][1] + i4coords[i4][1] + i3coords[i3][1] + i2coords[i2][1] + coords[i1][1],
                                    i5coords[i5][2] + i4coords[i4][2] + i3coords[i3][2] + i2coords[i2][2] + coords[i1][2],
                                    startx, starty, startz);
                        }
                    }
                }
            }
        }
    }
    public static int[][] returnCoords(int level) {
        int[][] coords = {
                {0, 0, 0},
                {1, 0, 0},
                {2, 0, 0},
                {0, 1, 0},
                {2, 1, 0},
                {0, 2, 0},
                {1, 2, 0},
                {2, 2, 0},

                {0, 0, 1},
                {0, 2, 1},
                {2, 0, 1},
                {2, 2, 1},

                {0, 0, 2},
                {1, 0, 2},
                {2, 0, 2},
                {0, 1, 2},
                {2, 1, 2},
                {0, 2, 2},
                {1, 2, 2},
                {2, 2, 2},
        };
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 3; j++)
                coords[i][j] *= level;
        }
        return coords;
    }
}

 

2 Responses

  1. Do it on an ultra flat world so you can get the whole level 5 to fit! That would be awesome.

  2. AH, I hadn’t thought of that. I’ll try it with my son this week. Thanks!