//作成 2020/04/18, 2020/04/20 //プログラミングの考え方 //結果が2桁までの加算と減算を自動生成する PFont myFont1; //フォントを格納する変数 String Calculation ="" ; String Shiki =""; String Kotae =""; String Mojiretsu =""; int Counter = 0 ; String Key = ""; String CorrectWrong ="" ; String Syutsudai = ""; String KeyIn = ""; int Wrong = 0; int jikan = 0; int fun = 0; int byou = 0; int start = 0; void setup() { //キャンバスを設定。画面サイズ、背景色、色などを最初に設定します。 size(1000, 600); //size([横幅], [縦幅]) background(255); //background([0が黒〜255が白],[透明度]); myFont1 = createFont( "メイリオ", 30 ); //createFont(name, size) フォントを動的に作成する //http://zawaworks.hatenablog.com/entry/2017/03/13/160055 //"MS ゴシック" "MS 明朝" textFont( myFont1 ); //textFont() 使用フォントを選択する。loadFont()やcreateFont()で作成したフォントを使えるようにします。 } void mousePressed() { //●mousePressed() 関数で、マウスボタンが押されたイベントを捕まえる //マウスボタンを押したタイミングをタイムリーに検知したいなら、mousePressed()関数でボタンが押されたタイミングで処理を行う。 //●mouseClicked() 関数で、マウスボタンが押されて離された事を捕まえる //「ボタンが、押されて離されたタイミング」で呼び出される事です。カチッとクリックしたタイミングで処理を行うための関数。 //マウスの位置情報を取得 mouseX,mouseY //画面の右側をテンキーにする。 if (mouseX>=320 && mouseX<440 && mouseY>=100 && mouseY<220) { Key = "7" ; } else if (mouseX>=440 && mouseX<560 && mouseY>=100 && mouseY<220) { Key = "8" ; } else if (mouseX>=560 && mouseX<=960 && mouseY>=100 && mouseY<220) { Key = "9" ; } else if (mouseX>=320 && mouseX<440 && mouseY>=220 && mouseY<340) { Key = "4" ; } else if (mouseX>=440 && mouseX<560 && mouseY>=220 && mouseY<340) { Key = "5" ; } else if (mouseX>=560 && mouseX<=960 && mouseY>=220 && mouseY<340) { Key = "6" ; } else if (mouseX>=320 && mouseX<440 && mouseY>=340 && mouseY<460) { Key = "1" ; } else if (mouseX>=440 && mouseX<560 && mouseY>=340 && mouseY<460) { Key = "2" ; } else if (mouseX>=560 && mouseX<=960 && mouseY>=340 && mouseY<460) { Key = "3" ; } else if (mouseX>=320 && mouseX<=960 && mouseY>=460 && mouseY<=580) { Key = "0" ; } //右下のキー入力状況表示を消す fill(255); noStroke(); rect(620, 460, 90, 140); //rect(基準のx座標, 基準のy座標, 横幅, 縦幅) fill( 60 ); if (mousePressed == true) { text( "true", 630, 500 ); } else { text( "false", 630, 500 ); } text( "Key " + Key, 620, 550 ); //text(文字列, x座標, y座標) //リセット if (mouseX>0 && mouseX<1000 && mouseY>0 && mouseY<100) { loop(); fill(255); noStroke(); rect(0, 0, 1000, 600); //rect(基準のx座標, 基準のy座標, 横幅, 縦幅) fill( 60 ); Counter = 0 ; Wrong = 0; Syutsudai =""; start = millis()/1000; } } void mouseClicked () { //void mouseClicked() { //クリックすると、ここの処理が実行される //右下の状況表示を消す fill(255); noStroke(); rect(620, 460, 90, 140); //rect(基準のx座標, 基準のy座標, 横幅, 縦幅) fill( 60 ); //リセット if (mouseX>0 && mouseX<1000 && mouseY>0 && mouseY<100) { loop(); fill(255); noStroke(); rect(0, 0, 1000, 600); //rect(基準のx座標, 基準のy座標, 横幅, 縦幅) fill( 60 ); Counter = 0 ; Wrong = 0; Syutsudai =""; start = millis()/1000; } } void Coloring (String Key, String CorW ) { //テンキーを着色する。 print("Key "); println(Key); //デバッグ用にコンソールに出力 print("CorW "); println(CorW); //デバッグ用にコンソールに出力 if (CorW == "Correct" || CorW == "Pending") { fill( 0, 255, 0, 255 ); switch(Key) { case "7": rect(320, 100, 120, 120); break; //各 case 文ごとに break 文を最後に書く必要があります。 //break 文を書かないと、処理は、合致した行以降の case 内の処理まで次々と実行されてしまいます case "8": rect(440, 100, 120, 120); break; case "9": rect(560, 100, 120, 120); break; case "4": rect(320, 220, 120, 120); break; case "5": rect(440, 220, 120, 120); break; case "6": rect(560, 220, 120, 120); break; case "1": rect(320, 340, 120, 120); break; case "2": rect(440, 340, 120, 120); break; case "3": rect(560, 340, 120, 120); break; case "0": rect(320, 460, 300, 120); break; } fill( 0, 255, 0, 255); } if (CorW == "Wrong") { fill( 255, 0, 0, 255 ); switch(Key) { case "7": rect(320, 100, 120, 120); break; //各 case 文ごとに break 文を最後に書く必要があります。 //break 文を書かないと、処理は、合致した行以降の case 内の処理まで次々と実行されてしまいます case "8": rect(440, 100, 120, 120); break; case "9": rect(560, 100, 120, 120); break; case "4": rect(320, 220, 120, 120); break; case "5": rect(440, 220, 120, 120); break; case "6": rect(560, 220, 120, 120); break; case "1": rect(320, 340, 120, 120); break; case "2": rect(440, 340, 120, 120); break; case "3": rect(560, 340, 120, 120); break; case "0": rect(320, 460, 300, 120); break; } fill( 255, 0, 0, 255); } } void draw() { fill( 128, 0, 255 ); if (Counter >= 20) { fill(255); noStroke(); rect(0, 0, 1000, 100); fill( 60 ); text( "正解数 = " + str(20-Wrong) + " 、誤答数 = " + str(Wrong) + " でした。回答時間は " + str(int(fun)) + " 分 " + str(byou) + " 秒です。", 45, 30 ); text( "このタイトル部分をクリックすると、再挑戦できます。", 45, 70 ); //右下の状況表示を消す fill(255); noStroke(); rect(620, 460, 90, 140); //rect(基準のx座標, 基準のy座標, 横幅, 縦幅) fill( 60 ); noLoop(); } else { text( "2桁までの足し算と引き算を、交互に、計20問生成します。", 45, 30 ); //text(文字列, x座標, y座標) text( "中央のテンキーをマウスでクリックして回答して下さい。", 45, 70 ); } //右側のテンキーを描く。 //枠 stroke(255); fill(200, 100); //fill() 塗りに色を付ける //fill(d) グレースケール。整数dが0なら黒、255なら白、その間の数は数が小さいほど濃い灰色。 //fill(d,a) グレースケールだが、「透明度」を追加指定する。aの0は完全に透明、255は完全に不透明。 rect(320, 100, 120, 120); //rect(基準のx座標, 基準のy座標, 横幅, 縦幅) rect(440, 100, 120, 120); rect(560, 100, 120, 120); rect(320, 220, 120, 120); rect(440, 220, 120, 120); rect(560, 220, 120, 120); rect(320, 340, 120, 120); rect(440, 340, 120, 120); rect(560, 340, 120, 120); rect(320, 460, 300, 120); //数 fill( 0 ); text("7", 370, 180 ); text("8", 490, 180 ); text("9", 610, 180 ); text("4", 370, 300 ); text("5", 490, 300 ); text("6", 610, 300 ); text("1", 370, 420 ); text("2", 490, 420 ); text("3", 610, 420 ); text("0", 470, 540 ); // 計算式を順次表示する //文字を取り出すには //http://mslabo.sakura.ne.jp/WordPress/make/processing%E3%80%80%E9 %80%86%E5%BC%95%E3%81%8D%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/%E6%96%87 %E5%AD%97%E3%82%92%E5%8F%96%E3%82%8A%E5%87%BA%E3%81%99%E3%81%AB%E3%81%AF/ //http://maicommon.ciao.jp/ss/processing_g/string/ if (Counter % 2 == 0) { Calculation = "Add"; } else { Calculation = "Subt"; } //式を表示 if (Syutsudai =="") { if (Counter <10 ) { Mojiretsu = Keisann(Calculation); Shiki = Mojiretsu.substring(0, 10); text(Shiki, 20, 130 + 50*Counter ); Kotae = trim(Mojiretsu.substring(11)); } else if (Counter <20 ) { Mojiretsu = Keisann(Calculation); Shiki = Mojiretsu.substring(0, 10); text(Shiki, 710, 130 + 50*(Counter - 10) ); Kotae = trim(Mojiretsu.substring(11)); } Syutsudai = "sumi"; } if (Key != "") { print("Kotae0 "); println(Kotae); print("Key0 "); println(Key); print("Kotae.length() "); println(Kotae.length()); //デバッグ用にコンソールに出力 if (Kotae.length() == 2) { if (CorrectWrong == "Pending") { if (int(Kotae.substring(1, 2)) == int(Key)) { CorrectWrong ="Correct"; } else { CorrectWrong ="Wrong"; } KeyIn = KeyIn + Key; } else if (int(Kotae.substring(0, 1)) == int(Key)) { CorrectWrong ="Pending"; KeyIn = Key; } else { CorrectWrong ="Wrong"; KeyIn = Key; } Coloring (Key, CorrectWrong ) ; Key = ""; } if (Kotae.length()== 1) { if (int(Kotae) == int(Key)) { CorrectWrong ="Correct"; fill( 0, 100, 0 ); } else { CorrectWrong ="Wrong"; fill( 255, 50, 50 ); KeyIn = Key; } Coloring (Key, CorrectWrong ) ; Key = ""; } } //回答を表示 if (CorrectWrong =="Wrong" || CorrectWrong =="Correct") { if (Counter <10 ) { text(Kotae, 190, 130 + 50*Counter ); if (CorrectWrong =="Wrong") { fill(0); text(KeyIn, 250, 130 + 50*Counter ); Wrong = Wrong + 1; KeyIn = ""; } } else { text(Kotae, 880, 130 + 50*(Counter-10)); if (CorrectWrong =="Wrong") { fill(0); text(KeyIn, 940, 130 + 50*(Counter-10)); Wrong = Wrong + 1; KeyIn = ""; } } Counter = Counter + 1; Syutsudai = ""; CorrectWrong =""; jikan = millis()/1000 - start; fun = jikan/60; byou = jikan - fun*60; } } String Keisann(String AorS ) { String mojiretsu=""; int A; int B; int S; //ループ方法 //http://www.cho-design-lab.com/2013/05/29/processing-repeat/ //while(条件){繰り返す処理;繰り返す処理;…繰り返す処理;} //do {繰り返す処理;繰り返す処理;…繰り返す処理;} while(条件); //do ? whileは「条件の判定をする前に、一度繰り返し処理を行う」という繰り返し処理です。 //for(カウンタ初期化; 条件; カウンタ更新)繰り返す処理; do { A = int(random(99))+1; //random(2) は 0以上 2未満の数を発生する。命令intはこれの小数部分を切り捨てて整数化する。 //int(random(2)) は0または1になる。 B = int(random(99))+1; S = A+B; //} while (S >= 10); //デバッグ用に1桁で出題 } while (S >= 100); if (AorS == "Add") { mojiretsu = nf(A) + " + " + nf(B) + " = " + nf(S); } else if (AorS == "Subt") { mojiretsu = nf(S) + " - " + nf(A) + " = "+nf(B); } return mojiretsu; }