ボケ防止用トレーニング
朝、トーストにかじりつきながら点けてあったテレビにふと視点をむける。ひらがなだけで書かれた文字列に焦点がうつる。ボケ防止用とのことで、簡単な足し算などの計算式を、すべてひらがなで書いてあるものを暗算すると効果がある、ということをやっていた。つられてやってみると、これがたしかになかなか戸惑ったりしてしまう。これはたしかに効果がありそう。
まぁ、ちょいちょいっと書けそうであるし、計算する数字の個数や桁数、掛け算や割り算も含めたりとか、いろいろとバリエーションをくわえることにして、さっそくエディタをひらく。
設定として指定することができるのは、次のとおり。
- 計算する数字の個数を指定できる。
- 計算する数字の最大の桁数を指定できる。
- 計算する数値にマイナスの数値を含めるか指定できる。
- 演算において掛け算、割り算をそれぞれ含めるか指定できる。
- ひらがな、カタカナの指定。
脳トレ – かなもじ計算式エクササイズ
と、いった具合。
あまり深く考えることもなく、php にてさっと書き始める。いくつかのところで、さっそく match を使ってみたが、これはたしかに楽ちんである。そのうえ、わずかなことではあるけれど、少し高速にもなるということであるから、これからよく使うようになると思う。
しかし、php で作ってしまってからちょっとまてよ、ということになる。こんなのは Javascript で作れば、わざわざ form 送信でページの再読み込みとかする必要もないではないか、と。
脳トレ – かなもじ計算式プログラム – html – Javascript 版
と、いうことで、php で書いたものを、なんのことはない、再度、Javascript に書き直すという、訳の分からない手間をかけてしまった。まぁ、たぶん、php の match を使って何かを書きたかったのかもしれない。ただ、それだけのことだったのかもしれないが、とりあえず、どちらにしても動くものである。
とりあえず、その Javascript で動くものを。
スタイル設定も Javascript もインラインになっているので、これをファイルにすれば、そのファイルだけで稼働する。何を隠そう php の部分はまったくないのでこれは HTML ファイルである。
2024/7/30 追記:
と、いいつつ、実は基本中の基本となるところで、ものすごいプログラムミスがあったのです。と、いうのは、掛け算、割り算においては先に計算するという四則演算のルールを適用しておくのを、ころっと忘れてしまっていたのですよ。と、いうか、基本的な足し算、引き算でのテストしか使っていなかったから、というのが本当のところ。と、いうことで、新しく calc_ans() なる関数を追加しています。これにて大丈夫だと思うのですけれど。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Kana - caluculate</title>
<meta http-equiv="Cache-Control" content="no-cache" />
<style type="text/css">
*{position:relative;}
#maincontents{width:90%;text-align:center;}
h1{margin-bottom:30px;font-size:1.2em;color:blue;text-align:center;text-shadow:2px 2px 2px rgb( 255, 255, 255 ), 3px 3px 3px rgba( 0, 0, 0, 0.7 );}
form{width:300px;margin:10px auto 20px auto;padding:10px;text-align:left;border:double 4px blue;border-radius:10px}
label:before{content:"\2666";margin-right:10px;color:lime;}
input{margin-left:20px;}
input[type='number']{width:50px;}
button{padding:5px 10px;border-radius:5px;}
</style>
</head>
<body>
<div id="mainframe">
<header id="header">
<h1>ぼけちゃだめ!かなもじけいさん - のうえくささいず!</h1>
</header>
<div id="maincontents">
<div id="param">
<form action="" method="get">
<p><label for="numcount">数値の個数</label> : <input type="number" min="3" max="20" name="numcount" id="numcount" value="5"></p>
<p><label for="numdigit">数値の最大桁数</label> : <input type="number" name="numdigit" id="numdigit" min="1" max="3" value="1"></p>
<p><label for="ope">Operation : </label>
<select name="ope" id="ope">
<option selected value="0">加減のみ</option>
<option value="1">加減 & 乗</option>
<option value="2">加減 & 除</option>
<option value="3">加減 & 乗除</option>
</select>
<p style="font-size:0.9em;color:grey;padding-left:20px;">※除法においては四捨五入により小数点第一位までの数値での計算となります</p>
</p>
<p><label for="minus">マイナスの数値の有無</label></p>
<p><input type="radio" name="minus" id="minusen" value="1"> : Enabel <input type="radio" name="minus" id="minusdis" value="0" checked> : Disable</p>
<p><label for="kana">かなの指定</label></p>
<p><input type="radio" name="kana" id="hiragana" value="1" checked> : ひらがな <input type="radio" name="kana" id="katakana" value="0"> : カタカナ</p>
<p><label for="timelimit">制限時間</label> : <input type="number" name="timelimit" id="timelimit" min="3" max="100" value="10"></p>
<p><button id="subbt" type="button" style="display:block;margin:10px auto;">Let's Go!</button></p>
</form>
</div>
<main id="calc">
<div>
<p id="ansstr" style="padding:20px 0px;opacity:1;transition:opacity 1.0s;"></p>
<p><button id="endbt" type="button" style="margin-left:20px;opacity:0;transition:opacity 1.0s;">It's done!</button></p>
</div>
<div id="yourans" style="margin:20px auto;opacity:0;transition:opacity 1.0s;">
<p><label for="yours">Finish!!! - Input Your Answer</label></p>
<p><input type="text" name="yours" id="yours" value=""></p>
<p><button id="judge" type="button">Judgement</button></p>
</div>
<div id="anscal" style="opacity:0;"></div>
<div id="ansint" style="opacity:0;"></div>
<div id="congura"></div>
</main>
</div>
</div>
<script>
( function() {
const doc = document;
function Gi( name, dcm = doc ) {
let ans = null;
ans = dcm.getElementById( name );
return ans;
}
// 指定した数値の範囲内で乱数を生成する関数
function retrand( min, max ) {
const rand = Math.floor( Math.random() * (max + 1 - min) ) + min;
return rand;
}
// 実際の計算結果を返す関数、基本中の基本で四則計算のルールにそったものでないといけません
function calc_ans ( tarary ) {
// 引数 tarary は右のような文字列-> 5X9÷1÷8+4÷2+3-9
let ret = 0;
if ( tarary ) {
const regexp = /[X÷+-]/g;
if ( regexp.test( tarary ) ) {
let tar = tarary.replace( /\s+/g, '' );// 空白を全て除去
tar = tar.replaceAll( '-', '+-' );
const tarel = tar.split( '+' ),
tarel_len = tarel.length;
for ( let i = 0; i < tarel_len; ++i ) {
const tarstr = tarel[ i ],
tarstr_len = tarstr.length,
numary = [ [], [] ];
let minus = 1,
tmpnum = '';
for ( let j = 0; j < tarstr_len; ++j ) {
if ( isNaN( tarstr[ j ] ) ) {
if ( '-' === tarstr[ j ] ) {
minus = -1;
} else {
numary[1].push( tarstr[ j ] );
numary[0].push( minus * Number( tmpnum ) );
tmpnum = '';
minus = 1;
}
} else {
tmpnum += tarstr[ j ];
}
}
numary[0].push( minus * Number( tmpnum ) );
console.table( numary );
if ( numary[1].length ) {
let tmpsum = 0,
tmpope = '',
numel_len = numary[0].length;
for ( let j = 0; j < numel_len; ++j ) {
if ( 'X' === tmpope ) {
tmpsum *= numary[0][ j ];
} else if ( '÷' === tmpope ) {
tmpsum = Math.round( tmpsum / numary[0][ j ] * 10 ) / 10;
} else {
tmpsum += Number( numary[0][ j ] );
}
tmpope = numary[1][ j ];
console.log( tmpsum );
}
ret += tmpsum;
} else {
ret += Number ( numary[0][0] );
}
}
} else {
ret = Number( tarary );
}
}
return ret;
}
window.addEventListener( 'load', function () {
const bt = Gi( 'subbt' ),
jdg = Gi( 'judge' );
if ( null !== bt ) {
bt.onclick = () => {
const elstr = Gi( 'ansstr' ),
elcal = Gi( 'anscal' ),
elint = Gi( 'ansint' ),
endbt = Gi( 'endbt' ),
yourans = Gi( 'yourans' ),
yours = Gi( 'yours' ),
congra = Gi( 'congura' );
elcal.style.opacity = 0;
elcal.innerText = '';
elint.style.opacity = 0;
elint.innerText = '';
yours.value = '';
yourans.style.opacity = 0;
congra.innerHTML = '';
congra.style.opacity = 0;
let numary = [],
ansstr = '',
anscal = [],
ansint = 0,
ncount = Number( Gi( 'numcount' ).value ),
ndigit = Number( Gi( 'numdigit' ).value ),
ope = Number( Gi( 'ope' ).value ),
minusen = Gi( 'minusen' ).checked,
hira = Gi( 'hiragana' ).checked,
tlimit = Number( Gi( 'timelimit' ).value ),
prevnum = 0,
prevcal = 0,
endbtflg = false;
if ( ncount < 1 || ncount > 20) {
ncount = 5;
}
if ( ndigit < 1 || ndigit > 3) {
ndigit = 1;
}
if ( ope < 0 || ope > 3) {
ope = 0;
}
if ( tlimit < 3 || tlimit > 100) {
tlimit = 10000;
} else {
tlimit *= 1000;
}
const men = minusen ? 1 : 0,
kana = hira ? 1 : 0;
const kana_1 = [
[ '', '' ],
[ 'イチ', 'いち' ],
[ 'ニ', 'に' ],
[ 'サン', 'さん' ],
[ 'ヨン', 'よん' ],
[ 'ゴ', 'ご' ],
[ 'ロク', 'ろく' ],
[ 'ナナ','なな' ],
[ 'ハチ', 'はち' ],
[ 'キュウ', 'きゅう' ]
],
kana_2 = [
[ '', '' ],
[ 'ジュウ', 'じゅう' ],
[ 'ニジュウ', 'にじゅう' ],
[ 'サンジュウ', 'さんじゅう' ],
[ 'ヨンジュウ', 'よんじゅう' ],
[ 'ゴジュウ', 'ごじゅう' ],
[ 'ロクジュウ', 'ろくじゅう' ],
[ 'ナナジュウ', 'ななじゅう' ],
[ 'ハチジュウ', 'はちじゅう' ],
[ 'キュウジュウ', 'きゅうじゅう' ]
],
kana_3 = [
[ '', '' ],
[ 'ヒャク', 'ひゃく' ],
[ 'ニヒャク', 'にひゃく' ],
[ 'サンビャク', 'さんびゃく' ],
[ 'ヨンヒャク', 'よんひゃく' ],
[ 'ゴヒャク', 'ごひゃく' ],
[ 'ロッピャク', 'ろっぴゃく' ],
[ 'ナナヒャク', 'ななひゃく' ],
[ 'ハッピャク', 'はっぴゃく' ],
[ 'キュウヒャク', 'きゅうひゃく' ]
],
cal_str = [
[ [ 'ヒク', 'ひく' ], '-' ],
[ [ 'タス', 'たす' ], '+' ],
[ [ 'カケル', 'かける' ], 'X' ],
[ [ 'ワル', 'わる' ], '÷' ],
],
range = {// 乱数を発生させる範囲
1: [ [ 1, -9 ], 9 ],
2: [ [1, -99 ], 99 ],
3: [ [ 1, -999 ], 999 ],
};
while ( numary.length < ( ncount * 2 ) ) {
let rand;
while ( true ) {
rand = retrand( range[ ndigit ][0][ men ], range[ ndigit ][1] );
// 同じ数値が続いて出ないように
if ( 0 !== rand && prevnum !== rand ) {
prevnum = rand;
break;
}
}
numary.push( [ rand ] );
const cal = retrand( 0, 10000 );
let calkey;
// Javascript の switch は厳格なる比較 "===" なので使用可能
switch ( ope ) {
case 0:
calkey = cal & 1;
break;
case 1:
calkey = cal % 3;
break;
case 2:
calkey = cal % 3;
if ( 2 === calkey ) {
calkey = 3;
}
break;
case 3:
calkey = cal % 4;
}
// 前回と同じ演算子なら同じ数値が続いてもかまわない
if ( prevcal === calkey ) {
prevnum = 0;
}
prevcal = calkey;
numary.push( [ null, calkey ] );
}
let tmpnum = 0,
tmpope = 1;
numary.pop();// 最後の演算子は不要なので配列ストックから消去する
for ( let i = 0, na_len = numary.length; i < na_len; ++i ) {
if ( 'undefined' !== typeof numary[ i ][1] ) {// データが演算子の場合は numary[i][1] にデータが入っている
tmpope = numary[ i ][1];
ansstr += cal_str[ tmpope ][0][ kana ];
anscal.push( cal_str[ tmpope ][1] );
} else {
const val = numary[ i ][0];
let nstr = String( val ),
n_len = nstr.length;
anscal.push( nstr );
if ( '-' === nstr[0] ) {
ansstr += 'まいなす';
nstr = nstr.substring(1);
--n_len;
}
switch ( n_len ) {
case 1:
ansstr += kana_1[ Number( nstr[0] ) ][ kana ];
break;
case 2:
ansstr += kana_2[ Number( nstr[0] ) ][ kana ] + kana_1[ Number( nstr[1] ) ][ kana ];
break;
case 3:
ansstr += kana_3[ Number( nstr[0] ) ][ kana ] + kana_2[ Number( nstr[1] ) ][ kana ] + kana_1[ Number( nstr[2] ) ][ kana ];
}
}
}
if ( ansstr ) {
const elstr = Gi( 'ansstr' ),
elcal = Gi( 'anscal' ),
elint = Gi( 'ansint' ),
endbt = Gi( 'endbt' ),
yours = Gi( 'yours' ),
yourans = Gi( 'yourans' );
elstr.style.fontSize = '1.5em';
elstr.innerText = ansstr;
endbt.style.opacity = 1;
elcal.style.cssText = 'opacity:0;transition:opacity 1.2s;';
elcal.innerText = anscal.join( ' ' );
ansint = calc_ans( anscal.join( '' ) );
elint.style.cssText = 'opacity:0;transition:opacity 1.2s;';
elint.innerText = 'answer : ' + ansint;
let endId = setTimeout( () => {
elstr.style.opacity = 0;
yours.value = '';
yours.focus();
yourans.style.opacity = 1;
}, tlimit );
endbt.onclick = () => {
clearTimeout( endId );
endbtflg = true;
elstr.style.opacity = 0;
yours.value = '';
yours.focus();
yourans.style.opacity = 1;
}
function showresult() {
const yans = Number( Gi( 'yours' ).value ),
congra = Gi( 'congura' ),
elstr = Gi( 'ansstr' ),
elcal = Gi( 'anscal' ),
elint = Gi( 'ansint' );
let innerstr = '';
if ( ansint=== yans ) {
if ( endbtflg && tlimit < 11000 ) {
innerstr = '<span style="color:lime;font-size:1.5em;text-shadow:2px 2px 2px rgba(250,250,250,1.0),2px 2px 3px rgba(0,0,0,0.6);">Correct! Excellent, your brain seems to be in good shape. </span>';
} else {
innerstr = '<span style="color:blue;font-size:1.5em;text-shadow:2px 2px 2px rgba(250,250,250,1.0),2px 2px 3px rgba(0,0,0,0.6);">Correct! Your brain still seems to be normal. </span>';
}
} else {
innerstr = '<span style="color:red;font-size:1.5em;">Incorrect! Your brain is rotten.</span>';
}
congra.innerHTML = innerstr;
congra.style.opacity = 1;
elstr.style.opacity = 1;
elcal.style.opacity = 1;
elint.style.opacity = 1;
}
judge.onclick = () => {
showresult();
}
doc.onkeydown = function( e ) {
const key_code = e.key;
if ( 'Enter' === key_code ) {
const current = document.activeElement;
if ( 'yours' === current.id ) {
showresult();
}
}
}
}
}
}
});
})();
</script>
</body>
</html>
php版 プログラム
で、実はこちらの方を先に書いていた php 版である。
ただし、カタカナで表記する部分は Javascript 版を書いた後につけくわえたものなので、この php 版の方にはない。そして、判定したりする部分も、それはもともとが Javascript の領域のことなので無いし、 php 版はあくまでひらがなの計算式を生成させるところまでのもの。
前述のとおり match を複数つかっているので、php 8 じゃないと動かない。あしからず。
自分自身のページのフォームで送信された設定データを受け取って、計算式をかなに変換して生成する。Javascript ならページの再読み込みをすることなどないので、これは使い道のないプログラム。ただ、match の使用例としてだけのもの。
<?php
$ansstr = '';
$anscal = array();
$ansint = 0;
$numary = array();
if ( isset ( $_GET['submit'] ) ) {
$el = array_filter( $_GET, function( $tar ) { return ( int ) $tar; } );
if ( $el['numcount'] and $el['numdigit'] ) {
if ( isset ( $el['ope'] ) and $el['ope'] ) {
$el['ope'] = $el['ope'] % 4;
} else {
$el['ope'] = 0;
}
if ( isset ( $el['minus'] ) and $el['minus'] ) {
$el['minus'] = $el['minus'] & 1;
} else {
$el['minus'] = 0;
}
$kana_1 = array( 'ぜろ', 'いち', 'に', 'さん', 'よん', 'ご', 'ろく', 'なな', 'はち', 'きゅう' );
$kana_2 = array( '', 'じゅう', 'にじゅう', 'さんじゅう', 'よんじゅう', 'ごじゅう', 'ろくじゅう', 'ななじゅう', 'はちじゅう', 'きゅうじゅう', );
$kana_3 = array( '', 'ひゃく', 'にひゃく', 'さんびゃく', 'よんひゃく', 'ごひゃく', 'ろっぴゃく', 'ななひゃく', 'はっぴゃく', 'きゅうひゃく', );
$cal_str = array(
[ 'ひく', '-' ],
[ 'たす', '+' ],
[ 'かける', 'X' ],
[ 'わる', '÷' ],
);
$range = array(
1 => [ [ 1, -9 ], 9 ],
2 => [ [1, -99 ], 99 ],
3 => [ [ 1, -999 ], 999 ],
);
while ( count ( $numary ) < ( $el['numcount'] ) * 2 ) {
$rand = mt_rand( $range[ $el['numdigit'] ][0][ $el['minus'] ], $range[ $el['numdigit'] ][1] );
if ( 0 !== $rand ) {
$numary[] = array( $rand );
$cal = mt_rand( 0, 10000 );
$calkey = match ( $el['ope'] ) {
0 => $cal & 1,
1,2 => $cal % 3,
3 => $cal % 4,
};
$numary[] = array( null, $calkey );
}
}
$tmpnum = 0;
$tmpope = 1;
array_pop( $numary );
foreach ( $numary as $val ) {
if ( isset ( $val[1] ) ) {
$tmpope = $val[1];
$ansstr .= $cal_str[ $val[1] ][0];
$anscal[] = $cal_str[ $val[1] ][1];
} else {
$ansint = match ( $tmpope ) {
0 => $ansint - $val[0],
1 => $ansint + $val[0],
2 => $ansint * $val[0],
3 => floor( $ansint / $val[0] ),
};
$nstr = ( string ) $val[0];
$n_len = strlen( $nstr );
$anscal[] = $nstr;
if ( '-' === $nstr[0] ) {
$ansstr .= 'まいなす';
$nstr = substr( $nstr, 1 );
--$n_len;
}
$ansstr .= match ( $n_len ) {
2 => $kana_2[ ( int ) $nstr[0] ] . $kana_1[ ( int ) $nstr[1] ],
3 => $kana_3[ ( int ) $nstr[0] ] . $kana_2[ ( int ) $nstr[1] ] . $kana_1[ ( int ) $nstr[2] ],
default => $kana_1[ $nstr[0] ],
};
}
}
}
}
?>
Post : 2023/02/06 17:37
Comments feed
Trackback URL : https://strix.main.jp/wp-trackback.php?p=174276