ホームページ | Pirikaで化学 | ブログ | 業務案内 | お問い合わせ |
情報化学+教育トップ | 情報化学 | MAGICIAN | MOOC | プログラミング |
2022.2.20
Pirika.comでプログラミング
山本博志
コンピュータへの指令書の事をプログラムと言います。
プログラミングはこの指令書を書くことです。
日本語で扱えるものもありますが、とても簡単な単語程度の英語なので覚えてしまいましょう。
コンピュータは種類によって指令書の書き方が違っているので、どのコンピュータでも動くようなプログラミングを作るのは大変です。
そこで、最近のコンピュータなら(PC, Mac, iPhone, iPadのタブレットまで皆コンピュータです)ホームページを見るためのブラウザーはどのコンピュータも持っている事に着目します。
ブラウザーで表示するページを作った時に、ブラウザーの種類やハードウエアーの違いで見えたり、見えなかったりすると大変です。
そこで、画面の大きさの問題はあるとしても、共通に利用できるページの規格が必要になります。
それの規格が、htmlという規格です。
htmlというのは、ハイパー・テキスト・マークアップ・ランゲージの略です。
現在は第5版なのでHTML5とか呼ばれています。
ブラウザーは何かを読み込んで表示しようとした時に、ファイル名の後ろの文字に注目します。
ファイル名.htmlになっていた場合には、このファイルはhtmlの作法で読み取ろうって考えます。
その他よく出てくるものとしては、画像ファイルの時には、.jpgや.png、単なるテキストの時には.txtというように、アルファベットの3-4文字とアプリとを結びつけています。
このようなアルファベットの3-4文字の事を拡張子と呼びます。
こうした指令書を作ってコンピュータに何かをやらせようとした時、人間とコンピュータがやりとりする仕掛けが必要になります。(もちろん、やりとりの必要のないプログラムもあります。例えば車のエンジン用のプログラムは、エンジンとは会話しているかもしれませんが人とは口もきいてくれません)
人間とやりとりといっても、人間の知覚は5感の見る、聞く、嗅ぐ、味わう、触覚ぐらいで、実際に使えるのは視覚、聴覚ぐらいでしょう。
htmlの中に大きく分けて2つの領域があります。
ページの大前提のような、ヘッダー部分
人間が見て理解できる、ボディー(本体)分です。
そして、html5からは、ボディー部分にコンピュータに対する指令書、プログラムを書くことができるようになっています。
この1枚の指令書があれば、どのブラウザーでも、どのコンピュータでも動くのでとても便利です。
ファイルには、人間が読めるテキスト・ファイルと、コンピュータだけが読めるバイナリー・ファイルがあります。
バイナリーファイルは、英数字だけのファイルなので、ここでは詳しく説明しません。
例えば、画像データはバイナリー・データで、それを各ドットの色で再構築するとイメージに見えます。
テキストファイルは、ここで読んでいるような文章が書き込まれたファイル形式です。
ただ、文字の大きさや色、段落などを(コンピュータが)制御する符号が入ったりするので、ちょっと読みにくいテキストになります。
制御文字が入らないテキストをプレイン(ただの)テキストと呼びます。
ワードプロセッサーなどのアプリケーションで文章を作成すると、書いてある内容はテキストでも、アプロケーション特有の形式の(バイナリー)ファイルになるので、作ったアプリケーションでしか開けなくなります。
そこで、どのアプリケーションで作ったかを区別するため、拡張子(.3−4文字)をつけます。
プレインテキストの拡張子は、txtで、これはほとんど全てのアプリケーションで読み書きできます。
アプリケーション・ソフトの中でも、Windowsであればメモ帳、Macであればテキストエディットは余計な制御コードを付け加えないので、プログラムを書くのに適しています。
より本格的にプログラム開発を行いたいのであれば、Visual Studio Codeや、Macであれば、mi, CotEditor, MacDown、iPadであればTaioなどがお勧めです。
ここで作成するのは、制御文字付きのテキスト・ファイルです。
HTML(HyperText Markup Language)と言う、ブラウザー・アプリケーションが理解できるタグという制御コードが入るので、拡張子は.htmか.htmlになります。
しかし、ブラウザー・アプリケーションは、htmlのテキストファイルを読むのが専門で、書くのは別のアプリケーションを使うことが話を難しくします。htmlエディターなどのキーワードで検索するといろいろなものが見つかります。
今回作成するのは、htmlにプログラムの機能を付け加えるため、htmlエディターよりは、コードエディターの方が使いやすいかもしれません。
最初は、メモ帳やテキストエディットを使い、慣れてきたら他のものを使って行きましょう。
大事な点は、ファイルを保存する時には、拡張子にhtmlを必ず付けることです。
全角のhtmlなどはダメです。半角にしましょう。
保存されたファイルをダブルクリックをすると、自動的にブラウザーで開かれてしまいます。Chrome, Edge, Safari, FireFox、それ以外、どれになるかは設定次第で変わります。
すると、ファイルを修正しようとすると困ります。
メモ帳やテキストエディットから、開くを使うか、保存されたファイルをマウスで右クリックして開くソフトを選択します。
この辺りが、不便で難しいです。
開発にiPadを使うのは、この辺りが難しいです。TaioはMarkDownエディターでかつJavascriptの実行環境でもあるので、これを使うのがいいのかもしれません。
次に作ったファイルをどこに置くかです。
階層型ディレクトリー・システムがわかる人なら「書類の中にMyHtmlフォルダーを作り、作成したファイルはそのフォルダーに入れてください」で済むのでとても簡単です。画像ファイルは、その中にimagesフォルダーを作ってそこに集めます。
問題は、iOSなどを使う、iPad,iPhoneでは、階層型ディレクトリー・システムが(見かけ上)無いので、この説明では理解できない方が大勢いるという事です。
昔のコンピュータは、計算をするCPUと一時的にプログラムやデータを蓄えるメモリがあって、ファイルなどは外部記憶装置に保存しました。ハードディスク、USBメモリー、DVD(CD),磁気テープなどがその外部記憶装置でした。
ところが最新のデバイスは、プログラムやデータはもともとメモリ上に持っているので、アプリケーションを使って作ったファイルもメモリー上にあり、「保存する」という概念がなくなってしまいました。
見かけ上、アプリケーションの中に作成したファイルも含まれてしまっているようなものになってしまいました。
そうなってしまうと、htmlファイルとimageファイルの依存性を考えた配置はできなくなります。
iPadは単なるユーザーとしての利用はとてもやりやすいですが、中身をクリエイトしたい場合には、とてもやりにくいマシンだと言えます。
他にやり方があれば、ぜひ教えてください。
自分は、Mac側でDropBoxやiCloudにファイル構造を作り、iPad, iPhoneからそこへアクセスしています。
単体だけでどう使っていいのかは、いまだに不明です。
階層型ファイルシステム:
今回作成しているプログラムは、ブラウザーが理解、実行できるプログラムを目指します。
ブラウザーが理解できるページは、HTML(HyperText Markup Language)と言う形式で書きます。これは、文字の大きさや色、ブラウザー中での配置などが自由にできる書き方ですが、静的なページになります。
書き方としてはタグというものを使います。
タグというのは、<XXX> のように<>で囲まれたものです。始まりのタグに対して終わりのタグ、</XXX>とのペアで使います。
このhtmlの中には大きく分けてヘッダーとボディーがあります。
<head>から</head>の間には細かい設定やらタイトルなどを書きます。
<body>から</body>の間に本文を書きます。
<html>
<head>
設定
</head>
<body>
本文
</body>
</html>
リンクというのは、マウスでクリックした時に、違うページに飛んだりするのに使われます。このページの上部にあるメニューもリンクになっています。
基本的な使い方は<a> </a>の間にクリックする文字列(pirikaのホームページなど)を書きます。そして、その文字列がクリックされた時に飛んでいく先をhrefに書きます。
<a href="https://www.pirika.com/">pirikaのホームページ</a>
このようにbodyタグの中に書くと、次のようなリンクが表示されます。
pirikaのホームページ
3択では、各問題の3択の答えにリンクが貼られています。
これは問題によって3択は変わるので、問題ごとに動的に(いつも同じでないという意味)作成します。
countは問題番号を、nは3択のどれかを示しています。
s += "【 <a href='javascript:anser(" + n + ")'>" + qa[count][n] + "</a> 】";
例えば、問題の0番目(count=0)は次のようになっています。
qa[0][0]="水素の元素記号は?"
qa[0][1]="Hg"
qa[0][2]="H";
qa[0][3]="He";
qa[0][4]=2;
そこで、Hg, H, Heについて次のようなリンクを作ってあげます。
[Hg] [H] [H2]
[<a href="">Hg</a>] [<a href="">H</a>] [<a href="">H2</a>]
ここではリンク先は入れていませんが、実際には、'javascript:anser(" + n + ")に飛びなさいと書いてあります。
これはjavascriptプログラムの中の、anser関数にnの値を持って飛びなさいという命令になります。
この命令を3つ分、変数sに順番に代入して、変数sをtext_sの位置に表示させます。
変数sが質問のたびに変わるので、text_sの表示が変わるのです。
document.getElementById("text_s").innerHTML = s;
HTMLの仕様もだんだん良くなってきて、HTML5からはお絵描き用のキャンバスなどが豊富に使えるようになってきました。
3択で使うのは、ボタンとテキストエリアです。
テキストエリアは複数の行を持つテキスト領域です。
<textarea name="GetText" id="textarea1" cols="80" rows="10"></textarea>
これをhtmlファイルの<body> </body>の間の適当な所に貼り付けるとテキストエリアと呼ばれる領域が下記のように現れます。
cols="80" rows="10"と言うのは列が80文字、行が10行の大きさを示しています。
何も処理をしないと、テキストエリアにはtabを入力できません。ですから、手動でデータセットを作れないので、エクセルからのペーストにします。
ボタンは次のように作成する事ができます。
<input type="button" id="ReadBtn" value="テキストエリアを読み込む" onclick="XXX();">
valueには、ボタンに表示される文字列を入れます。
このボタンをクリックすると、XXX()というjavasxcriptのXXX関数が実行されます。
この2つのパーツのidはjavascriptのプログラムからアクセスするときに必要になるので必ず(重複しないように)設定します。
ボタンなどが押された時など動的な表現はプログラムが行います。
このプログラムはJavaScriptと言う言語が使われます。
これを、<body>から</body>の間に置きます。
<script type="text/javascript">
</script>
以上がhtmlを構成するパーツの説明になります。
プログラムの中には、単なる説明、コメントとして実行させない部分を入れることができる。
//ならそれ以降の1行
/* */ で囲まれた間全部
がコメント行になります。
特に//は多用します。
プログラムで実現したい機能をいくつかの関数(function)に分けて記載します。
3択問題では、標準で4つの関数、テキストエリアを読み込むように改造した場合には5つの関数があります。
日本列島を都道府県に分けて、塊とみなすようなモノです。
一つだけ、anser関数は括弧の中にnumというのが入っています。
これは引数と呼ばれるものです。
関数を呼んだ側でnumに何かを入れてanserに送り付けています。
この3択問題では、3択の何番目かをnumに入れています。
function setReady() {
}
function quize(){
}
function anser(num) {
}
function nextQuize(){
}
function GetTextArea(){
}
プログラムでは変数を使う事ができます。
変数というのは「変わる数の入れ物」だと思ってください。
一番簡単には次のように使います。
var Hensuu=10;
以降、プログラム中ではHensuuは数字の10として扱われます。
var Kotae=Hensuu - 3;
のように計算結果を他の変数に代入したりする事ができます。
変数には数字だけでなく、文字列を代入する事ができます。
var MojiHensuu="pirikaで楽しくプログラミング";
最近は、var の代わりに let や constを使うことも増えてきました。
ただし、古いソフトではサポートしていないこともあるので注意が必要です。
入れる中身によって、器を別々に用意するので、すぐにあふれかえってしまします。
変数は使う場所によって、グローバル変数とローカル変数に分かれます。
<script type="text/javascript">
var q_sel = 3; //選択肢の数
var Seikai=0;//正解の数
function quize(){
var s, n;
}
</script>
functionの中で定義されている、var s, nはquize()という関数の中だけで使えます。
(他のfunction中では使えない。)
そこで、ローカル変数と呼ばれます。
それに対して、関数の外で定義された、var q_sel = 3; やvar Seikai=0;はどの関数(function)の中でも使えるので、グローバル変数と呼ばれます。
円は日本中どこでも(グローバルに)使えますけど、地域振興券は発行した自治体(ローカル)でしか使えないのと同じです。
変数の連結には、+を使います。
特に、文字変数で結果表示などに使います。
変数countにはクイズの番号(0-9)が入っています。
var s;//文字変数に使う
var d;//数値変数に使う
d=count+1;//クイズの番号を0-9から1-10へ
s = d + "問目:";//変数の連結、数字+文字列
var ans="あたり!”;
s += ans;//文字列、文字列連結
s += ans;
s = s + ans;
この2つは同じものです。上の書き方は省略形です。 算数で習った=(等号)とは意味が違うので注意が必要です。
意味は、「右辺、s+ansを左辺の変数sに代入しなさい」という命令です。 たまたま、左辺の変数が右辺でも使われているだけです。 その場合には、右辺、s(旧)+ansを左辺の変数s(新)に代入しなさい」と新旧を補ってあげるとわかりやすいです。
1つの変数には1つの値しか入れられません。
そうすると変数が増えてくると大変です。変数名を使うのも大変になります。
そこで、変数に数字をつけた配列という変数が用意されています。
例えば、3択の問題が10種類あったとすると、
qa[0],qa[1],qa[2] ,,,,,qa[9]
の変数が使えれば良いわけです。
これは、ループの中で、順番に違う変数を参照したいときに特に便利です。
Array()という命令を使うとqaを配列として定義できます。
これには2つの定義の仕方があって、Arrayの()の中に何も入れない場合と、明示的に変数10個(添え字は0-9の10個)、Array(10)と定義する事があります。
何も入れないのは、実際にその配列を使い始めるまで変数を何個まで使うか決まっていない場合には便利です。
qa = new Array();
var qa = new Array(10);
配列をさらに2重にする事もよく行われます。
これはおでん鍋を思い浮かべてください。
Oden[0][0]には"大根”を入れる。
Oden[0][1]には”卵”を入れる。
Oden[1][0]には”こんにゃく”を入れる。
Oden[2][3]には”昆布”を入れる。
この2重の配列を作る時には、使うときにArray()で定義します。
Oden[0]=new Array()
とすれば、Oden[0][0]- Oden[0][X]が使えるようになります。
配列の配列を作るときに、質問が100個あり、いちいちArray()関数を書くのは大変です。
しかも質問が何個あるかは事前にはわかりません。
このような時には、繰り返し(ループ)を使います。
(ちなみに、今年のオリンピックの収穫は、アクセルが人の名前だと知ったことです!)
繰り返しには、forループとwhileループがあります。(JavaScriptにはトウ・ループはありません)
回す回数が決まっている時には、forループ。
条件で回る回数が変わる場合には、whileループを使います。
3択クイズではforループしか使っていません。
forループは( )の中の回数{ }の間を繰り返すという命令になります。
for(var i=0;i<10;i++){
qa[i]=new Array();
}
( )の中身
var i=0;i<10;i++
var i=0 :変数iを定義して、iに0(ゼロ)を代入する。そして{ }の中の命令を実行する。
つまり、qa[0]=new Array();を実行する。q[0]を2次元配列にする。
i++:{ }ループから戻ると、右端のi++が実行される。iは1になる。
i<10:右端i++が実行された後、i<10, iが10より小さい時には、{ }の間が実行される。
{}ループから戻ると、またi++が実行され、i<10が評価され、全部で10回ループが回ります。
次のようなバリエーションがある。
<, >:不等号記号
<= , >= :イコール(等しい)も許す不等号
i-- :iの値を一つ減らす。
i=i+2:iの値を2つ増やす。
iを1増やします。
i--なら1減らします。
条件分岐には、if文とswitch文がありますが、3択クイズではif文しか使っていません。
if文の説明の前に、
3択クイズの1問目の質問と答えは次のようになっています。
qa[0] = ["水素の元素記号は?","Hg","H","He",2];
これは次と同じです。
qa[0][0]="水素の元素記号は?";
qa[0][1]="Hg";
qa[0][2]="H";
qa[0][3]="He";
qa[0][4]=2;//正しいのは2番目、qa[0][2]
if文は基本形は次のように使います。
if(条件式){
条件式が正しい時に実行される命令
}
else{
条件式が正しくない時に実行される命令
}
条件式は
<, >:不等号記号
<= , >= :イコール(等しい)も許す不等号
までは、分かりやすいでしょう。
数学的には少し変なのですが、等しいことを示す条件式は
==
と=を2回繰り返します。
3択クイズでは次のように使われています。
numは3択の何番目を選んだかの数字が入っています。
countは問題の番号です。
if (num == qa[count][4]) {
//正解
ansers[count] = "あたり! ";
Seikai++;
} else {
ansers[count] = "はずれ! 答えは "+ qa[count][qa[count][4]];
}
条件式、num == qa[count][4]は、『3択の何番目を選んだか』と 『qa[count]配列の4番目が(正解の番号)』が等しかったら、{ }の中を実行しろと言っています。
{ }の中には、ansers[count] = "あたり! "; snsers配列に"あたり!”という文字列を代入して、Seikaiの数値変数を1つ増やす命令があります。
else{ }の中には外れた時の処理が書かれています。
bodyタグの中にある、ボタンはクリックされると、javascriptプログラムの中のGetTextArea()関数へ飛んで、その関数の中身が実行されます。
<input type="button" id="ReadBtn" value="テキストエリアを読み込む" onclick="GetTextArea();">
また、javascriptプログラムの中の変数は、次のようにしてbodyタグ中のhtml要素に値を代入する事ができます。
div要素、id="text_q"をbodyタグ中に置きます。
<div id="text_q"></div>の間には何もないので最初は何も表示されません
<div id="text_q"></div>
そこにjavascriptのプログラムの側で次のように書くと、count番目のクイズの問題が表示されます。
document.getElementById("text_q").innerHTML = (count + 1) + "問目:" + qa[count][0];
document.getElementById("textq")というのは、文章が書かれている部分の中で、idが"textq"の部分を探してきて、そのinnerHTML に文字列変数を代入しなさい、という命令になります。
代入する文字列は、(count + 1) + "問目:" + qa[count][0]になります。
<div id="text_q"></div>の間にそのテキストが挿入されます。
画像を挿入するだけなら、imgタグを用いれば表示できます。
<img src="./images/Santaku.png" alt="サンタが3択苦労す">
しかし、これでは、途中で表示を入れ替える事ができません。
そこで、imgタグだけ用意しておき、ボタンが押された時にimg要素を取り出します。
そしてimgのソースに画像を指定します。
<img id="image_place" src=""><br>
<button onclick="changeImage()">画像の読み込み</button><br>
<script type="text/javascript">
// img要素を取得する
let img = document.getElementById("image_place");
function changeImage(){
img.src = "./images/Pafe.jpg";
}
</script>
htmlとjavascriptの連携を使い、id=textarea1を、textAreaValue変数に代入します。この変数にはdocument関係の色々なデータが代入されてしまいます。
そこで、テキストエリアの中身だけMyText文字列変数に代入します。
function GetTextArea(){
var textAreaValue = document.getElementById("textarea1"); // htmlでID textarea1の内容を取り出す。
var MyText = textAreaValue.value;//テキトエリアの内容を代入
}
文字列を分割します。
MyTextには次のようなデータが入っています。
No | Question | Ans1 | Ans2 | Ans3 | RA |
---|---|---|---|---|---|
0 | 水素の元素記号は? | Hg | H | Su | 2 |
9 | ヘリウムの元素記号は? | He | She | I | 1 |
2 | ネオン元素記号は? | No | Nd | Ne | 3 |
各行の間には、目には見えませんが改行コード("\n")が入っています。この改行コードはwindowsとMac/Unixで異なるのですが、ネットの世界では一つです。
そこで、この改行コード("\n")に着目して、MyTextを行ごとに分割して配列変数へ代入することを考えます。
まず、MyLine変数を定義します。これは普通の単独の変数です。
テキストエリアの中身を入れたMyText文字列変数に.split("\n")をくっつけると、( )の中の文字によってMyTextを分割します。
var MyLine;//変数を定義
MyLine = MyText.split("\n");//テキトエリアの内容を改行コード\nで分割して、MyLine配列へ代入する。
var lines = MyLine.length; //how many lines
そして、素晴らしいことに、自動で、MyLineを配列にして1行ずつ格納してくれます。
MyLine[0]="0\t水素の元素記号は?\tHg\tH\tSu\t2" //1行目
MyLine[1]= "9\tヘリウムの元素記号は?\tHe\tShe\tI\t1" //2行目
(テーブルの境にはタブ記号("\t")が入っていることに注意!)
全部で何行あるかは、MyLine配列の長さを調べるMyLine.lengthで取ることができます。
ここで問題は、WindowsとMacで、ペーストされたテーブルの行数が変わるという大問題がありました。
WindowsではExcelからテーブルをコピペすると改行コードが自動的にペーストされてしまいます。
すると、最後の行が中身の無い行になってしまいます。
そこで、MyLine.lengthがWindowsとMacで異なった値になります。
その処理も含めて、 MyLine[X]の中に入っているタブ記号("\t")で文字列を分割することを考えます。
MyData = new Array(lines);// linesの数だけMyData[i]配列を作る。
var BlankLine=0;
for (var i = 0; i < lines; i++) {
if(MyLine[i]==""){
BlankLine++;
continue;
}
MyData[i] = MyLine[i].split("\t");//MyLine[]をタブ区切り(カンマ)でMyData[i][j]に代入
}
lines=lines-BlankLine;
MyLine[X]をタブ記号("\t")で分割した中身を入れる変数を用意します。
Xは行数分あり、各行は6つの変数になっているので、おでん鍋タイプの2次元配列を用意します。
MyData = new Array(lines);とすると、MyData[0]からMyData[lines-1]の1次元配列が準備されます。
そして、0から(lines-1)の間、forループを回します。
MyLine[i].split("\t");で、 MyLine[i]をタブ記号("\t")で分割し、MyData[i]に配列として代入します。
もともと、MyData[i]は1次元の配列だったのですが、split("\t")されたものを配列として代入するので2次元になります。
その際に、WindowsとMacの違いを調べるために、if文でMyLine[i]が値を持たないかどうか調べます。
もし、行がブランク(=="")であるなら、BlankLine++を行ないます。
その場合は、 MyLine[i]の分割は行わず、次の行の処理に移ります。
contineu;命令は、ループ処理の先頭に戻って処理を続けなさい、という命令です。
contineu;命令の後ろにある命令はスキップされます。
ループを強制的に離脱させるには、break命令を使います。
このように処理すると、途中にブランクの行があっても読み飛ばすことができます。
そして、最後に実際のデータ数の分だけqa配列にデータを代入します。
lines=lines-BlankLine;
for(var i=1;i<lines;i++){
var qaX=parseInt(MyData[i][0]);//qa[x]
qa[qaX]=new Array();
qa[qaX][0]=MyData[i][1];//question
qa[qaX][1]=MyData[i][2];//Ans1
qa[qaX][2]=MyData[i][3];//Ans2
qa[qaX][3]=MyData[i][4];//Ans3
var rightAns=parseInt(MyData[i][5]);//right ans
qa[qaX][4]=rightAns;
}
このような、配列操作を行うと配列の中身は文字列変数になります。
するとゼロ番目と4番目では、数値変数に変換しなければならなくなります。
値が整数の時にはparseInt( )命令で文字列を整数に変換することができます。
(値が小数点を持つ実数の時は、parseFloat( )を使います。)
Copyright pirika.com since 1999-
Mail: yamahiroXpirika.com (Xを@に置き換えてください) メールの件名は[pirika]で始めてください。