×

[PR]この広告は3ヶ月以上更新がないため表示されています。
ホームページを更新後24時間以内に表示されなくなります。

1次関数のグラフ


中学校の頃に習った、1次関数のグラフを描くプログラムを作ってみます。
y = ax + b の、a(傾き)とb(切片)をテキストボックスに入力して実行するとグラフを描いてくれるような感じです。
方眼紙のような目盛りが付けば尚良し。
目盛りは後回しにするとして……
1次関数だからと、直線を引くのでは芸がないし、この後他の関数のグラフに使いまわせません。
点を細かく打ってグラフを作りたいのです。
つまり、y = 5x + 2 なら、(0, 2)(1, 7)(2, 12)(3, 17)……のように、xを変化させた時のyの値を計算し、その点を繋げば直線になるだろう、と。

これは「For ループ」を使えば簡単そうです。

For i = 1 To 100
(なんかの処理)
EndFor

これで、「なんかの処理」を、i=1からはじめて、i=2、i=3、……、i=100まで繰り返してくれます。
x=i、y=5i + 2とすれば1次関数になりますね。
GraphicsWindow.DrawEllipse」で座標を指定し楕円を描くことができますが、この楕円の横幅と高さを1に設定すれば、1ドットの点になります。
1ドットの点を繰り返し描かせれば線になるでしょう。

GraphicsWindow.DrawEllipse(x座標, y座標, 楕円の横幅, 楕円の高さ)

だから、

GraphicsWindow.DrawEllipse(i, 5i + 2, 1, 1)

こういう感じかな?
これと「For ループ」を組み合わせれば、点をいっぱい描写することで直線が描けるでしょう。

しかし、ひとつ問題があります。
原点(0,0)の指定方法です。
GraphicsWindowでウィンドウを書いた場合、ウィンドウの左上を(0,0)として、x軸は右方向が正の値、y軸は下方向が正の値となります。

グラフ1

つまり……

x座標→iの値に、画面横幅の1/2の値を加える。
y座標→(5i + 2)の計算結果にマイナスをかけて(正負を入れ替える)、画面縦幅の1/2の値を加える。

こうすれば、ウィンドウの中央付近を原点にできるでしょう。
また、y座標にマイナスをかけることで、y軸の上方向を正の値にできます。

そして、iの値も単純に0から100では駄目ですね。
例えば画面の幅が500なら、原点が中央にずれるから、xは-250から+250までということになります。

……最初にウィンドウのサイズを適当な変数で決めておく方が、プログラムを書く時に混乱しないかもですね。

ということで、まずはウィンドウを作ります。

GraphicsWindow.Title = "Graph"
GraphicsWindow.BackgroundColor = "white"
windowsize = 600
GraphicsWindow.Width = windowsize
GraphicsWindow.Height = windowsize

この後にウィンドウのサイズが重要になるので、変数「windowsize」でウィンドウサイズを決めておきました。
高さも幅も「windowsize」にしたので、正方形のウィンドウが描かれることになります。

続いて、ウィンドウに、x軸とy軸、傾きと切片を入力するためのテキストボックス、グラフを描画するためのボタンを設置します。

GraphicsWindow.PenColor = "blue"
GraphicsWindow.DrawLine(0, windowsize/2, windowsize, windowsize/2)
GraphicsWindow.DrawLine(windowsize/2, 0, windowsize/2, windowsize)

GraphicsWindow.DrawText(10, 10, "y =")
GraphicsWindow.DrawText(75, 10, "x +")

katamuki = Controls.AddTextBox(40, 10)
Controls.SetSize(katamuki, 30, 20)

seppen = Controls.AddTextBox(100, 10)
Controls.SetSize(seppen, 30, 20)

Controls.AddButton("Graph", 200, 10)
Controls.ButtonClicked = OnTick

最初の行はx軸とy軸を描くペンの色を青に設定しています。
2行目と3行目でx軸とy軸を描画しましたが、ここで変数「windowsize」を利用して、座標の位置を決定しました。
変数「windowsize」の丁度半分の位置に十字に線を引く、というプログラムです。

それ以降で、1次関数の式を入力する為のテキストボックスを描画しています。
傾きを入力するテキストボックスを「katamuki」、切片を入力するテキストボックスを「seppen」にしました。

また、下から2行目はグラフを描画するためのボタンです。
最後の行で、グラフ描画ボタンを押した時のサブルーチンを「OnTick」としました。

サブルーチン「OnTick」は以下の通り。

Sub OnTick
a = Controls.GetTextBoxText(katamuki)
b = Controls.GetTextBoxText(seppen)
  For i = -windowsize/2 To windowsize/2 Step 1
    x = i
    y = -a * i - b
    GraphicsWindow.PenColor = "red"
    GraphicsWindow.DrawEllipse(x + windowsize/2, y + windowsize/2, 1, 1)
  EndFor
EndSub

2つのテキストボックスから値をとって、For ループを使い、x座標とy座標を計算しては代入、計算しては代入……を繰り返しています。
グラフを描くペン色は、x軸y軸と被らないように赤色にしました。
GraphicsWindow.DrawEllipseで、実際にグラフの点を描画していますが、ここでグラフの原点をズラすため、画面幅の1/2を足しています。

以上を全て合わせたプログラムは以下の通り。

GraphicsWindow.Title = "Graph"
GraphicsWindow.BackgroundColor = "white"
windowsize = 600
GraphicsWindow.Width = windowsize
GraphicsWindow.Height = windowsize

GraphicsWindow.PenColor = "blue"
GraphicsWindow.DrawLine(0, windowsize/2, windowsize, windowsize/2)
GraphicsWindow.DrawLine(windowsize/2, 0, windowsize/2, windowsize)

GraphicsWindow.DrawText(10, 10, "y =")
GraphicsWindow.DrawText(75, 10, "x +")

katamuki = Controls.AddTextBox(40, 10)
Controls.SetSize(katamuki, 30, 20)

seppen = Controls.AddTextBox(100, 10)
Controls.SetSize(seppen, 30, 20)

Controls.AddButton("Graph", 200, 10)
Controls.ButtonClicked = OnTick

Sub OnTick
a = Controls.GetTextBoxText(katamuki)
b = Controls.GetTextBoxText(seppen)
  For i = -windowsize/2 To windowsize/2 Step 1
    x = i
    y = -a * i - b
    GraphicsWindow.PenColor = "red"
    GraphicsWindow.DrawEllipse(x + windowsize/2, y + windowsize/2, 1, 1)
  EndFor
EndSub

実行結果。

グラフ1

プログラムを実行すると、x軸とy軸が描かれます。
また、テキストボックスに傾きと切片を入力できる状態になりました。
傾きに2、切片に20を入れて、「Graph」ボタンをクリックします。

グラフ2

1次関数のグラフが描かれました。

グラフ3

傾きaの絶対値が大きいと、点の隙間が広がってしまい、こういう見た目になってしまいます。

For i = -windowsize/2 To windowsize/2 Step 1

の「Step 1」(1刻み)を「Step 0.1」(0.1刻み)のように変更すれば、隙間が狭くなります。
ただしグラフの描画(計算)に少し時間がかかるようになりますが。

このグラフは、方眼紙でいえばマス目が1ドット×1ドットです。
マス目を10ドット×10ドットくらいにした方が、1次関数を習っている最中の中学生には理解しやすいでしょう。
10ドット×10ドットの方眼紙を描くにはどうすればいいか?
これも「For ループ」を使って描けるかな?

GraphicsWindow.DrawLine(0, windowsize/2, windowsize, windowsize/2)

これがx軸を描く処理です。
x軸から上に10ドット移動したところにもう一本線を引きたい。
更にその上に10ドット移動したところにもう一本線を……
を、ウィンドウの上限まで繰り返せばx軸に平行な線をたくさん引けそうです。
もちろん、下に10ドットずつずらして書くのもくわえなければ、ウィンドウ全体に線が引けませんので……

For i = 1 To windowsize/20
   GraphicsWindow.PenColor = "PowderBlue"
   GraphicsWindow.DrawLine(0, windowsize/2 + i * 10, windowsize, windowsize/2 + i * 10)
   GraphicsWindow.DrawLine(0, windowsize/2 - i * 10, windowsize, windowsize/2 - i * 10)
EndFor

ペンの色に「PowderBlue」を指定して書いてみました。
iは1から、画面サイズの半分を10で割った値までになります(10ドット置きに線を引くから)。
同じことをy軸でもやってみると……

For i = 1 To windowsize/20
   GraphicsWindow.PenColor = "PowderBlue"
   GraphicsWindow.DrawLine(windowsize/2 + i * 10, 0, windowsize/2 + i * 10, windowsize)
   GraphicsWindow.DrawLine(windowsize/2 - i * 10, 0, windowsize/2 - i * 10, windowsize)
EndFor

以上を付け加えて方眼紙が作れるはず。

グラフ4

割と細かい目になってしまった……。

あとは、描く座標を10倍すればOKのはずです。
描画する「For ループ」は以下のように変更しました。

For i = -windowsize/2 To windowsize/2 Step 0.1
   x = i
   y = -a * i - b
   GraphicsWindow.PenColor = "red"
   GraphicsWindow.DrawEllipse(x * 10 + windowsize/2, y * 10 + windowsize/2, 1, 1)
EndFor

Stepが1刻みだったのを、0.1刻みに変更。
また、GraphicsWindow.DrawEllipseで描くグラフの点は、x,y座標を10倍してから、画面幅の1/2の値を足しています。

グラフ5

傾きや切片の値がわかりやすくなった……かな。

方眼紙込み完成形は以下の通り。

GraphicsWindow.Title = "Graph"
GraphicsWindow.BackgroundColor = "white"
windowsize = 600
GraphicsWindow.Width = windowsize
GraphicsWindow.Height = windowsize

For i = 1 To windowsize/20
GraphicsWindow.PenColor = "PowderBlue"
GraphicsWindow.DrawLine(0, windowsize/2 + i * 10, windowsize, windowsize/2 + i * 10)
GraphicsWindow.DrawLine(0, windowsize/2 - i * 10, windowsize, windowsize/2 - i * 10)
EndFor

For i = 1 To windowsize/20
GraphicsWindow.PenColor = "PowderBlue"
GraphicsWindow.DrawLine(windowsize/2 + i * 10, 0, windowsize/2 + i * 10, windowsize)
GraphicsWindow.DrawLine(windowsize/2 - i * 10, 0, windowsize/2 - i * 10, windowsize)
EndFor

GraphicsWindow.PenColor = "blue"
GraphicsWindow.DrawLine(0, windowsize/2, windowsize, windowsize/2)
GraphicsWindow.DrawLine(windowsize/2, 0, windowsize/2, windowsize)

GraphicsWindow.DrawText(10, 10, "y =")
GraphicsWindow.DrawText(75, 10, "x +")

katamuki = Controls.AddTextBox(40, 10)
Controls.SetSize(katamuki, 30, 20)

seppen = Controls.AddTextBox(100, 10)
Controls.SetSize(seppen, 30, 20)

Controls.AddButton("Graph", 200, 10)
Controls.ButtonClicked = OnTick

Sub OnTick
a = Controls.GetTextBoxText(katamuki)
b = Controls.GetTextBoxText(seppen)
 For i = -windowsize/2 To windowsize/2 Step 0.1
    x = i
    y = -a * i - b
    GraphicsWindow.PenColor = "red"
    GraphicsWindow.DrawEllipse(x * 10 + windowsize/2, y * 10 + windowsize/2, 1, 1)
 EndFor
EndSub

次:反比例・2次関数のグラフ


▲TOPへ戻る