tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトル時計回りの座標移動アルゴリズム
記事No14946
投稿日: 2010/09/30(Thu) 18:21
投稿者にっちも
【VB 6.0】
【OS WinXP】

プログラマー1年目です。

X軸/Y軸それぞれ-5から+5までの座標で、(-5,-5)から(+5,+5)までの25点の座標を、
(0,0)を中心とした時計回りで移動したい。
中心(X0,Y0)⇒右(X1,Y0)⇒下(X1,Y-1)⇒左(X0,Y-1)・・・ といった感じ。

この座標移動のアルゴリズムを考えているのですが、良い案が思いつけず悩んでいます。

座標は相対値なので、今の座標から一つ右に、一つ下に、一つ左に…という移動方法で
行うのですが、うまくループ等の処理でまとめられないでしょうか。

よろしくお願いします。

[ツリー表示へ]
タイトルRe: 渦巻き回りの座標移動アルゴリズム
記事No14947
投稿日: 2010/09/30(Thu) 18:24
投稿者にっちも
失礼します。
タイトルが正しくなかった気がして、修正したいのですが方法が分からず。

ただ単に時計回りではなく、時計回りに渦巻状に移動する方法で悩んでいます。

また、(-5,+5) ではなく、(-4,+4) の25点でした。

よろしくお願いします。

[ツリー表示へ]
タイトルRe^2: 渦巻き回りの座標移動アルゴリズム
記事No14948
投稿日: 2010/09/30(Thu) 20:38
投稿者
> X軸/Y軸それぞれ-5から+5までの座標で、・・・25点の座標を、
> (0,0)を中心とした時計回りで移動したい。

Xが-5〜+5、Yが-5〜+5の時、範囲内の座標は25個どころじゃないというのはさておき…

実際に方眼用紙やExcelで移動経路を描いてみると
どういう増減で移動をしているか分かりやすいと思いますよ。
1,1,2,2,3,3,4,4,…と単純なルールで移動しています。

あくまで1点ずつ移動したいのであれば、
移動している方向と既に通った座標を記憶しておけば
移動の度に右手(移動方向に対して)の座標が既に通った場所かの判断で
直進か右折(移動方向に対して)かを決められると思います。

[ツリー表示へ]
タイトルRe^3: 渦巻き回りの座標移動アルゴリズム
記事No14949
投稿日: 2010/10/01(Fri) 08:26
投稿者にっちも
> 1,1,2,2,3,3,4,4,…と単純なルールで移動しています。
方眼紙に経路を書いてみて、1,12,2,3,3… のルールは見て取れたのですが、

> あくまで1点ずつ移動したいのであれば、
> 移動している方向と既に通った座標を記憶しておけば
> 移動の度に右手(移動方向に対して)の座標が既に通った場所かの判断で
> 直進か右折(移動方向に対して)かを決められると思います。
の部分が理解できずにいます。

さらにアドバイスがあれば、よろしくおねがいします。

[ツリー表示へ]
タイトルRe^4: 渦巻き回りの座標移動アルゴリズム
記事No14950
投稿日: 2010/10/01(Fri) 11:09
投稿者魔界の仮面弁士
2次元配列(初期値0)を作って、1〜121 の数値を入れていくとします。
http://www.vb-user.net/junk/replySamples/2010.10.01.11.05/rasen.png

・Private Cell(-5 To 5, -5 To 5) As Integer

・既に値が入っている(≠0)座標には進めない物とする。

・「現在どの方向に進んでいるか」を管理しておく。

・初回は右に進むものとする。

・移動方向に応じて、以下のようにループ処理する。
 (1) 右に移動時:下方向に 0 があれば下に曲がる。右も下も進めなければ終了。
 (2) 下に移動時:左方向に 0 があれば左に曲がる。下も左も進めなければ終了。
 (3) 左に移動時:上方向に 0 があれば上に曲がる。左も上も進めなければ終了。
 (4) 上に移動時:右方向に 0 があれば右に曲がる。上も右も進めなければ終了。

[ツリー表示へ]
タイトルRe^5: 渦巻き回りの座標移動アルゴリズム
記事No14951
投稿日: 2010/10/01(Fri) 16:20
投稿者にっちも
アドバイス、ありがとうございました。
以下のような方法で期待の動作を実現できました!

もし、もっと良い方法があれば後学のために、教えてください。

While iCount < mAll
    If iCount <> 0 Then
        For i = 0 To 2
            If bEndFlg Then
                Exit For
            End If
            
            If i = 0 Then
                For j = 1 To iMove
                    If iXToggle Mod 2 <> 0 Then
                        Move(-1, 0)
                    Else
                        Move(1, 0)
                    End If
                    iCount = iCount + 1
                    If iCount = mAll Then
                        bEndFlg = True
                        Exit For
                    End If
                Next j
            ElseIf i = 1 Then
                For j = 1 To iMove
                    If iXToggle Mod 2 <> 0 Then
                        Move(0, 1)
                    Else
                        Move(0, -1)
                    End If
                    iCount = iCount + 1
                Next j
            End If
        Next i
    End If
Wend

[ツリー表示へ]
タイトルRe^6: 渦巻き回りの座標移動アルゴリズム
記事No14954
投稿日: 2010/10/01(Fri) 19:01
投稿者
> もし、もっと良い方法があれば後学のために、教えてください。

もっと良い方法かは判りませんが、
移動済みか否かを判別せずに移動するロジックを考えてみました。

'----------------------------------------
mCount = 21   '移動回数
iMovement = 0  '移動方向

For I = 1 To mCount
    Select Case iMovement
        Case 0  '右:X+
            X = 1
            Y = 0
        Case 1  '下:Y-
            X = 0
            Y = -1
        Case 2  '左:X-
            X = -1
            Y = 0
        Case 3  '上:Y+
            X = 0
            Y = 1
    End Select

    For J = 1 To Int((I / 2) + 0.5)
        Move(X, Y)
    Next J

    iMovement = (iMovement + 1) Mod 4  '方向転換
Next I
'----------------------------------------

変数 mCount は次の曲がり角までの直進を 1 とする移動回数です。
事前に調査して設定、または算出して入れておく必要があります。

変数 X および Y は各座標軸に対する増減です。
移動する方向に合わせて+-を設定します。

現在地から次の曲がり角までの移動量(1,1,2,2,3,3…)を算出し、1マスずつ移動します。

[ツリー表示へ]
タイトルRe^6: 渦巻き回りの座標移動アルゴリズム
記事No14955
投稿日: 2010/10/01(Fri) 19:27
投稿者魔界の仮面弁士
No.14950の私のヒントは、琴さんのNo.14948
> あくまで1点ずつ移動したいのであれば、
によるものです。


一方、同投稿にあった
> 1,1,2,2,3,3,4,4,…と単純なルールで移動しています。
の方を使うのであれば、たとえばこんな感じ。

Option Explicit

Private Sub Form_Load()
    With Picture1
        .AutoRedraw = True
        .ScaleTop = -6
        .ScaleLeft = -6
        .ScaleWidth = 12
        .ScaleHeight = 12
    End With
End Sub

Private Sub Command1_Click()
    Dim c As Integer, offset As Integer

    Picture1.Cls
    Picture1.PSet (0, 0)

    c = 0
    Do
        c = Abs(c) + 1
        offset = IIf(c Mod 2 = 1, c, -c)

        Picture1.Line -(Picture1.CurrentX + offset, Picture1.CurrentY)
        If Abs(Picture1.CurrentX) > 5 Then Exit Do

        Picture1.Line -(Picture1.CurrentX, Picture1.CurrentY + offset)
        If Abs(Picture1.CurrentY) > 5 Then Exit Do
    Loop
End Sub

[ツリー表示へ]