chapter 10: Minecraft Magic with for Loops

10.1 A Simple for Loop

리스트에서 아이템을 꺼내 오는 예제를 보자

noodleSoup = ["water", "soy sauce", "spring onions", "pepper", "noodles",
"beef", "vegetables"]


for ingredient in noodleSoup:
print(ingredient)

Mission #55: Magic Wand

9장에서 pollBlockHits() 함수를 이용했다. 이 함수를 이용해서 다음 코드를 실행해 보자. 실행한 모든 블럭이 다른 블럭으로 변하게 된다.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()

import time

time.sleep(60)

hits = mc.events.pollBlockHits()
block = 103

for hit in hits:
    x, y, z = hit.pos.x, hit.pos.y, hit.pos.z
    mc.setBlock(x, y, z, block)

Mission #56: Magic Stairs

다음 미션을 수행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()

pos = mc.player.getTilePos()
x, y, z = pos.x, pos.y, pos.z

stairBlock = 53

for step in range(10):
    mc.setBlock(x + step, y + step, z, stairBlock)

Playing Around with range()

다음을 입력해 보자.

>>> aRange = range(5)
>>> list(aRange)
[0, 1, 2, 3, 4]

>>> aRange = range(2, 5)
>>> list(aRange)
[2, 3, 4]

>>> aRange = range(3, 10, 2)
>>> list(aRange)
[3, 5, 7, 9]

>>> newRange = range(100, 0, -2)
>>> list(newRange)
[100, 98, 96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76, 74, 72, 70, 68, 66, 64,
62, 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26,
24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2]

10.2 Other List Functions

이번에는 reversed() 라는 함수를 익혀 보자.

>>> backwardsList = reversed(aRange)
>>> list(backwardsList)
[9, 7, 5, 3]


countDown = range(1, 101)
countDown = reversed(countDown)
for item in countDown:
print(item)

Mission #57: Pillars

다음 미션을 수행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()


def setPillar(x, y, z, height):
    """Creates a pillar. Args set position and height of pillar"""
    stairBlock = 156
    block = 155

    # Pillar top
    mc.setBlocks(x - 1, y + height, z - 1, x + 1, y + height, z + 1, block, 1)
    mc.setBlock(x - 1, y + height - 1, z, stairBlock, 12)
    mc.setBlock(x + 1, y + height - 1, z, stairBlock, 13)
    mc.setBlock(x, y + height - 1, z + 1, stairBlock, 15)
    mc.setBlock(x, y + height - 1, z - 1, stairBlock, 14)

    # Pillar base
    mc.setBlocks(x - 1, y, z - 1, x + 1, y, z + 1, block, 1)
    mc.setBlock(x - 1, y + 1, z, stairBlock, 0)
    mc.setBlock(x + 1, y + 1, z, stairBlock, 1)
    mc.setBlock(x, y + 1, z + 1, stairBlock, 3)
    mc.setBlock(x, y + 1, z - 1, stairBlock, 2)

    # Pillar column
    mc.setBlocks(x, y, z, x, y + height, z, block, 2)

pos = mc.player.getTilePos()
x, y, z = pos.x + 2, pos.y, pos.z

for xOffset in range(0, 100, 5):
    setPillar(x + xOffset, y, z, 10)

기둥 7개를 그리는 코드이다.

Mission #58: Pyramid

다음 코드를 실행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()


block = 24  # sandstone
height = 10
levels = reversed(range(height))

pos = mc.player.getTilePos()
x, y, z = pos.x + height, pos.y, pos.z

for level in levels:
    mc.setBlocks(x - level, y, z - level, x + level, y, z + level, block)
    y += 1

10.3 Looping Over a Dictionary

Dictionary에 사용되는 loop를 살펴보자.

inventory = {'gems': 5, 'potions': 2, 'boxes': 1}
for key in inventory:
print(key)


gems
potions
boxes


inventory = {'gems': 5, 'potions': 2, 'boxes': 1}
for key in inventory:
print(key + " " + str(inventory[key]))

gems 5
potions 2
boxes 1

Mission #59: Scoreboard

다음 코드를 실행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()

import time

scores = {}

message = ""

while message != "exit":
    print("Click in the Minecraft window")
    time.sleep(10)
    mc.events.clearAll()

    mc.postToChat("Go")

    time.sleep(60)

    hits = mc.events.pollBlockHits()
    numberOfHits = len(hits)
    mc.postToChat("You used your sword " + hits + " times.")

    playerName = input("Enter your name: ")
    scores[playerName] = numberOfHits

    for name in scores:
        print(name + str(scores[name]))

    message = input("Press enter in this window to start ('exit' to quit)")

10.4 for-else Loops.

for else 구문도 가능하다.

sandwich = ["Bread", "Butter", "Tuna", "Lettuce", "Mayonnaise", "Bread"]
for ingredient in sandwich:
    print(ingredient)
else:
    print("This is the end of the sandwich.")

Bread
Butter
Tuna
Lettuce
Mayonnaise
Bread
This is the end of the sandwich.

Breaking a for-else Loop

다음처럼 break문을 써서 빠져 나올 수 있다.

sandwich = ["Bread", "Butter", "Tuna", "Lettuce", "Mayonnaise", "Bread"]
for ingredient in sandwich:
    if ingredient == "Mayonnaise":
        print("I don't like mayonnaise on my sandwich.")
        break
    else:
        print(ingredient)
else:
    print("This is the end of the sandwich.")

Mission #60: The Diamond Prospector

다음 미션을 수행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()

pos = mc.player.getTilePos()
x, y, z = pos.x, pos.y, pos.z

depth = 50

for deep in range(depth):
    block = mc.getBlock(x, y - deep, z)
    if block == 56:
        mc.postToChat("A diamond ore is " + str(deep) + " blocks below you.")
        break
else:
    mc.postToChat("There are no diamond ore blocks below you")

10.5 Nested for Loops and Multidimensional Lists

다음 코드를 실행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()
twoDimensionalRainbowList = [[0, 0, 0],
                             [1, 1, 1],
                             [2, 2, 2],
                             [3, 3, 3],
                             [4, 4, 4],
                             [5, 5, 5]]
pos = mc.player.getTilePos()
x = pos.x
y = pos.y
z = pos.z
startingX = x

mc.player.setTilePos(x+3, y, z+3)

for row in twoDimensionalRainbowList:
    for color in row:
        mc.setBlock(x, y, z, 35, color)
        x += 1
    y += 1
    x = startingX

Accessing Values in 2D Lists

1차원 리스트는 다음처럼 하면 된다.

scores = [1, 5, 6, 1]
scores[2] = 7

2차원 이상은 다음처럼 하면 된다.

twoDimensionalRainbowList = [[0, 0, 0],
                             [1, 1, 1},
                             [2, 2, 2],
                             [3, 3, 3],
                             [4, 4, 4],
                             [5, 5, 5]]


twoDimensionalRainbowList[0][1] = 7

Mission #61: Pixel Art

다음 코드를 실행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()

pos = mc.player.getTilePos()
x, y, z = pos.x, pos.y, pos.z

mc.player.setTilePos(x+3, y, z+3)

blocks = [[35, 35, 22, 22, 22, 22, 35, 35],
          [35, 22, 35, 35, 35, 35, 22, 35],
          [22, 35, 22, 35, 35, 22, 35, 22],
          [22, 35, 35, 35, 35, 35, 35, 22],
          [22, 35, 22, 35, 35, 22, 35, 22],
          [22, 35, 35, 22, 22, 35, 35, 22],
          [35, 22, 35, 35, 35, 35, 22, 35],
          [35, 35, 22, 22, 22, 22, 35, 35]]

for row in reversed(blocks):
    for block in row:
        mc.setBlock(x, y, z, block)
        x += 1
    y += 1
    x = pos.x

Generating 2D Lists with Loops

다음을 실행해 보자.

import random
    randomNumbers = []
for outer in range(10):
    randomNumbers.append([])
for inner in range(10):
    number = random.randint(1, 4)
randomNumbers[outer].append(number)
print(randomNumbers)


[[3, 1, 4, 1, 4, 1, 2, 3, 2, 2],
[1, 3, 4, 2, 4, 3, 4, 1, 3, 2],
[4, 2, 4, 1, 4, 3, 2, 3, 4, 4],
[1, 4, 3, 4, 3, 4, 3, 3, 4, 4],
[3, 1, 4, 2, 3, 3, 3, 1, 4, 2],
[4, 1, 4, 2, 3, 2, 4, 3, 3, 1],
[2, 4, 2, 1, 2, 1, 4, 2, 4, 3],
[3, 1, 3, 4, 1, 4, 2, 2, 4, 1],
[4, 3, 1, 2, 4, 2, 2, 3, 1, 2],
[3, 1, 3, 3, 1, 3, 1, 4, 1, 2]]

Mission #62: A Weather-Worn Wall

다음 코드를 실행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()

import random


def brokenBlock():
    brokenBlocks = [48, 67, 4, 4, 4, 4]
    block = random.choice(brokenBlocks)
    return block

pos = mc.player.getTilePos()
x, y, z = pos.x, pos.y, pos.z
mc.player.setTilePos(x+3, y, z+3)
brokenWall = []
height, width = 5, 10

# create the list of broken blocks
for row in range(height):
    brokenWall.append([])
    for column in range(width):
        block = brokenBlock()
        brokenWall[row].append(block)

# set the blocks
for row in brokenWall:
    for block in row:
        mc.setBlock(x, y, z, block)
        x += 1
    y += 1
    x = pos.x

Outputting 3D Lists

다음 코드를 실행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()
pos = mc.player.getTilePos()
x = pos.x
y = pos.y
z = pos.z
mc.player.setTilePos(x+10, y, z+10)

cube = [[[57, 57, 57, 57], [57, 0, 0, 57], [57, 0, 0, 57], [57, 57, 57, 57]],
        [[57, 0, 0, 57], [0, 0, 0, 0], [0, 0, 0, 0], [57, 0, 0, 57]],
        [[57, 0, 0, 57], [0, 0, 0, 0], [0, 0, 0, 0], [57, 0, 0, 57]],
        [[57, 57, 57, 57], [57, 0, 0, 57], [57, 0, 0, 57], [57, 57, 57, 57]]]
startingX = x
startingY = y

for depth in cube:
    for height in reversed(depth):
        for block in height:
            mc.setBlock(x, y, z, block)
            x += 1
        y += 1
        x = startingX
    z += 1
    y = startingY

Accessing Values in 3D Lists

cube = [[[57, 57, 57, 57],
[57, 0, 0, 57],
[57, 0, 0, 57],
[57, 57, 57, 57]],
#
[[57, 0, 0, 57],
[0, 0, 0, 0],
[0, 0, 0, 0],
[57, 0, 0, 57]],
#
[[57, 0, 0, 57],
[0, 0, 0, 0],
[0, 0, 0, 0],
[57, 0, 0, 57]],
#
[[57, 57, 57, 57],
[57, 0, 0, 57],
[57, 0, 0, 57],
[57, 57, 57, 57]]]

cube[0] 이면

[[57, 57, 57, 57],
[57, 0, 0, 57],
[57, 0, 0, 57],
[57, 57, 57, 57]]

cube[0][3]

[57, 57, 57, 57]

cube[0][3][3] = 41 처럼 변경할 수 있다.

Mission #63: Duplicate a Building

다음 코드를 실행해 보자.

from mcpi.minecraft import Minecraft
mc = Minecraft.create()


def sortPair(val1, val2):
    if val1 > val2:
        return val2, val1
    else:
        return val1, val2


def copyStructure(x1, y1, z1, x2, y2, z2):
    x1, x2 = sortPair(x1, x2)
    y1, y2 = sortPair(y1, y2)
    z1, z2 = sortPair(z1, z2)

    width = x2 - x1
    height = y2 - y1
    length = z2 - z1

    structure = []

    print("Please wait...")

    # Copy the structure
    for row in range(height):
        structure.append([])
        for column in range(width):
            structure[row].append([])
            for depth in range(length):
                block = mc.getBlock(x1 + column, y1 + row, z1 + depth)
                structure[row][column].append(block)

    return structure


def buildStructure(x, y, z, structure):
    xStart = x
    yStart = y
    for row in structure:
        for column in row:
            for block in column:
                mc.setBlock(x, y, z, block)
                z += 1
            x += 1
            z = yStart
        y += 1
        x = xStart


# get the position of the first corner
input("Move to the first corner and press enter in this window")
pos = mc.player.getTilePos()
x1, y1, z1 = pos.x, pos.y, pos.z

# get the position of the second corner
input("Move to the opposite corner and press enter in this window")
pos = mc.player.getTilePos()
x2, y2, z2 = pos.x, pos.y, pos.z

# copy the building
structure = copyStructure(x1, y1, z1, x2, y2, z2)

# get the position for the copy
input("Move to the position you want to create the structure and press ENTER in this window")
pos = mc.player.getTilePos()
x, y, z = pos.x, pos.y, pos.z
buildStructure(x, y, z, structure)

10.6 What You Learned

for loops with lists range() function more about for loops lists, such as reversing lists, looping over dictionaries, and breaking for loops

two- and threedimensional lists with nested loops