🍍

Ruby で創る RPG 第十章 勇者がコマンドを選び直せるようにする

2024/01/25に公開

Ruby で創る RPG


十四歳のお誕生日のお祝いにとMacBook Air を贈られた 未來(みらい)。
憧れの遙香(はるか)お姉様から、プログラミングを教えてもらえることに。
コンピュータの仕組みを学ぶところから始まり、RPG(ロールプレイングゲーム)を創り上げてます。

本日は配列を学ぶことに。

毎週木曜日の掲載予定です。お楽しみに。


配列の基礎を学ぶ

「とてもよくできたわね。 勇者が攻撃するか回復するか逃走するか選べるようになったのね。」
「うん、そうなんだ。そしてね、勇者が回復しなくちゃいけないところで、間違えて攻撃しちゃったり、逃げ出しちゃったりするとやり直しが聞かないんだけれど、どうしたらいいのかな?」
「そうね。そうすると、コマンド選択を繰り返すことができるようにすると良いわね。」

「うん、そうだね。どうやったらできるの?」
「そうね〜、みっくんはどうやったらできると思う?」
「もう一回繰り返しを入れるといいのかな〜」
「そうね。ひとまずそれでやってみましょうか。RPGのプログラムもだいぶ長くなってきたので、前回同様、小さなプログラムで練習していきましょう。」
「うん、そうだね。」

「まず、コマンドメニューの表示のところだけれど、こんな感じで書いていたわよね。」

# コマンドを表示する
puts "1: 攻撃"
puts "2: 回復"
puts "3: 逃走"

「うん、そうだよ。」
「前にも少し話したけれども、こういった時に配列を使うととても簡単に描けるようになるわ。」
「そうなんだね。配列ってどうやって書くの?」

「** 配列は、複数のデータを順番に並べたデータ構造・入れ物**って、紹介したけれど、Rubyの場合だと、配列はこんな感じで書くわ。」

array.rb
menus = ["攻撃", "回復", "逃走"]
puts menus[0]
puts menus[1]
puts menus[2]

「配列は、複数のデータを順番に並べたデータ構造・入れ物ってあるけれど、入れ物の中に入っているそれぞれのデータが"攻撃""回復""逃走"っていう三つの文字列ね。で、これらが一緒になっている入れ物、配列を作るためには [] で囲むと、配列ができるというのが、Rubyの文法よ。」

「そうなんだね。なので["攻撃", "回復", "逃走"]って書くと、三つの文字列が一緒になった配列ができるんだね。」
「ええ、そうよ。」
「そして、配列を作ったので、後からいろいろ使うのが便利なように、menusっていう変数に代入しているんだね。」
「ええ、その通り。」
「で、次の行なんだけれど、puts は画面に表示する命令だったよね。その後のmenus[0]というのは何?」
「これね、配列の中に入っているそれぞれのデータのことを、要素と言うふうに言ったりもするんだけれど、0番目の要素って言う意味よ。」
「0番目の要素?」
「ええ、あたしたちが話している日本語の世界だと、一番目、二番目という風にいうけれど、コンピュータの世界では、最初の要素を指し示す時に、0番目っていうことも良くあるわ。」
「そうなんだね。じゃあ、これは配列の最初の要素のことだから、"攻撃"って表示されるってことだね。」
「ええ、その通り。」
「じゃあ、puts menus[1]"回復"が、puts menus[2]"逃走"が表示されるんだね。」
「ええ、そうよ。」
「配列は、arrayっていうから、array.rbって名前のファイルを作りましょう。ruby array.rbってすると実行できるわ。」
「うん。やって見る」

「どう、実行できたかしら。」
「うん、できたよ。」

irb (Interactive Ruby) で練習する

「さて今までは、新規作成してコードを書いて実行してきたけれども、Rubyには、irbという手軽にコードを実行できる機能があるの。ターミナル画面から、Command + N を押すと別のウィンドが開けるの。CommandキーとNを一緒に押すのね。やってみて。」

「うん、もう一つ別のウィンドウが開いたよ。」
「ええ、開いたら 今の時刻などメッセージが表示されていると思うけれど、clearってタイプすると、画面の表示を消してスッキリすることができるわ。」
「うん、何も表示されなくなってスッキリしたよ。」
「そしたら、irbってタイプするの。」
「うん、入れて見る。」
「どうかしら。立ち上がったみたいね。これがirbの画面。左端に表示されているのがプロンプトって呼ばれる画面よ。」

「そうなんだね。プロンプトってなに?」
「プロンプトは、促すっていう意味なんだけれど、これからいろいろ入力してねって、促してくれているのね。irb は Interactive Ruby の 略なんだけれど、その名の通り、対話的に双方向で簡単なRubyのコードを入力して結果を見ることができるわ。早速やってみましょうか。」
「うん。」

配列を作成する

「じゃあ、menus = ["攻撃", "回復", "逃走"]って入れて、エンターキーを押してね。」
「うん、エンターを押したよ。」
["攻撃", "回復", "逃走"]って表示されたわよね。」
「うん」
「じゃあ、次にmenus[0]って入れてみて。」
「うん。"攻撃"って表示されたよ。」
「ええ、irbが、応答を返してくれるの。最初の例だと menus = ["攻撃", "回復", "逃走"] を実行した結果を、次の例だと menus[0] が返ってくるの。これが Interactive 対話 っていう意味よ。」

puts menus[0] って書かなくても、menus[0] だけでいいんだね。」
「そうね。変数の値を知るだけなら、menusmenus[0]と直接、変数名を入力するだけで良いから、簡単よね。」
「うん、そうだね。」
「ファイルを作って、実行させてっていう手間もないから、ちょっとした結果を知るにはとっても便利よ。」
「そうだね。」
「短いコードなら直接irbに打ち込んだらいいし、ちょっと長いコードを試したい時には、今使っているpulsarエディタの上で入力してコピーしたのを、irbに貼り付けるようにすると楽だわ。」
「うん、わかったよ。」
「じゃぁ、練習を兼ねて、このままirb上で配列についていろいろ学んでいきましょう。」
「うん。」

配列要素の追加

「配列への要素の追加は、いろいろな方法があるわ。配列の添字を使ってmenus[5] = "魔法"なんてする方法もあるの。やってみて。」
「うん、やって見る。」
「どのように配列に追加されたか見たかったら、menusってすると、見ることができるわ。」
「うん、"魔法"が追加されているよ。この間にある nilっていうのは何?」
nilは、ラテン語由来なんだけれど、何もない を表しているの。数で言ったら0に相当するわ。お皿の上に林檎が三つあることを、3と書くわよね。」
「うん、そうだよ。」
「じゃあ、お皿の上に全くりんごがなかったら?」
「うん、0だよ。」
「ええ、それと一緒で、配列は複数のデータを格納できるデータ構造・入れ物って紹介したけれど、そこには何も要素がない、データがないということを示しているのが、nilなの。」
「そうなんだね。ええ、林檎がないことを0という数を使って表したように、オブジェクトが存在しないことを表すのがnilよ。」
「そうなんだね。」
「ちなみに、今は配列の要素として、文字列を追加しているけれど、数を一緒にすることもできるわ。」
「そうなの。」
「ええ、じゃあ、menus[6] = 6なんてやってみましょうか。」
「うん、やって見るよ。」
「配列に6が追加されたかどうかみてみましょう。もう一度 menusって入力すれば良いの。」
「うん、6も表示されているよ。」
「他の言語だと、配列の中に入れられるのは同じ種類だけ、数字用の配列、文字列用の配列なんてしなくちゃいけなかったりするけれど、ここでもRubyはとっても柔軟でいいわね。」

配列要素の取得

「配列の要素を取得するには、添字というのだけれど、何番目の要素を取得したいのか、番号でしていするのが簡単だわ。0番目、1番目、2番目の要素を取得するために、menus[0]menus[1]menus[2]って書けばいいの。」
「うん、そうだね。」
「他にも最後の要素を指定したかったら、menus[-1]なんて指定方法もあるわ。負の数の添字を使うと最後の要素から数えてくれるわ。」
「すごい、便利だね。」
「ええ、プログラマが楽しくコーディングできるよう、柔軟性に富んでいるところがRubyの良いところよね。」

配列要素の更新

「要素の更新も簡単に行えるわ。menus[0] = "物理攻撃"menus[1] = "魔法"って感じで書くの。」
「うん、やって見る。」
「どう? menusってすると、確認できるわ。」
「うん、更新できたよ。簡単だね。」
「ええ、そうね。ちなみに"魔法"っていう要素が二つあるけれど、同じ要素が二つできてもOKよ。」

配列要素の更新

「じゃあ、最後は要素の削除をしましょう。」
「うん」
「要素の削除には二通りの方法があるわ。1つは添地で添事を指定して削除する方法、もう一つは値を削除して値を指定して削除する方法よ。」
「そうなんだね。」
「ええ、順番に見ていきましょう。」
delete_atメソッドを使うと、指定した位置にある要素を削除できるわ。menus[6] = 6 って書いて、要素を追加したじゃない。この追加した要素を削除してみましょう。」
「うん、どうやるの?」
menus.delete_at(6)で、削除できるわ。やってみて」
「うん。menusってタイプして配列の要素を確認してみたけれど、最後の要素が消えているね。」
「ええ。添字を指定して要素を削除することができるの。」
「じゃあ、もう一つの方法は?」
「値を指定して削除することができるわ。魔法が二つあるので、これを消すことにしてみましょうか。」
「うん」
menus.delete("魔法")って入力してみて。」
「うん、やって見る。」
「お〜、二つ消えているね。」

配列の要素数を取得する

「ということで、配列の要素数が、4つになっているわね。」
「うん、そうだね。」
「配列の要素数を数えるには、sizeまたはlengthメソッドを使うといいわ。」
「どっちでもいいの?」
「ええ、どちらでもいいの。配列の大きさだからsize、配列の長さだからlengthどちらも自然よね。なので、どちらを使ってもいいように別名(alias)として定義されているの。」
「そうなんだね。」
「どちらも4と返ってくるはずよ。やってみて。」
「うん」

irb を終了する

「それでは配列の作り方、要素の追加・取得・更新・削除、要素数を学んだところで、irbを終了してみましょう。終了するには、exitコマンドで終了できるわ。やってみて。」
「うん、終了できたよ。」
「ええ、対話的に簡単にRubyのコードを実行できるのがirbの良いところよ。ちょっと動作を確認したいなって時にも重宝するわ。どんどん活用していってね。」

学習した内容

irb

# 配列を作成する
menus = ["攻撃", "回復", "逃走"]
menus[0]
menus[5] = "魔法"
menus
menus[6] = 6
menus
menus[0] = "物理攻撃"
menus[1] = "魔法"
menus
menus.delete_at(6)
menus
menus.delete("魔法")
menus
menus.size
menus.length

exit


実行結果

配列と繰り返し

「配列の基礎も学んだわね。」
「うん。こんなふうに書けば表示できるんだったよね。」

menus = ["攻撃", "回復", "逃走"]
puts menus[0]
puts menus[1]
puts menus[2]

「ええ、そうよ。そしてね、Rubyには配列を使った繰り返しが簡単にできる、素敵なメソッドも用意されているの。」
「そうなの。どんなふうに使うの?」
eachメソッドというのがそれよ。こんな風に書くといいわ。」

menus = ["攻撃", "回復", "逃走"]
menus.each do |menu|
  puts menu
end

eachはそれぞれっていう意味なんだけれど、その名の通り、menusっていう配列の先頭から順番にそれぞれの要素を取り出してくれるの。doから始まってendまでで囲まれている部分をブロックっていうけれど、配列から取り出したそれぞれの要素はmenuっていう ブロック変数 に入るの。ブロックパラメタとも行ったりするわ。なので、menuには、最初は "攻撃"が入っているから、puts "攻撃" となって、"攻撃"が表示されて、次は "回復"が入っているから、puts "回復" となって、"回復"が表示されて、最後は "逃走"が入っているから、puts "逃走" となって、"逃走"が表示されることになるわ。」
「そうなんだね。」
「もし100個の要素がある配列だとしたら、puts menus[0] puts menus[1] puts menus[2] ... puts menus[99] なんて書いていられないもの。」
「うん、そうだね。100個も書くのはとっても大変そう。」
「あ、そして、これはちょっとしたポイントなんだけれど、配列名は複数形、ブロック変数は単数形 で命名するのがおすすめよ。複数形になっていると、たくさんの要素を中に持っている入れ物なんだなって、目印になって、コードを読む時の理解を助けてくれるわ。」
「うん、複数形にするんだね。わかったよ。」

「ええ、そして、ここでは、配列をmenusって変数に代入してから使ったけれど、配列だけでコードを書くこともできるわ。」

["攻撃", "回復", "逃走"].each do |menu|
  puts menu
end

「あとから、配列を特に使わないのであれば、もっと簡潔に書けるこちらの書き方もおすすめね。」
「うん。」

配列と繰り返し、添え字も添えて

「最初にやった時のように、番号をつけるにはどうするの?」

# コマンドを表示する
puts "1: 攻撃"
puts "2: 回復"
puts "3: 逃走"

eachメソッドに続けてwith_indexメソッドを使うといいわ。こんな風に書くの。」

["攻撃", "回復", "逃走"].each.with_index do |menu, index|
  puts "#{index}: #{menu}"
end

「もし 1 から始めたかったら、こんな感じね。」

["攻撃", "回復", "逃走"].each.with_index(1) do |menu, index|
  puts "#{index}: #{menu}"
end


実行結果

eachメソッドに続けて、.を入れてwith_indexメソッドで繋げるの。前にも話したけれど、メソッドチェーンがここでも使われているのよ。」

習得したい基本的なショートカット

「さて、irbでの実行例を出したけれど、irbやターミナル画面での入力は、何度も同じコマンドを入力することがよくあるわ。もちろん同じコマンドは何度も入力しても良いのだけれど、ちょっと手間と感じることもあるわよね。そういった時のために、履歴を活用する方法もあるわ。」
「そうなんだね。どうやってやるの?」
「簡単な上矢印キー↑を押すということなんだけれど。やってみて。」
「あ、ほんとだね。前に入れたコマンドを覚えているんだね。」
「ええ、そうよ。入力したいコマンドのところにたどり着いたら、そのままエンターキーを押せばいいわ。修正もできるから、バックスペースで消したりして試してみてね。」
「うん、やってみる。」
「戻り過ぎた時は下矢印キー↓を押せばいいわ。」
「ありがとう。」

「ということで、カーソルキーを使って履歴を移動する方法だったわ。 そしてね、ちょっとキーボードのホームポジションから離れたところにあるじゃない。」
「うん、そうだね。」
「だからね、なるべくなら指はポジションに置いたまま、操作したいわ。」
「うん、そうだね。」
「だからね。ショートカットキーって呼ばれるんだけれど、カーソル移動のためのショートカットキーも用意されているの。」
「そうなんだね。」
「ええ、例えば、次のような感じよ。」

ショートカットキーの表記

名前 記号
Control ^
Shift
Command
Option

カーソル移動

キーバインド 動作 意味
Ctrl + F カーソルを右へ移動 Forward 先へ進んで
Ctrl + B カーソルを左へ移動 Backward 後方へ
Ctrl + P カーソルを上へ移動 Previous 以前の行へ
Ctrl + N カーソルを下へ移動 Next 次の行へ
Ctrl + A カーソルを行頭へ移動 Ahead 前方へ
Ctrl + E カーソルを行末へ移動 End 行末へ

「カーソルを上に移動する代わりにCtrl + Pを押せばいいのよ。あ、CtrlキーとPキーを一緒に押すことを、Ctrl + Pって書くわ。Ctrlキーは、左の小指の横にあるし、Pの位置はもうみっくん、覚えているわよね。」
「うん、もう体が覚えているよ。毎日こつこつ見ないでタイプできるよう、練習したんだ。」
「みっくん、えらいわ。練習したのね。」
と、お姉様が褒めてくれる。

「他にも良く使うショートカットキーを紹介するから、是非習得してね。」

入力ソース切替

キーバインド 動作
Ctrl + Space 日本語入力と英数入力を切替

ファイル操作

キーバインド 動作 意味
Command + O ファイルを開く Open 開く
Command + S ファイルを保存する Save 保存する

テキスト編集

キーバインド 動作 意味
Command + Z 元に戻す
Command + X 切り取り
Command + C コピー Copy
Command + V 貼付
Command + A 全選択 All
Ctrl + H カーソルの左の文字を削除
Ctrl + D カーソルの右の文字を削除 Delete
Ctrl + K カーソル以降を切り取り Kill line
Ctrl + T カーソル前後の文字を入替 Transpose 転置

Pulsarエディタの基本操作

キーバインド 動作 意味
Shift + Command + D 行の複製 Duplicate
Shift + Ctrl + K 行の削除 Kill line
Command + / コメントアウト
Ctrl + F 検索(ファイル内) Find 見つけ出す
Shift + Ctrl + F 検索(プロジェクト内) Find 見つけ出す
Ctrl + G 任意行へカーソルを移動 Go
Command + ] インデントを追加
Command + [ インデントを削除
Command + K → 画面分割
Command + W 画面を閉じる Window close
Shift + Ctrl + P コマンドパレット Pallet
Shift + Command + C 色を選択 pigments

「じゃあ、次回は、今学んだ配列を使って、勇者がコマンド選択をやり直せるように作っていきましょうか。」
「うん、そうだね。 今日もいろいろ学べてよかったです。」
「こちらこそ。みっくんと楽しくお話しできて嬉しかったわ。」

そう言って、夕日と共にお姉さまは去っていく。

コンピュータは現代の魔法使い。
世界を救う勇者のように、いつか僕もすごいプログラムを作ってみたいなー。
そう、僕はワクワクしながら眠りについた。。。

Discussion