2

タプルの値がウェイポイントのリストの次の値と比較してどのように増加または減少するかを調べることにより、座標系を移動するときにどちらの方向を向いているかを確認するためのこの関数があります。コードを見ると、複雑でぎこちなく感じます。

a.facing = self.direction(a.travel_list[0], a.travel_list[1])

def direction(self, start, end):
    s_width = start[0]
    s_height = start[1]
    e_width = end[0]
    e_height = end[1]
    # check directions
    if s_height < e_height:
        if s_width < e_width:
            return 'right'
        elif s_width > e_width:
            return 'up'
        else:
            return 'up_right'

    elif s_height > e_height:
        if s_width < e_width:
            return 'down'
        elif s_width > e_width:
            return 'left'
        else:
            return 'down_left'

    elif s_height == e_height and s_width < e_width:
        return 'down_right'
    else:
        return 'up_left'

戻り値は、時計回りに 1 ステップ回転するように調整されます。私の質問は、関数をより短く効率的にするためにコードをどのように変更できるかということです。

編集: 移動は指定された 8 方向でのみ発生することに注意してください。

4

5 に答える 5

4

cmp()の戻り値に基づく辞書を使用します。

def direction(self, start, end):
    return table[cmp(start[0], end[0]), cmp(start[1], end[1])]

ディクショナリを構築して、現在のロジックを要約します。

table = {
    (-1, -1): 'right',
    (-1, 1):  'up',
    (-1, 0):  'up_right',
       ...
}

Python 3 を使用している場合は、独自のcmp()関数を次のように定義する必要があります。

cmp = lambda x, y:  -1 if x < y else 1 if x > y else 0
于 2013-01-24T04:05:19.977 に答える
2

関数を少し変更すると、単純な関数定義で方向のリストを返すことができます:

def direction(self, start, end):
    delta = (end[0] - start[0], end[1] - start[1])

    s = []

    if delta[1]>0 : s.append("up")
    elif delta[1]<0 : s.append("down")

    if delta[0]>0 : s.append("right")
    elif delta[0]<0 : s.append("left")

    return s

ここで、移動の方向に応じて、s には 0、1、または 2 メンバーが含まれます。移動がない場合、リストは空になります。

指定した形式の戻り値が特に必要な場合は、リストから値を抽出し、必要に応じて解析するだけです。


時計回りのシフトの必要性を完全には理解していませんが、それが変更できない場合は、最初にプレースホルダーとしてより短い/単純な値を使用し、次に辞書を使用してプレースホルダーを目的のテキストに置き換えることと、時計回りのシフト。

于 2013-01-24T04:11:23.017 に答える
1

ステップ 1: y と x の距離を取得する

ステップ 2: atan2(x, y) を呼び出して角度を取得します ( http://docs.python.org/2/library/math.html#math.atan2 )

ステップ 3: pi/4 で割り、最も近い整数に丸めて -4 ~ 4 の値を取得する

ステップ 4: これで、ケース/スイッチを実行できます。これらの値のそれぞれは、異なる基本方向になります (-4 と 4 は同じ方向になります。たとえば、両方とも東になります)。

編集:これは、たとえば東よりも 10 度高いと考えた場合にのみ機能することに気付きました。XD もっと良いものを考えさせてください...

編集2:わかりました、これを試してください:

ステップ 1: 2 つの値のタプルを作成する

ステップ 2: 値 1 = cmp(x1, x2)

ステップ 3: 値 2 = cmp(y1, y2)

ステップ 4: タプルのテーブルで方向を検索し (例: 0,1 は北、0,-1 は南、1,1 は北東など)、結果を返します。

于 2013-01-24T04:03:53.970 に答える
0

元のコードが正しければ、マッピングについて私が理解できないことがあります。開始が(幅、高さ)であると仮定すると、または以下で使用するように(x、y)であり、xが右に増加し、yが増加すると仮定します(数学では通常の場合ですが、要件は少し異なります)、これが終了が開始に対して相対的な場所を示す簡潔な方法です(文字列名のセットを使用して):

DIR_STR_LIST  = ("up", "down", "right", "left")

def direction3((sx, sy), (ex, ey)):
    conds = (sy < ey, ey < sy, sx < ex, ex < sx)
    istr = DIR_STR_LIST.__iter__()
    return '_'.join([istr.next() for c in conds if c or not istr.next()])

falseのor not istr.next()場合、イテレータを進めるために必要です。c

これ簡潔ですが、私が望むよりも少し醜いです。元のコードよりもパフォーマンスが向上する可能性があると思いましたが(リスト内包表記が高速であるため)、これはパフォーマンスにとって単純さが優れている場合です。元のコードは5倍高速です(痛い!)。

于 2013-01-24T06:15:39.977 に答える
0

and次の演算子を使用できます。

a.facing = self.direction(a.travel_list[0], a.travel_list[1])

def direction(self, start, end):
    s_width, s_height, e_width, e_height = start[0], start[1], end[0], end[1]
    # multiple assignments
    # check directions
    if s_height < e_height and s_width < e_width:
        return 'right' 
    elif s_height < e_height and s_width > e_width:
        return 'up'
    elif s_height < e_height: # this will get executed if the top two are false
        return 'up_right'     # its similar to using the `else` in a nested conditional
    elif s_height > e_height and s_width < e_width:
        return 'down'
    elif s_height > e_height and s_width > e_width:
        return 'left'
    elif s_height > e_height:
        return 'down_left'
    elif s_height == e_height and s_width < e_width:
        return 'down_right'
    else:
        return 'up_left'
于 2013-01-24T04:09:06.233 に答える