独自関数

プログラムを作っているときに、同じような計算を何度も行う必要があったり、一つの式では表すことができない複雑な計算を行わなければならないことに時々出くわします。

複雑な計算の式は、それを見ただけでは何の式かわかりません。例えば、以下の式はどんな計算をしているのでしょうか?

// mx,myは自分のキャラクターの座標
// ex,eyは敵のキャラクターの座標
sqr(pow(abs(mx-ex),2)+pow(abs(my-ey),2))

この式は、自分のキャラクターと敵のキャラクターとの画面上での距離を計算しています。組み込み関数と同じように、この式に名前を付けて関数として作ることができると便利になりそうです。

独自関数の作り方

Jasmine Tea では、式の中で利用することができる独自関数をプログラムから作ることができます。独自関数は、function 命令を使って作ります。

function calc_distance(mx,my,ex,ey)
  return sqr(pow(abs(mx-ex),2)+pow(abs(my-ey),2))
end function

function 命令は、パラメーターとして独自関数の名前と、独自関数の中で必要となる数値や文字列を受け取るための変数(これを仮引数と呼びます)を記載します。上記のプログラム例では、独自関数の名前として、calc_distance(距離の計算の意)としています。そして、以下の仮引数を作っています。

  • mx - 自分のキャラクターの横方向の位置
  • my - 自分のキャラクターの縦方向の位置
  • ex - 敵のキャラクターの横方向の位置
  • ey - 敵のキャラクターの縦方向の位置

この例では、すべての仮引数は数値変数となりますが、文字列変数として仮引数を作ることもできます。

function 命令から end funciton 命令の間に、行いたい計算や処理を書きます。そして、独自関数での計算結果は、return 命令を使って決定します。ここでは、自分のキャラクターと敵のキャラクターの距離を計算して、その結果を return 命令のパラメーターに指定します。

では、calc_distance 命令を実際に使ってみましょう。if 命令を使って、自分のキャラクターと敵のキャラクターの距離が 100 未満かどうかをチェックして、処理を条件分岐するプログラムは、以下となります。

// mx,myは自分のキャラクターの座標
// ex,eyは敵のキャラクターの座標
if calc_distance(mx,my,ex,ey)<100 then
  // 距離が100未満だったときの処理
end if

複雑な計算式と違って、上記のプログラム例では、キャラクター同士の距離に基づいて条件分岐が行われていることが明確になりました。

もう一つ例を紹介しましょう。組み込み関数の inkey$ 関数から得られたキーの文字列から、上下左右のどちらに移動するかの数値(direction 命令で使う方向を示す数値)を決定するための処理を考えてみましょう。この処理は、Jasmine Tea のプログラムとして、以下のように書くことができます。

let k$=inkey$()
if k$="ArrowUp" then
  d=1
else if k$="ArrowRight" then
  d=3
else if k$="ArrowDown" then
  d=5
else if k$="ArrowLeft" then
  d=7
else
  d=0
end if

上記のプログラムを関数にすると、以下のようなプログラムになるでしょう。

function to_direction(k$)
  if k$="ArrowUp" then
    return 1
  else if k$="ArrowRight" then
    return 3
  else if k$="ArrowDown" then
    return 5
  else if k$="ArrowLeft" then
    return 7
  else
    return 0
  end if
end function

このように、複数の命令から構成される関数を独自に作成することもできます。この to_direction 関数を使ったプログラム例が、以下となります。

let k$=inkey$()
d=to_direction(k$)
if d<>0 then
  direction 0,d
end if

変数のスコープ

Jasmine Tea のプログラムは、様々な情報を記憶しておくために、変数を使うことができます。1つの変数には、数値または文字列を1つ記憶しておくことができます。

基本的には、プログラムのどの行でも、変数を使うことができます。しかし、ある行で作られた変数が、特定の行からは使えない、という状況があります。

Jasmine Tea のプログラムは、1行目から順に実行されます。実行が開始されたときに、Jasmine Tea は内部で「メイン変数スコープ」と呼ばれる変数の記憶領域が作られます。下図は、1行目にて作られた変数 x がメイン変数スコープの中に作られている様子です。

user-function-1

3 行目の if 命令の条件式にて、独自関数の double 関数が使われています。doule 関数によって独自関数にジャンプする際に、Jasmine Tea では新しく変数スコープを作成します。

user-function-2

上図では、3行目の double 独自関数の呼び出しによって、6行目から9行目の double 独自関数にジャンプしています。この際に、Jasmine Tea は double 独自関数向けに、新規に変数スコープの記憶領域を作成します。そして、独自関数に渡された数値や文字列は、仮引数として書かれた変数として double 変数スコープに作成されます。つまり、メイン変数スコープに存在する変数 x と、double 変数スコープに存在する変数 x は、名前は同じですが、別の変数です。

異なる変数スコープに記憶されている変数は、使うことができません。例えば、メイン変数スコープに変数 y が存在していたとしても、double 独自関数の中からは利用することができません。そのため、作成した独自関数の中で必要となる数値や文字列は、必ず仮引数として記載しておく必要があります。

独自関数を呼び出す度に、新規に変数スコープが作成されます。例えば、double 関数の中から更に double 関数を呼び出す(これを再帰呼び出しと言います)際にも、新規に変数スコープが作成されますので、注意しましょう。