繰り返しループ処理 – FlyWithLua

2023年4月8日

繰り返し処理にはテーブルを使うと便利である。

参考:https://symfoware.blog.fc2.com/blog-entry-450.html

for doの基本形

for i = 1 , 5 , 1 do
print(i) — 1 2 3 4 5が出力される Lua
imgui.TextUnformatted(i) — 1 2 3 4 5が出力される FlyWithLua
end

0から始めることも出来る。出力は6つになるが、5の設定であることに注意!

for i = 0, 5, 1 do
imgui.TextUnformatted(i) — 0 1 2 3 4 5が出力される FlyWithLua
end

ボタンの繰り返し

imgui.SameLine()で横に並べる。これが無いと下に並ぶことになる。

------------------------------------------------------------------------
-- ウインドウの作成
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")        --wnd変数をセット
float_wnd_set_imgui_builder(wnd, "im_on_build") --関数を読み込みセットする
------------------------------------------------------------------------
--ボタンを作成するための関数
function im_on_build(wnd, x, y)
  text = {"ABC","BVC","GFD"}
	for i = 1, #text do
		if imgui.Button(text[i]) then

		end
		imgui.SameLine()
	end
end

テキストの繰り返し

wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")        --wnd変数をセット
float_wnd_set_imgui_builder(wnd, "im_on_build") --関数を読み込みセットする
------------------------------------------------------------------------
local button_number = {"1","2","3","4","5"}
--ボタンを作成するための関数
function im_on_build(wnd, x, y)
	for i = 1, #button_number do
		imgui.TextUnformatted(button_number [i])
		imgui.SameLine()
	end
end

数字だけなら、こっちが簡単。上と同じ結果になる。

wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")        --wnd変数をセット
float_wnd_set_imgui_builder(wnd, "im_on_build") --関数を読み込みセットする
------------------------------------------------------------------------
--ボタンを作成するための関数
function im_on_build(wnd, x, y)
	for i = 1, 5 do
		imgui.TextUnformatted(i)
		imgui.SameLine()
	end
end

数字の途中から始める

5からスタートする場合

5からスタートする場合、for i = 5 , 10 , 1 do

for i = 5 , 10 , 1 do
print(i) — 1 2 3 4 5が出力される Lua
imgui.TextUnformatted(i) — 1 2 3 4 5が出力される FlyWithLua
end

テキストの位置を設定する

基本的には左上から下に並べられる。位置を指定したい場合は以下のようになる。9行と10行に入っている。

imgui.SetCursorPosX(40)
imgui.SetCursorPosY(60)

wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")             --wnd変数をセット
float_wnd_set_imgui_builder(wnd, "im_on_build") --関数を読み込みセットする
------------------------------------------------------------------------
local button_number = { "1", "2", "3", "4", "5" }
--ボタンを作成するための関数
function im_on_build(wnd, x, y)
    text = { "ABC", "BVC", "GFD" }
    imgui.SetCursorPosX(40)
    imgui.SetCursorPosY(60)
    for i = 1, #button_number do
        imgui.TextUnformatted(button_number[i])
        imgui.SameLine()
    end
end

テキスト間の横送りを指定する

6行目にテーブルを作成して、その変数を11行目に入れている。button_numberは上のように不要にすることもできる。

wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")             --wnd変数をセット
float_wnd_set_imgui_builder(wnd, "im_on_build") --関数を読み込みセットする
------------------------------------------------------------------------
local button_number = { "1", "2", "3", "4", "5" }
text_Distance = {"30", "70", "110", "150", "190"}
--ボタンを作成するための関数
function im_on_build(wnd, x, y)
    imgui.SetCursorPosY(60)
    for i = 1, #button_number do  
        imgui.SetCursorPosX(text_Distance[i])
        imgui.TextUnformatted(button_number[i])
        imgui.SameLine()  
    end
end

特定の部分だけを表示しないようにする

for文のある部分だけを削除(表示しない)するようにする方法。下の分は3番目を対象にしている。このように3つ目が非表示になる。

for i = 1, 5, 1 do
if i == 3 then
goto continue
end
–内容を記述
::continue::
end

----------------------------------------------------
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")            
float_wnd_set_imgui_builder(wnd, "im_on_build") 
----------------------------------------------------
function im_on_build(wnd, x, y)
    for i = 1, 5, 1 do
        if i == 3 then
            goto continue
       end
       imgui.TextUnformatted(i)  --内容を記述
       ::continue::
    end
end

1つおきに表示する場合(1 3 5と1つ飛びで出力される)

for i = 1 , 5 , 2 do
print(i) — 1 3 5が出力される
imgui.TextUnformatted(i)–FlyWithLuaの場合
end

後ろから表示する場合(3、2、1の順番で表示される)

for i = 3 , 1 , -1 do
print(i) — 3 2 1と逆に出力される
imgui.TextUnformatted(i)–FlyWithLuaの場合
end

(break)でループ処理を途中で終了する

数字のカウントを途中で止める。以下は2で止めるので1しか表示されない。

for i = 1 , 3 do
if i == 2 then
break
end
print(i) — 1が出力される end
imgui.TextUnformatted(i)–FlyWithLuaの場合

while文

条件式がtrueの間、ループを実行します。

while [評価式] do
end

サンプルとして、1から5までループし、数を表示してみます。

> v = 1
> while v <= 5 do
>> print(v)
>> v = v + 1
>> end
1
2
3
4
5

repeat

ループの中身を必ず一回は実行し、最後にループを脱出するかの評価を行いたい場合は、repeatを使用します。

repeat
until [評価式]

評価式がtureになったらループを脱出します。

> v = 1
> repeat
>> print(v)
>> v = v + 1
>> until v == 6
1
2
3
4
5

for

forの構文はこんな感じ。

for [変数名] = [開始値],[終了値] do
end

ループ時、加算する値を指定できます。

for [変数名] = [開始値],[終了値],[加算値] do
end

サンプルは以下の通り。

> for i = 1, 5 do
>> print(i)
>> end
1
2
3
4
5

偶数のみ表示。

> for i = 2,10,2 do
>> print(i)
>> end
2
4
6
8
10

イテレーター(配列のようなデータ構造の要素を順に処理する構文)

「in ipairs」でも「in pairs」でも動作する。

Lua では、for ループで特定のテーブルを反復処理する場合に、pairs() と ipairs() 関数の両方を使用できる。 これらの関数は両方とも、キーが要素のインデックスであり、値がそのインデックス テーブルに格納されている要素であるキーと値のペアを返します。

Pairs() 関数と ipairs() 関数の最初の違いは、ipairs() 関数は確実にキーの順序を維持するのに対し、pairs() 関数はキーの順序を維持しないこと。
ipairs()はインデックスと値のペアを返し、主に数値テーブルに使用されます。配列内の非数値キーは無視されますが、インデックスの順序は確定的です(数値順)。

----------------------------------------------------
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")
float_wnd_set_imgui_builder(wnd, "im_on_build")
----------------------------------------------------
function im_on_build(wnd, x, y)
    coffee = {
        "Blue mountain",
        "Guatemala",
        "Hawaii Kona"
    }
    for idx, val in ipairs(coffee) do 
        imgui.TextUnformatted("coffee[" .. idx .. "] = " .. val)
    end  
end

連想配列のキーと値のペアを返し、全ての要素にアクセスできる。

----------------------------------------------------
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")
float_wnd_set_imgui_builder(wnd, "im_on_build")
----------------------------------------------------
function im_on_build(wnd, x, y)
    coffee2 = {
        bluemountain_coffee = "ABC",
        guatemala_coffee = "JHG",
        hawaii_coffee = "GGH"
    }
    for key, val in pairs(coffee2) do
        imgui.TextUnformatted(key .. " = " .. val)
    end
end

テーブルを使った繰り返し

tableの中身を表示するには、以下の構文を使用します。

for [key変数], [value変数] in pairs([table “” not found /]
) do
end

tableをリストとして使用している場には、keyにはインデックスが入ります。2つの内容を同時に処理。

tableをリストとして使用している場合のサンプル。

t = {“a”, “b”, “c”, “d”, “e”}
for key, value in pairs(t) do
imgui.TextUnformatted(key .. ” ” .. value)
end

実際のスクリプト例

wnd = float_wnd_create(200, 150, 1, true)
float_wnd_set_title(wnd, "Buttons")
float_wnd_set_imgui_builder(wnd, "im_on_build")


function im_on_build(wnd, x, y)
	t = { "a", "b", "c", "d", "e" }
	for key, value in pairs(t) do
		imgui.TextUnformatted(key .. "  " .. value)
	end
end

tableを連想配列として使用している場合のサンプル。

u = {}
u[1] = “a”
u[3] = “b”
u[2] = “c”
u[4] = “d”
u[“hello”] = “world”
for key, value in ipairs(u) do
imgui.TextUnformatted(key .. ” ” .. value)
end

「ipairs」と「pairs」では使い方が少し違ってくる。

「ipairs」にすると、このスクリプトに関しては「hello = world」が表示されなくなる。
ipairs()はインデックスと値のペアを返し、主に数値テーブルに使用されます。配列内の非数値キーは無視されますが、インデックスの順序は確定的(数値順)。
下を見るとわかるように、1から数値順に表示されていて、スクリプトに記述されている順番は無視されている。

wnd = float_wnd_create(200, 150, 1, true)
float_wnd_set_title(wnd, "Buttons")
float_wnd_set_imgui_builder(wnd, "im_on_build")


function im_on_build(wnd, x, y)
	u = {}
	u[1] = "a"
	u[3] = "b"
	u[2] = "c"
	u[4] = "d"
	u["hello"] = "world"
	for key, value in ipairs(u) do
		imgui.TextUnformatted(key .. "  " .. value)
	end
end

13行めの「ipairs(u)」を「pairs(u)」に変更するとうまく表示される。
pairs()はキーと値のペアを返し、主に連想テーブルに使用されます。キーの順序は指定されていません。(順番が確定的でない?)
順番は同じように数値の番号の順番で表示されペアの文字が返されている、違うのはテキストが表示されるということになる。

以下のような書き方もある。
しかしこれは「pairs(t)」を「ipairs(t)」とすると表示されなくなるので使えなるので注意。

t = {}
t.a = “a_value”
t.b = “b_value”
t.c = “c_value”
t.d = “d_value”
t.e = “e_value”
for key, value in pairs(t) do
imgui.TextUnformatted(key .. ” ” .. value)
end

break

ループを途中で脱出する場合には、breakが使用できます。

> v = 0
> while true do
>>     if v == 5 then
>>         print(“break実行”)
>>         break
>>     end
>>     print(v)
>>     v = v + 1
>> end
0
1
2
3
4
break実行

forの中にforを入れる

縦横を繰り返し。この方法だと最初の行を繰り替えしているだけ。

----------------------------------------------------
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")            
float_wnd_set_imgui_builder(wnd, "im_on_build") 
----------------------------------------------------
function im_on_build(wnd, x, y)
    for i = 1, 5 do
        for j = 1, 10 do
        imgui.TextUnformatted(j)
        imgui.SameLine()
        end
        imgui.TextUnformatted("\n")
    end
end

for文で作成した数値を特定の位置で改行する

この方法だと好きな位置で改行を設定することができる。必要な改行位置分だけelseifを作成する必要があるのが面倒だが、それ以外に方法が見つからない。
andとかorは最初の条件になれば、そこで終了してしまうので1つだけになってしまう。

----------------------------------------------------
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")
float_wnd_set_imgui_builder(wnd, "im_on_build")
----------------------------------------------------
function im_on_build(wnd, x, y)
    for i = 1, 10 do
        imgui.TextUnformatted(i)
        imgui.SameLine()
        if i == 3 then
            imgui.TextUnformatted("\n")
        elseif i == 5 then
            imgui.TextUnformatted("\n")
        end
    end
end

ボタンを繰り返して10ボタン目で改行する

----------------------------------------------------
wnd = float_wnd_create(600, 150, 1, true)
float_wnd_set_title(wnd, "Buttons")
float_wnd_set_imgui_builder(wnd, "im_on_build")
----------------------------------------------------
function im_on_build(wnd, x, y)
	for i = 1, 30 do
		if imgui.Button("Edit", 50, 40) then

		end
		imgui.SameLine()
		if i == 10 then
            imgui.TextUnformatted("\n")--本来テキストが入るところに改行を入れるとボタンを改行できるようになる。
        elseif i == 20 then
            imgui.TextUnformatted("\n")--あとはelseifで同じ改行が繰り返されるのでこれ1つで良い。
        end
	end
end

while文

----------------------------------------------------
wnd = float_wnd_create(400, 200, 1, true)
float_wnd_set_title(wnd, "Buttons")
float_wnd_set_imgui_builder(wnd, "im_on_build")
----------------------------------------------------
function im_on_build(wnd, x, y)
    local cnt = 1
    while cnt <= 5 do
        imgui.TextUnformatted("cnt = " .. cnt)
        cnt = cnt + 1
    end
end

Luaでは

local cnt = 1
while cnt <= 5 do
    print("cnt = "..cnt)
    cnt = cnt + 1
end

「0」又は「-5」からスタートする

Luaではインデックス1で配列を開始するのが通例です。配列も1で始まる場合は、何もしなくてもその機能を直接使用できます。
しかし、0から始めたい場合があるのです。その場合は以下のようにする方法があるとか。
これもまだ検証していない。

a = {} — new array
for i=1, 10 do
a[i] = 0
end

-5から始める

— -5 から 5 までのインデックスを持つ配列を作成します
a = {}
for i=-5, 5 do
a[i] = 0
end