FC2ブログ

溶岩の中はゲームまみれ

ゲーム好きのテラビモスが綴るブログ。普通の日記を書いたり、ゲームを紹介したりするブログです。

スポンサーサイト
--/--/--(--) --:--

タグ:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

JavaScriptでツイート機能付き診断を作ってみた
2017/07/15(Sat) 11:51

テーマ:コンピュータ/プログラミング
タグ: 暇潰し  プログラミング  JavaScript  乱数 
2017/7/15 ver0.70公開。第四世代ポケ、第五世代ポケ対応。
診断で遊んでたら、ふと『診断メーカーなしで作れるかなあ』と思ったのでJavaScriptで製作を試みたら案外短時間でできてしまったので公開します。

あなたがポケモンに生まれ変わったら ver0.70 - http://terabi.web.fc2.com/shindan/shindan.html

プログラムについて詳しく説明していこうと思います(続きを見るをクリックしてご覧ください)。
※わかる人にはわかりますが、わからない人は全くわからないと思います(笑)

【ポイント】
・自然数列を生成し、それをシャッフルする
・診断結果が日替わりになるようにするため、乱数seedを日付情報により固定する
・入力された文字列をASCIIコードに変換して数値化する


【グローバル変数】
pokemon_name : ポケモンの名前を格納する配列
n : pokemon_nameの長さ分だけの自然数列
sn : シャッフル後の数列を格納するための配列
seed : 疑似乱数の種

【シャッフル関数】
JavaScriptでの実装例
<コード>
function shuffle(array) {
var n = array.length, t, i;
while (n) {
i = Math.floor(Math.random() * n--);
t = array[n];
array[n] = array[i];
array[i] = t;
}
return array;
}
流れとしては、以下のようになる。
  1. 変数nの初期値をarrayの要素数(=最後尾の要素)とする
  2. array[n]と交換する要素(要素nより前の要素である必要がある)をランダムに選定する(その要素をiとする)
  3. array[n]とarray[i]を交換する
  4. nをデクリメントして、n=0となるまで2と3を繰り返す
本プログラムでは、日替わりで乱数列を固定するため、このシャッフル関数を拡張する。
JavaScriptでは、種を固定して再現性のある疑似乱数を扱うメソッドは存在しないが、ググってみたところ、種を固定できるようなライブラリが見つかったので、本プログラムではそれを利用する(GitHubで公開されている→https://github.com/davidbau/seedrandom
<拡張されたシャッフル関数のコード>
function shuffle(array, seed) {
// 元の配列を破壊したくないので複製する
var a = new Array(array.length);
for(var i = 0; i < a.length; i++) {
a[i] = array[i];
}
var n = a.length, t, i;
Math.seedrandom(seed);
while (n) {
i = Math.floor(Math.random() * n--);
t = a[n];
a[n] = a[i];
a[i] = t;
}
return a;
}
種の固定を行っている部分は、Math.seedrandom(seed)である。ライブラリ作成者の説明によると、このseedの値は文字列でも数値でもいいらしい。

【疑似乱数の種に用いる日付情報について】
ページロードを行った年月日の0時0分0秒という日付情報に対して、getTimeメソッド(指定した日付に対して、1970年1月1日0時0分0秒から何ミリ秒経ったかを返すメソッド)を使って数値化したものを疑似乱数の種に使う。こうすることで、日を跨がない限り乱数種が固定されるため、診断結果を日替わりにすることができる。
<実際のコード>
// ページロード時に行われる処理
function data_set() {
var load_date = new Date();
var year = load_date.getFullYear();
var month = load_date.getMonth() + 1;
var day = load_date.getDate();
var text = month + "/" + day + "/" + year;
var dt = new Date(text);

seed = dt.getTime();
sn = shuffle(n, seed);
// Cookieの呼び出し
if(get_cookie("client_name") != -1) {
form.name.value = get_cookie("client_name");
}
}
コードの中に"Cookieの呼び出し"とあると思うが、これは、テキストボックスに入力された文字列を、診断後に、Cookieを用いて保存しておき、リロード時に、保存した文字列でオートコンプリートを行うようにするためのコードである(Cookieの呼び出しおよび書き込みを行う関数も実装しているが、ここでは省略する)。

【ポケモン選定のしくみ】
選定のしくみ(クリックで拡大表示)
※ver0.42aから計算方法を変えました。しかし原理としては↑と一緒です。
流れとしては、以下のようになる。
  1. テキストボックスに入力された文字列を左から1文字ずつASCIIコードに変換し、それらの値を足し合わせる計算を施す
  2. 1で計算した値をpokemon_nameの要素数で割った余りを計算する
  3. 事前にシャッフルされた数列snに対して、番号(2で計算した値)の値を参照する(例ではsn[245]を参照し、値154を取得している)
  4. 配列pokemon_nameに対して、番号(4で取得した値)の値を参照する(例ではpokemon_name[154]を参照し、値"ヒノアラシ"を取得している)
※計算方法
  1. 名前をシャッフルする(文字の順番を滅茶苦茶にする)。シード値はロード年月日の0時0分0秒をミリ秒に変換した数値に設定。以下シャッフルされた名前はs_nameと呼ぶことにする
  2. シード値を再び固定(1と同値)
  3. s_nameのどれか1文字をランダム選定
  4. s_nameの各文字のASCIIコードを調べ、足し合わせる。ただし、4で選定された文字についてはASCIIコードを2倍した値を加算する
  5. 4で計算した値をpokemon_nameの要素数で割った余りを計算する

<実装例>
function pokemon_shindan() {
var komoji = "";
var oomoji = "";

var name = form.name.value;
set_cookie("client_name", name, 365);
var a = shuffle(name, seed);
var s_name = "";
for(var i = 0; i < a.length; i++) {
s_name += a[i];
}
Math.seedrandom(seed);
// var position = Math.floor(Math.random() * s_name.length);
// Math.seedrandom(seed + s_name.charCodeAt(position));
position = Math.floor(Math.random() * s_name.length);
var sum = 0;
for(var i = 0; i < s_name.length; i++) {
if(i == position) {
sum += s_name.charCodeAt(i) * 2;
} else {
sum += s_name.charCodeAt(i);
}
}
var poke_name = pokemon_name[sn[sum % sn.length]];
// アンノーンの場合は特殊な処理
if(sn[sum % sn.length] == 200) {
Math.seedrandom(seed + sum);
var code = Math.floor(Math.random() * 28);
if(code < 26) {
komoji = String.fromCharCode(97 + code);
oomoji = String.fromCharCode(65 + code);
} else if(code == 26) {
komoji = "z1";
oomoji = "!";
} else if(code == 27) {
komoji = "z2";
oomoji = "?";
}
}
// デオキシス
if(sn[sum % sn.length] == 385) {
Math.seedrandom(seed + sum);
var code = Math.floor(Math.random() * 4);
komoji = String.fromCharCode(97 + code);
switch(code) {
case 0:
oomoji = "(ノーマルフォルム)";
break;
case 1:
oomoji = "(アタックフォルム)";
break;
case 2:
oomoji = "(ディフェンスフォルム)";
break;
case 3:
oomoji = "(スピードフォルム)";
break;
}
}
// 結果表示&ツイート投稿リンク作成部分
var tweet = name + "がポケモンに生まれ変わったら、" + poke_name + oomoji + "になります。";
var result = encodeURI(tweet);
var hash_tag = encodeURI("あなたがポケモンに生まれ変わったら");
var text = name + "がポケモンに生まれ変わったら、<strong>" + poke_name + oomoji + "</strong>になります。";
text += '<input type="button" onclick="window.open(';
text += "'https://twitter.com/share?text=" + result + "%0a&hashtags=" + hash_tag + "&url=http://terabi.web.fc2.com/shindan/shindan.html&related=terabimos" + "');" + '" ';
text += 'value="結果をツイートする">';
text += "<br>";
text += '<img border="0" src="./image/' + (sn[sum % sn.length] + 1) + komoji + '.png">';
document.getElementById("body_content").innerHTML = text;
}
コードにも書いてある通り、診断結果がアンノーンである場合は特殊な処理が行われる。具体的には、疑似乱数の種を(日付情報+ASCIIコードの合計値)に固定してから、フォルムのランダム選定を行っている。日付情報は、ページロード年月日の0時0分0秒に固定しているため、日を跨がない限り変化しないし、ASCIIコードの合計値も文字列依存の固定値なので、日を跨がない限り、『診断』ボタンを押すたびにアンノーンのフォルムが変化してしまうことなく、かつ、テキストボックスに入力された文字列によってフォルムが変化する。デオキシスも同様な処理。
関連記事

コメント:

コメントの投稿

管理者にだけ表示を許可する

トラックバック:

http://terabimos.blog.fc2.com/tb.php/973-82a92a6f

«前の記事  | ホーム |  次の記事»

カレンダー

« | 2019-01 | »
S M T W T F S
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -

現在の時刻



日() 

月別アーカイブ

カテゴリ


カウンター


カウント開始:2013/06/10
今、人が閲覧していますよ♪

ブログランキング


このブログを面白いと思った方は、クリックしてください。一つ一つのクリックが管理人の励みになります。

アクセスランキング

[ジャンルランキング]
ゲーム
863位
アクセスランキングを見る>>

[サブジャンルランキング]
その他
166位
アクセスランキングを見る>>

プロフィール

テラビモス

テラビモス

ゲーム大好きです。やっているゲームの機種は任天堂寄りで、レトロゲームもほどほどに遊びます。

さらに詳しく ≫


FC2Ad

最近の記事

タグクラウド

ツイート


フォロー大歓迎です!私の趣味に合う人ならほぼ100%フォロバします。ポケモンの対戦や交換の申し込みもお気軽にどうぞ。それ以外でも気軽に声をお掛けください。

最近のコメント

最近のトラックバック

このブログをリンクに追加する

ブロとも申請フォーム

この人とブロともになる


QRコード

QR

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。