【農家は Replace() されました】第12回 関数|ギャルから学ぶドローン農業【超初心者向け攻略】

当記事はChatGPTが出力した文章を使用しています。

 

このゲームの関連記事

www.himajin-block30.com

 

前回

www.himajin-block30.com

 

関数は“コードを部品化して使い回す”魔法

ギャル視点で、ゲームに即効く形でまとめ&実例置いてくね。


関数ってなに?(超要約)

  • 名前のついたミニプログラム

  • 呼ぶたびに同じ仕事をしてくれる。

  • 引数=材料を渡す/戻り値=結果を返す。

def move_n_dir(n, dir):        # ← 関数の定義(名前・引数)
    for _ in range(n):
        move(dir)              # ← 仕事
# 使う
move_n_dir(3, North)           # ← 呼び出し(カッコ必須!)

戻り値(return)

  • returnすると結果が呼び出し元に“返る”よ。

  • 返さないときは暗黙に“何もない値(None)”になる。

def at_top(size):
    return get_pos_y() == size - 1  # True/False を返す

コツ:条件判定は関数にして名前をつけると読みやすさ爆上がり✨


デフォルト引数(お好み設定の初期値)

  • 省略されたときの標準値を用意できる。

def wait_ticks(n=0):
    for _ in range(n):
        do_a_flip()
# wait_ticks() でも OK(0tick待ち)
# wait_ticks(2) なら2tick待つ

“高レベル関数”の使い方(関数を渡す)

  • 関数も“値”だから引数として渡せるのね。汎用化できて超便利。

def repeat(n, action, arg=None):
    for _ in range(n):
        if arg is None:
            action()
        else:
            action(arg)

repeat(3, move, North)   # move(North) を3回
repeat(2, do_a_flip)     # do_a_flip() を2回

注意:repeat(3, move(North)) はダメ。「関数そのもの」を渡したいから moveNorth を別々に渡すのが正解。


スコープ(届く/届かないの話)

  • 関数の中で作った変数はその中だけ有効(ローカル)。

  • 外側の値を読むのはOK(書き換えは注意)。

  • 迷ったら「必要な値は引数で渡す」が安全だよ👌


実戦テンプレ3つ(コピペで強い)

1) 作業を部品化(草/茂み/ニンジン)

def do_grass():
    if can_harvest():
        harvest()

def do_bush():
    if can_harvest():
        harvest()
        plant(Entities.Bush)
    elif get_entity_type() is None:
        plant(Entities.Bush)

def do_carrot():
    if can_harvest():
        harvest()
    if get_entity_type() is None:              # 空なら植え戻し
        if get_ground_type() == Grounds.Grassland:
            till()
        if num_items(Items.Hay) >= 1 and num_items(Items.Wood) >= 1:
            plant(Entities.Carrot)

2) 列の役割スイッチャー(1列目=🥕 2列目=🌳 3列目=🌿)

lanes = [do_carrot, do_bush, do_grass]

def do_job_for_current_tile():
    x = get_pos_x()
    job = lanes[x % len(lanes)]   # いまの列の仕事関数を選ぶ
    job()                         # 実行!

3) “縦スネーク”1歩進める関数(フラグを返す)

端ガード付きで1tickだけ移動し、次の向きフラグを戻り値で返す

def snake_step(size, going_right, going_up):
    x = get_pos_x(); y = get_pos_y()

    if going_up:
        if y == size - 1:
            if going_right:
                if x == size - 1:
                    going_right = False
                    move(West)
                else:
                    move(East)
            else:
                if x == 0:
                    going_right = True
                    move(East)
                else:
                    move(West)
            going_up = False
        else:
            move(North)
    else:
        if y == 0:
            if going_right:
                if x == size - 1:
                    going_right = False
                    move(West)
                else:
                    move(East)
            else:
                if x == 0:
                    going_right = True
                    move(East)
                else:
                    move(West)
            going_up = True
        else:
            move(South)

    return going_right, going_up   # 方向フラグを返す

使い方(本体は超スッキリに)

size = get_world_size()
going_right, going_up = True, True

while True:
    do_job_for_current_tile()                      # そのマスの仕事を実行
    going_right, going_up = snake_step(size, going_right, going_up)  # 1歩進む

 

いい質問〜!結論👉 1)・2)・3)は“役割分担した部品”で、基本はぜんぶ組み合わせて使うのがオススメ💅

  • 1) 作業部品 … そのマスで何をするか(草/茂み/ニンジン)

  • 2) 列スイッチャー … いまの“列”に合わせて、どの作業部品を呼ぶか決める

  • 3) 移動エンジン … 端ガード付きで“1歩だけ”縦スネーク移動させる
    この3つをメインループで配線すると、読みやすくて壊れにくい永久運転になるの🧩


フル配線版(そのまま動かせる統合形)

# ── 1) 作業部品 ──────────────────────────
def do_grass():
    if can_harvest():
        harvest()

def do_bush():
    if can_harvest():
        harvest()
        plant(Entities.Bush)
    elif get_entity_type() == None:    # 環境によっては is None でもOK
        plant(Entities.Bush)

def do_carrot():
    if can_harvest():
        harvest()
        if get_ground_type() == Grounds.Grassland:
            till()                     # 必要時だけ耕す(トグル事故回避)
        if num_items(Items.Hay) >= 1 and num_items(Items.Wood) >= 1:
            plant(Entities.Carrot)
    elif get_entity_type() == None:    # 初回の空きタイル対策(資材があるときだけ)
        if get_ground_type() == Grounds.Grassland:
            till()
        if num_items(Items.Hay) >= 1 and num_items(Items.Wood) >= 1:
            plant(Entities.Carrot)

# ── 2) 列スイッチャー ────────────────────────
lanes = [do_carrot, do_bush, do_grass]   # 1列目=🥕 2列目=🌳 3列目=🌿 の順に循環

def do_job_for_current_tile():
    x = get_pos_x()
    job = lanes[x % len(lanes)]          # 現在列の担当作業を決定
    job()                                # 実行!

# ── 3) 移動エンジン(端ガード付き・1歩だけ進む) ───────
def snake_step(size, going_right, going_up):
    x = get_pos_x(); y = get_pos_y()
    if going_up:
        if y == size - 1:
            if going_right:
                if x == size - 1:
                    going_right = False
                    move(West)
                else:
                    move(East)
            else:
                if x == 0:
                    going_right = True
                    move(East)
                else:
                    move(West)
            going_up = False
        else:
            move(North)
    else:
        if y == 0:
            if going_right:
                if x == size - 1:
                    going_right = False
                    move(West)
                else:
                    move(East)
            else:
                if x == 0:
                    going_right = True
                    move(East)
                else:
                    move(West)
            going_up = True
        else:
            move(South)
    return going_right, going_up

# ── メイン(配線) ───────────────────────────
size = get_world_size()
going_right, going_up = True, True

while True:
    do_job_for_current_tile()                       # そのマスでの作業
    going_right, going_up = snake_step(size, going_right, going_up)  # 1歩だけ移動

どうして“分けて”使うの?

  • 読みやすい:仕事・選択・移動が混ざらないから、後で見返しても一発で分かる👌

  • 差し替えが楽:列の配分を変えたい時は lanes = [...] だけ触ればOK(例:木不足なら [do_carrot, do_bush, do_bush])。

  • 再利用しやすい:移動はそのままで「行ベースにしたい」「待ちtick入れたい」なども 3) だけ直せば済む。


じゃあ“まとめない”ケースは?

  • 今日は草だけ刈りたいみたいな超単純運用なら、1)の一個を直接書き込んでもOK。

  • でも長期運転調整拡張を考えるなら、3部品に分けて使うのが結局ラクだよ💪

よくあるつまずき💣

  • カッコ忘れmovemove() は別物!呼ぶ時は必ず ()

  • インデント:関数内は1段深く。Tab/Space混在はエラー。

  • 戻り値の受け取り忘れa, b = f() みたいにちゃんと左側に受ける

  • デフォルト引数の順序:デフォルトありは後ろ側に置く。

  • 重複呼び出し:毎tick同じ重い処理を何度も呼ばない(size = get_world_size() は外に出して共有が◎)。


まとめ(ギャル要点)

  • 関数=名前のついた仕事

  • 引数で材料を渡しreturnで結果を返す

  • “判定”“作業”“移動 1歩”を分けて関数化すると、読みやすくてミスらない。

  • 高機能はあとから足すだけで全体が育つのが関数の強み✨

 

 

 

続き

 

 

 

このゲームの関連記事

www.himajin-block30.com