はい、承知いたしました。Luaのwhile文について、初心者向けに基本構文から実践的な使い方までを詳細に解説する約5000語の記事を作成します。
【Lua入門】while文の基本構文と使い方を初心者向けに徹底解説!
プログラミングの世界へようこそ!コードを書き始めると、同じような処理を何度も繰り返したい場面に必ず出くわします。例えば、「プレイヤーのHPが0になるまで敵の攻撃を繰り返す」「ユーザーが正しいパスワードを入力するまで入力を促し続ける」「リストの項目をすべて表示する」など、繰り返し処理はプログラミングの基本的な骨格の一つです。
Luaには、こうした繰り返し処理を実現するために、いくつかの便利な構文が用意されています。代表的なものにfor文、repeat-until文、そしてこの記事の主役であるwhile文があります。
特にwhile文は、「ある特定の条件が満たされている間、ずっと処理を繰り返す」という、非常に直感的で強力なループ処理を実現します。回数が決まっている繰り返しが得意なfor文とは異なり、while文は回数が決まっていない、より柔軟な繰り返し処理を記述するのに最適です。
この記事では、Luaのwhile文に焦点を当て、その基本的な概念から、具体的な書き方、実践的な応用例、そして初心者が陥りがちな罠まで、一つひとつ丁寧に、そして徹底的に解説していきます。この記事を読み終える頃には、あなたはwhile文を自信を持って使いこなし、プログラミングの表現力を一段階引き上げることができるようになっているでしょう。
さあ、while文のシンプルかつ奥深い世界を一緒に探検していきましょう!
第1章: while文とは何か? – 繰り返しの基本概念
while文を学ぶ前に、まずその核心的なコンセプトを理解することが重要です。while文のルールは、驚くほどシンプルです。
「指定した条件式が真(true)である限り、ブロック内の処理を繰り返し実行する」
これだけです。英語の “while” が「~の間」という意味を持つことからも、その動作は直感的に理解できるでしょう。「(条件)の間、~する」と読み替えれば、プログラムの動きがそのままイメージできます。
for文との違い
Luaを学び始めた方が最初に触れるループはfor文かもしれません。では、while文とfor文は何が違うのでしょうか?両者の最も大きな違いは、ループの目的にあります。
-
for文: 繰り返す回数が明確な場合に適しています。- 例:「1から10まで数える」「テーブル(配列)のすべての要素を処理する」
for i = 1, 10 do ... endのように、開始と終了がはっきりしています。
-
while文: 繰り返す回数が事前にわからない場合や、特定の状態が続く限り処理を続けたい場合に適しています。- 例:「ユーザーが ‘exit’ と入力するまで待つ」「ファイルの終端に達するまで読み込む」「ダウンロードが完了するまで待機する」
- ループが何回実行されるかは、プログラムの実行時の状況によって変化します。
この違いを理解することが、適切なループ構文を選択する第一歩となります。
while文の処理フロー
while文がどのように動作するのか、その流れを追いかけてみましょう。これは一種のフローチャートのようなものです。
+-------------------------+
| ループの開始点 |
+-----------+-------------+
|
v
+<------------+-------------+
| | |
| +---------v---------+ |
| | 条件式を評価する | |
| +---------+---------+ |
| | |
| (true) | | (false)
| v |
| +-------------------+ |
| | ループ内の処理を実行| |
| +-------------------+ |
| | |
+-------------+ |
v
+-------------------------+
| ループの終了 (endの次へ) |
+-------------------------+
この図の流れを言葉で説明すると、以下のようになります。
- 条件式の評価: まず、
whileの後に指定された「条件式」を評価します。 - 分岐:
- もし条件式の評価結果が真(
true)であれば、doからendまでの間に書かれた「ループ内の処理」を実行します。 - もし条件式の評価結果が偽(
false)であれば、ループ内の処理は一切実行せず、直ちにループを終了し、endキーワードの次の行の処理に進みます。
- もし条件式の評価結果が真(
- ループの継続: ループ内の処理が最後まで実行されると、プログラムは自動的にステップ1に戻り、再び「条件式」を評価します。
- 繰り返し: この「条件式の評価 → 処理の実行」というサイクルは、条件式が偽(
false)になるまで、何度も何度も繰り返されます。
この「条件がtrueなら実行、falseなら終了」というシンプルなメカニズムが、while文のすべての動作の基本です。次の章では、このメカニズムを実際のコードでどのように記述するのかを見ていきましょう。
第2章: while文の基本構文
while文の概念を理解したところで、いよいよ具体的なコードの書き方(構文)を学びます。構文は非常にシンプルで、一度覚えてしまえば簡単に使えます。
基本構文のテンプレート
Luaにおけるwhile文は、以下の形で記述します。
lua
while (条件式) do
-- 条件式が true と評価される場合に
-- 繰り返し実行される処理をここに書く
end
各部分の役割を分解して見ていきましょう。
while: これからwhileループを開始することを宣言するキーワードです。必ず小文字で書きます。条件式: ループを続けるかどうかを判断するための式です。この式を評価した結果によって、ループ内の処理が実行されるか、ループが終了するかが決まります。括弧()は必須ではありませんが、コードの可読性を高めるために付けることが推奨されます。do:while文の条件式と、繰り返し実行する処理ブロックの本体とを区切るためのキーワードです。-- 繰り返す処理: 条件式がtrueの間、何度も実行されるコードブロックです。インデント(字下げ)を付けて書くことで、コードがどこからどこまでループの一部なのかが視覚的にわかりやすくなります。end: ループブロックの終わりを示すキーワードです。whileは必ずendで閉じる必要があります。
Luaにおける「真(true)」と「偽(false)」
while文を正しく使う上で極めて重要なのが、Luaが何を「真(true)」とみなし、何を「偽(false)」とみなすかというルールです。
- 偽(
false)とみなされる値:falseとnilの2つだけです。 - 真(
true)とみなされる値: 上記のfalseとnil以外のすべての値です。
これは非常に重要なポイントです。つまり、数値の 0 や、空の文字列 "" であっても、Luaの世界では「真(true)」として扱われます。このルールを忘れると、意図しないループの挙動に悩まされることがあります。
具体的なコード例
それでは、いくつかの簡単な例を通してwhile文の使い方に慣れていきましょう。
例1: カウンターを使った基本的なループ
最も基本的なwhileループの例として、1から5まで数を数えて表示するプログラムを作成します。
“`lua
— ループを制御するためのカウンター変数を準備する
local count = 1
— count が 5 以下である間、ループを繰り返す
while count <= 5 do
— 現在の count の値を表示する
print(“現在のカウント: ” .. count)
— ★重要★ カウンター変数を更新する
— この行がないと、count は永遠に 1 のままなので、無限ループに陥る
count = count + 1
end
print(“ループが終了しました。”)
“`
実行結果:
現在のカウント: 1
現在のカウント: 2
現在のカウント: 3
現在のカウント: 4
現在のカウント: 5
ループが終了しました。
このコードのポイントを解説します。
local count = 1: ループの外側で、カウンターとして使う変数countを初期化しています。ループが始まる前の状態を定義する重要なステップです。while count <= 5 do: ここが条件式です。「変数countの値が5以下である」という条件がtrueの間、ループは続きます。print(...): ループの中で実行したい処理です。ここでは現在のcountの値を画面に表示しています。count = count + 1: これがwhile文を使う上で最も重要な部分の一つです。 ループ内で、条件式で使っている変数countの値を変化させています。もしこの行がなければ、countの値は永遠に1のままであり、count <= 5という条件は常にtrueになります。その結果、プログラムは無限にループし続け、終了しなくなってしまいます(これを無限ループと呼びます)。
例2: false や nil を使ってループを終了させる
while文は、条件式がfalseまたはnilになった瞬間に終了します。その挙動を見てみましょう。
“`lua
local keepLooping = true
local loopCount = 0
while keepLooping do
loopCount = loopCount + 1
print(“ループ実行中… (” .. loopCount .. “回目)”)
— 3回ループしたら、ループを終了させるためのフラグを false にする
if loopCount >= 3 then
print(“ループを終了します。”)
keepLooping = false
end
end
print(“—- 次の例 —-“)
— 数値は nil 以外 true と扱われることを利用した例
local aNumber = 3
while aNumber do — aNumber が数値の間は true 扱い
print(“aNumber の値: ” .. aNumber)
aNumber = aNumber – 1
if aNumber == 0 then
aNumber = nil — aNumber を nil にすることで、次の条件判定でループが終了する
end
end
print(“ループが終了しました。”)
“`
実行結果:
ループ実行中... (1回目)
ループ実行中... (2回目)
ループ実行中... (3回目)
ループを終了します。
---- 次の例 ----
aNumber の値: 3
aNumber の値: 2
aNumber の値: 1
ループが終了しました。
最初の例では、keepLoopingという「フラグ(旗印)」となる変数を用意し、ループを続けるかどうかの目印にしています。特定の条件(loopCount >= 3)が満たされたら、このフラグをfalseに倒すことで、次の条件判定時にループが cleanly (きれいに) 終了します。
二つ目の例は、Luaの「nilとfalse以外はtrue」というルールを巧みに利用しています。aNumberが3, 2, 1の間は数値なのでtrueと扱われループが続きます。aNumberが0になったタイミングでnilを代入することで、次のwhile aNumberの判定で条件がfalse(nilなので)となり、ループを抜けています。
この章で学んだ基本構文とLuaの真偽値のルールをしっかり押さえておけば、while文の基本的な読み書きはマスターしたも同然です。次の章では、while文をさらに強力にするbreak文と、厄介な無限ループについて掘り下げていきます。
第3章: 無限ループとbreak文 – ループの強力な制御
while文を使いこなす上で避けては通れないのが、「無限ループ(Infinite Loop)」の概念と、それを意図的に制御するための「break文」です。この2つを理解することで、while文の表現力は飛躍的に向上します。
無限ループとは?
無限ループとは、その名の通り、ループの終了条件が永遠に満たされず、プログラムが半永久的に処理を繰り返し続けてしまう状態を指します。
無限ループが発生すると、プログラムはフリーズしたように見えたり、CPUリソースを100%消費してコンピュータ全体の動作が重くなったりするため、通常はバグ(不具合)として扱われます。
無限ループが発生する典型的な原因
初心者が無限ループに陥る最も一般的な原因は、第2章でも触れた「条件判定に使う変数の更新忘れ」です。
lua
-- 意図しない無限ループの典型例
local i = 1
while i <= 5 do
print("これは無限ループです!")
-- i = i + 1 <-- この更新処理を書き忘れた!
end
-- このプログラムは永遠に "これは無限ループです!" と表示し続ける
このコードでは、変数iは常に1のままで、i <= 5という条件は未来永劫trueのままです。したがって、ループから抜け出すことができません。
ループを強制脱出する break 文
では、もしループの「途中」で、ある特定の条件が満たされたときにループを抜け出したくなったらどうすればよいでしょうか? そのために用意されているのが break 文です。
break文は、それが出現した時点で、現在実行中のループ(while, for, repeat-until)を即座に強制終了させるための命令です。endまで処理を待つことなく、ループの外へ脱出します。
“`lua
local i = 0
while i < 100 do — 本来なら100回ループするはずだが…
i = i + 1
print(“i = ” .. i)
if i == 5 then
print(“iが5になったので、breakします!”)
break — ここでループを強制的に抜ける
end
end
print(“ループの外に出ました。最終的なiの値: ” .. i)
“`
実行結果:
i = 1
i = 2
i = 3
i = 4
i = 5
iが5になったので、breakします!
ループの外に出ました。最終的なiの値: 5
この例では、iが5になった瞬間にif文の条件が満たされ、break文が実行されます。その結果、whileループは即座に終了し、プログラムはendの次の行にあるprint文の実行に移ります。iが6以上になることはありません。
while true do ... end と break の組み合わせ
ここからがwhile文の真骨頂です。一見すると奇妙に思えるかもしれませんが、while文は break文と組み合わせることで、非常に強力で読みやすいコードを書くことができます。その代表的なパターンが、意図的な無限ループです。
lua
while true do
-- ... 何らかの処理 ...
if (脱出条件) then
break
end
-- ... 何らかの処理 ...
end
while true do は、条件式が常にtrueなので、そのままでは必ず無限ループになります。しかし、ループの内部にif文とbreak文を置くことで、「特定の脱出条件が満たされたらループを抜ける」というロジックを非常に明確に記述できます。
このパターンは、以下のような場合に特に有効です。
- ループの終了条件が複数ある場合。
- ループの終了判定を、ループ処理の先頭ではなく、途中や末尾で行いたい場合。
例1: ユーザーが特定の文字を入力するまで待つ
このパターンが最も輝く典型的な例が、ユーザーからの入力を待つ処理です。
“`lua
while true do
print(“何かメッセージを入力してください (‘quit’ と入力すると終了します):”)
— ユーザーからの入力を一行読み取る
local input = io.read()
— 入力された文字が ‘quit’ かどうかをチェック
if input == “quit” then
— ‘quit’ ならループを脱出する
break
end
— ‘quit’ でなければ、入力されたメッセージをエコーバックする
print(“あなたが入力したのは: ‘” .. input .. “‘ ですね。”)
print(“——————–“)
end
print(“プログラムを終了します。ご利用ありがとうございました。”)
“`
このコードのロジックは非常に自然です。
- 無限ループを開始する (
while true do)。 - ユーザーに入力を促す。
- 入力を受け取る。
- もし入力が終了コマンド (
'quit') なら、ループをbreakで抜ける。 - そうでなければ、入力に対する処理を行い、ループの先頭に戻る。
この処理をbreakなしで書こうとすると、少し複雑になります。
lua
-- breakを使わない場合の代替案
local input = ""
while input ~= "quit" do
print("何かメッセージを入力してください ('quit' と入力すると終了します):")
input = io.read()
if input ~= "quit" then
print("あなたが入力したのは: '" .. input .. "' ですね。")
print("--------------------")
end
end
print("プログラムを終了します。ご利用ありがとうございました。")
breakを使った方が、ループ内の処理がシンプルになり、終了条件がif文の中にカプセル化されているため、コードの意図が読み取りやすくなるのがわかると思います。
例2: 配列(テーブル)から特定の要素を探索する
テーブルの中から特定のデータを探し、見つかったらすぐに探索を終了したい場合にもbreakは役立ちます。
“`lua
local user_database = {“alice”, “bob”, “charlie”, “dave”, “eve”}
local target_user = “charlie”
local found_index = nil — 見つかった場合のインデックスを保存する変数
local i = 1
while i <= #user_database do
local current_user = user_database[i]
print(“探索中… (” .. i .. “番目: ” .. current_user .. “)”)
if current_user == target_user then
print(“ターゲット ‘” .. target_user .. “‘ を発見!”)
found_index = i — インデックスを保存
break — 目的のデータが見つかったので、これ以上ループする必要はない
end
i = i + 1
end
if found_index then
print(“結果: ” .. target_user .. ” は ” .. found_index .. ” 番目にいました。”)
else
print(“結果: ” .. target_user .. ” はデータベースにいませんでした。”)
end
**実行結果:**
探索中… (1番目: alice)
探索中… (2番目: bob)
探索中… (3番目: charlie)
ターゲット ‘charlie’ を発見!
結果: charlie は 3 番目にいました。
``charlieが見つかった時点でbreakが実行されるため、その後のdaveやeve`はチェックされません。これにより、無駄な処理を省き、効率的なプログラムを書くことができます。
break文とwhile true doパターンは、最初は少しトリッキーに見えるかもしれませんが、一度慣れてしまえば、あなたのプログラミングの道具箱の中で最も頼りになるツールの一つとなるでしょう。
第4章: while文の実践的な使い方と注意点
これまで学んだ基本を元に、この章ではより実践的なwhile文の使い方と、プログラミング中に注意すべき点について深く掘り下げていきます。
実践例1: シンプルなゲームループ
多くのゲームの心臓部には、「ゲームループ」と呼ばれる無限ループが存在します。このループは、ゲームが実行されている間、常に回り続け、プレイヤーからの入力、キャラクターの動きの計算、画面の描画などを繰り返し行います。while文は、このゲームループを実装するのに最適です。
“`lua
— ゲームが実行中かどうかを示すフラグ
local isGameRunning = true
— プレイヤーの初期位置
local playerX = 10
local playerY = 10
print(“簡易ゲーム開始! ‘q’ を押して終了。’w’,’a’,’s’,’d’で移動。”)
— ゲームループ
while isGameRunning do
— ===================================
— 1. 入力処理 (Input)
— ===================================
print(“現在の位置: (” .. playerX .. “, ” .. playerY .. “) コマンドを入力してください:”)
local command = io.read()
— ===================================
— 2. ゲーム状態の更新 (Update)
— ===================================
if command == “q” then
— ‘q’ が入力されたらゲーム終了
isGameRunning = false
print(“ゲームを終了します。”)
elseif command == “w” then
playerY = playerY – 1 — 上に移動
elseif command == “s” then
playerY = playerY + 1 — 下に移動
elseif command == “a” then
playerX = playerX – 1 — 左に移動
elseif command == “d” then
playerX = playerX + 1 — 右に移動
else
print(“無効なコマンドです。”)
end
— ===================================
— 3. 描画 (Draw) – ここではコンソール出力で代用
— ===================================
— 本来はここで画面をクリアしてキャラクターなどを描画するが、
— この例ではループの先頭で位置を表示することで代用している。
print(“——————–“)
end
print(“最終的なプレイヤーの位置: (” .. playerX .. “, ” .. playerY .. “)”)
“`
この例では、isGameRunning というフラグ変数を使ってループを制御しています。ユーザーが ‘q’ を入力すると、このフラグが false になり、次のループの開始時に while の条件が満たされなくなり、ループが終了します。
もちろん、これをwhile true doとbreakで書くことも可能です。どちらのスタイルを選ぶかは、プロジェクトのコーディング規約や個人の好みによりますが、どちらの書き方でも同じことができると理解しておくことが重要です。
lua
-- while true と break を使ったゲームループの例
while true do
-- ... (入力処理と更新処理は上記と同じ) ...
if command == "q" then
print("ゲームを終了します。")
break -- ここでループを抜ける
end
-- ...
end
注意点1: 無限ループの罠(再訪)
無限ループはバグの元ですが、時にはさらに厄介な問題を引き起こすことがあります。特に、浮動小数点数を使った比較には注意が必要です。
浮動小数点数の比較による無限ループ
コンピュータは、0.1 のような小数を二進数で完全に正確に表現することができません。そのため、わずかな誤差(丸め誤差)が生じます。この誤差が原因で、意図しない無限ループが発生することがあります。
lua
-- 無限ループに陥る可能性のある危険なコード
local x = 0.0
while x ~= 1.0 do -- x が正確に 1.0 になるとは限らない!
print(x)
x = x + 0.1
end
このコードを実行すると、環境によってはxの値が0.9999999999999999のようになり、決して1.0と等しくならない可能性があります。その結果、x ~= 1.0(xは1.0ではない)という条件が常にtrueとなり、無限ループに陥ります。
対策:
浮動小数点数をループの終了条件に使う場合は、等価比較(== や ~=)を避け、不等号(<, <=, >, >=)を使いましょう。
lua
-- 安全なコード
local x = 0.0
while x < 1.0 do -- 1.0より小さい間、という条件にする
print(x)
x = x + 0.1
end
これにより、誤差によって x が 1.0 をわずかに超えたとしても、確実にループは終了します。
注意点2: ループ内での変数のスコープ
whileループの中でlocalキーワードを使って宣言された変数の寿命(スコープ)は、そのループブロック内に限定されます。より正確に言うと、ループが1回繰り返されるごとに、新しいローカル変数が作られ、その回のループが終わると破棄されます。
“`lua
local i = 0
while i < 3 do
i = i + 1
— この変数 ‘temp_message’ は、ループの各回で新しく作られる
local temp_message = “ループ ” .. i .. ” 回目の中です。”
print(temp_message)
end
— print(temp_message) — エラー! ループの外からは temp_message にアクセスできない
— この行のコメントを外して実行すると、temp_message が nil であるためエラーになる
“`
この挙動は、ループの各回で一時的にしか使わない変数を安全に管理するのに役立ちます。ループの外側で値を保持したい場合は、ループが始まる前に変数を宣言しておく必要があります。
注意点3: パフォーマンスとCPU使用率
while true do ... end のような、待機処理を含まないタイトなループは、CPUの計算能力を100%使い切ってしまう可能性があります。これは、CPUが「他にやるべきことがないか」と考える暇もなく、ひたすらループ内の処理を猛スピードで実行し続けるためです。
ゲームループのような場合は、意図的に高いパフォーマンスを求めるので問題ありませんが、「何らかのイベントを待つ」だけのループの場合、CPUリソースを無駄に消費してしまいます。
“`lua
— CPUを100%消費してしまう可能性のある待機ループの例
local file_exists = false
while not file_exists do
— ‘result.txt’というファイルが存在するかチェックする (擬似コード)
— file_exists = check_if_file_exists(“result.txt”)
— このループは待機時間がないため、CPUを無駄に食う
end
“`
このような場合、ループ内に短い待機処理を入れるのが一般的です。Luaの標準ライブラリにはsleep(待機)関数はありませんが、使用している環境やフレームワーク(例: LÖVE 2Dのlove.timer.sleep, コンピュータクラフトのos.sleepなど)が提供していることがよくあります。
“`lua
— 待機処理を入れた、より良い待機ループの例
while not file_exists do
— file_exists = check_if_file_exists(“result.txt”)
— 1秒待機することで、CPUに負荷をかけすぎないようにする
— os.sleep(1) — この関数は環境に依存します
end
“`
while文は強力ですが、その使い方によってはプログラム全体のパフォーマンスに大きな影響を与える可能性があることを常に心に留めておきましょう。
第5章: while文と他のループ構文の使い分け
ここまでwhile文について深く学んできましたが、Luaには他にもfor文とrepeat-until文というループ構文があります。優れたプログラマーは、それぞれのツールの長所と短所を理解し、状況に応じて最も適切なものを選択します。この章では、その使い分けの判断基準を明確にします。
for文 vs while文
for文には、決まった回数を繰り返す「数値for」と、テーブルの要素を走査する「汎用for」の2種類があります。
数値 for文 が適しているケース
「決まった回数だけ処理を繰り返したい」 ときは、迷わず数値for文を使いましょう。
for文の例: 1から10まで表示する
lua
for i = 1, 10 do
print(i)
end
while文で同じことを書いた場合:
lua
local i = 1
while i <= 10 do
print(i)
i = i + 1
end
両者を比較すると、for文の方が圧倒的に優れている点がわかります。
- 簡潔さ: 1行でカウンター変数の初期化(
i=1)、終了条件(10)、更新処理(自動で+1)をすべて定義できます。 - 安全性: カウンター変数の更新 (
i = i + 1) を書き忘れる心配がありません。これにより、意図しない無限ループのリスクが大幅に減少します。 - スコープ:
forループで宣言されたカウンター変数iのスコープはループ内に限定されます。ループ終了後にiを使おうとしてもnilになるため、意図せず他の場所で使ってしまうバグを防げます。
結論: 繰り返しの回数が事前にわかっているなら、常に for 文を優先して使いましょう。
汎用 for文 が適しているケース
「テーブル(配列や辞書)のすべての要素に対して順番に処理を行いたい」 ときは、汎用for文が最適です。ipairsやpairsといったイテレータと組み合わせて使います。
for文の例: テーブルの全要素を表示する
lua
local fruits = {"apple", "banana", "cherry"}
for index, value in ipairs(fruits) do
print(index, value)
end
while文で同じことを書いた場合:
lua
local fruits = {"apple", "banana", "cherry"}
local i = 1
while i <= #fruits do
local value = fruits[i]
print(i, value)
i = i + 1
end
ここでもfor文に軍配が上がります。for文はテーブルのサイズ(#fruits)を意識する必要がなく、インデックス(i)と値(value)を自動で取り出してくれます。コードがシンプルになり、間違いも起こりにくくなります。
結論: テーブルの全要素を走査するなら、汎用 for 文を使いましょう。
repeat-until文 vs while文
while文と非常によく似たループにrepeat-until文があります。両者の違いは2つです。
-
条件判定のタイミング:
while: ループに入る前に条件を判定します(前置判定)。条件が最初からfalseなら、一度も実行されません。repeat-until: ループ内の処理を一度実行した後に条件を判定します(後置判定)。そのため、最低でも1回は必ず実行されます。
-
ループの継続条件:
while: 条件がtrueの間、ループを継続します。repeat-until: 条件がfalseの間、ループを継続します(つまり、条件がtrueになったらループを終了します)。英語の “repeat … until (condition is true)”((条件がtrueになる)まで繰り返す)と考えると自然です。
repeat-until文が適しているケース
「最低でも1回は処理を実行し、その結果を見てからループを続けるか判断したい」 という場合にrepeat-until文は非常に便利です。
典型的な例は、ユーザーにメニューから正しい選択肢を選ばせる処理です。
repeat-until文の例:
“`lua
local choice
repeat
print(“— メニュー —“)
print(“1: ゲーム開始”)
print(“2: 設定”)
print(“3: 終了”)
print(“番号を入力してください:”)
— 文字列で入力される可能性も考慮し、tonumberで数値に変換
choice = tonumber(io.read())
if not (choice == 1 or choice == 2 or choice == 3) then
print(“無効な入力です。1, 2, 3のいずれかを入力してください。”)
end
— choiceが1か2か3になるまで繰り返す (つまり、不正な入力の間はループを続ける)
until choice == 1 or choice == 2 or choice == 3
“`
この例では、まずメニューを表示し、ユーザーに入力を促します。この「メニュー表示と入力」は、ユーザーが正しい選択をするまで何度も繰り返される必要がありますが、最低でも1回は必ず実行されなければなりません。このようなシナリオにrepeat-untilは完璧にマッチします。
これをwhile文で書くと、少し不自然なコードになります。
lua
-- while文で同じことを書いた場合
local choice = nil -- ループに入るために初期値を不正な値にしておく必要がある
while not (choice == 1 or choice == 2 or choice == 3) do
-- repeat-until と同じ処理
-- ...
end
ループに入るためだけに、事前に変数を初期化する手間が必要になります。
結論: 最低1回の実行を保証したい場合は、repeat-until文を検討しましょう。
while文が輝くとき
では、最終的にwhile文はどのような場面で最も輝くのでしょうか?
それは、「ループの開始前に継続条件を判定する必要があり、かつ、ループ回数が事前に決まっていない場合」 です。
- ファイルの終端まで読み込み:
while not file:is_at_end() do ... end - ゲームオブジェクトが存在する間:
while enemy:is_alive() do ... end - 汎用的なイベントループ:
while true do ... break endパターン
これらのシナリオでは、for文のように回数が決まっておらず、repeat-untilのように「まず実行」するわけにもいきません(ファイルが空かもしれないし、敵が最初から死んでいるかもしれません)。このような状況こそ、while文がその真価を発揮する場面なのです。
まとめ – while文をマスターして次のステップへ
この記事では、Luaのwhile文について、その基本から応用までを網羅的に解説してきました。最後に、学んだことの要点を振り返りましょう。
-
while文の基本:while (条件式) do ... endという構文で、「条件式がtrueである間」処理を繰り返します。Luaではfalseとnil以外はすべてtrueと見なされます。 -
無限ループに注意:
whileループでは、ループ内で条件式に関わる変数を更新し忘れると、簡単に無限ループに陥ります。これは最も一般的なバグの一つです。 -
break文による脱出:break文を使うことで、ループを任意のタイミングで強制的に中断できます。 -
while true do ... break endパターン: 意図的に無限ループを作り、内部のif文とbreakで脱出条件を記述するこのパターンは、非常に柔軟性が高く、多くの場面で役立つ強力なテクニックです。 -
他のループとの使い分け:
- 回数が決まっているなら
for文。 - テーブルの全要素を走査するなら汎用
for文。 - 最低1回の実行を保証したいなら
repeat-until文。 - 回数が未定で、ループ前に条件を判定したいなら
while文。
- 回数が決まっているなら
while文は、そのシンプルさゆえに、プログラミングにおける「繰り返し」という根源的な処理をストレートに表現できる美しい構文です。今回学んだ知識は、あなたが今後より複雑で動的なプログラムを構築していく上で、間違いなく強力な武器となるでしょう。
知識は、実際に使ってこそ血肉となります。ぜひ、あなた自身のコンピュータでエディタを開き、この記事で紹介した例を打ち込んでみたり、少し改造してオリジナルのプログラムを作ってみたりしてください。「ユーザーが”yes”と入力するまで質問を繰り返すプログラム」や、「ランダムな数が100になるまでサイコロを振り続けるプログラム」など、簡単な課題からで構いません。
手を動かして試行錯誤する中で、while文の本当の面白さと便利さが実感できるはずです。あなたのプログラミングの旅が、このwhile文のマスターによって、さらにエキサイティングなものになることを願っています。