1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【2Dプログラミング】「上下左右」の4通りの処理の重複をなくすリファクタリング案

Last updated at Posted at 2023-11-30

Pythonを用いて書いていますが、どの言語にも通底するお話をします。

はじめに

2Dゲームなど、二次元座標を用いてプログラミングするとき、「上下左右」で4回同じようなコードを書いていませんか?

例は何でもいいですが、たとえばこのようなコード。

冗長.py
map = True/Falseの二次配列Trueなら壁があることを表す

#自分から見てdirectionの方向にある壁を探す
def see_wall(position:tuple[int, int], direction):
    if direction == "up":
        #自分から上側へ
        for y in range(position.y, -1, -1):
            if map[position.x][y]:
                return (position.x, y)

    elif direction == "down":
        #自分から下側へ
        for y in range(position.y, len(map[0])):
            if map[position.x][y]:
                return (position.x, y)

    elif direction == "right":
        #自分から右側へ
        for x in range(position.x, len(map)):
            if map[x][position.y]:
                return (x, position.y)

    elif direction == "left":
        #自分から左側へ
        for x in range(position.x, -1, -1):
            if map[x][position.y]:
                return (x, position.y)

    #ここまで来たら、壁がなかったということ
    return None

上下左右で4回同じコードを書いていますね。冗長ですね。もし修正しようとしたら4か所修正しないといけなくなりメンドウですね。

ベクトルを使いましょう

ベクトル を使いましょう。
ベクトルは高校生の数学でやるものですが、簡単に言うと「方向を表すタプル」です。(タプルはプログラミング用語です。タプルが分からない場合はリストと考えてください)

行きたい方向とその距離を、(x, y)のようにまとめてタプルにします。すると4つの処理を簡単にまとめることができます。

おそらく、説明するよりも実際に見せた方が早いです。ごらんあれ。

ベクトル使った.py
def see_wall(position:tuple[int, int], direction):
    #ベクトルを設定
    vector = (0, 0)
    if direction == "up":
        #自分から上側へ
        vector = (0, -1)

    if direction == "down":
        #自分から下側へ
       vector = (0, 1)

    if direction == "right":
        #自分から右側へ
        vector = (1, 0)

    if direction == "left":
        #自分から左側へ
        vector = (-1, 0)

    #見る
    #x, yがマップ内にいる限りループ
    x, y = position
    while is_in_area(x, y):
        #確認
        if map[x][y]:
            return (x, y)

        #移動
        x += vector[0]
        y += vector[1]

    #ここまで来たら、壁がなかったということ
    return None

#マップ内にいるかを判定
def is_in_area(x, y):
    if (0 <= x <= len(map))
        and (0 <= y <= len(map[0])):
        return True
    else:
        return False

どうですか。一つにまとまり、スッキリしましたね。

  • 行きたい方向と量をvector(タプル)に登録
  • 「範囲内にいるとき」という条件でwhile
  • vectorに登録した分だけ移動するには、x, yにそれぞれ足し算

というわけです。

最後に

いいね頂けると泣きながら喜びます><

この記事を読んでいる方は、次の記事も読んでいるのかもしれません:

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?