2009年03月19日

シリーズ一気読み中

ライトノベル大量買いがやめられない海月歩空です。こんばんは。

最近のブログは、プログラムのことばかり。
それも説明がへたなのと、詳しく説明する気がないので、かなりおおざっぱなんですが、楽しんでいただけてますでしょうか。
ちなみに、私は楽しいですよ!(自己満足です)

そんな私ですが、今週日曜日にがばっと11冊本を買いました。
シリーズ一気読みを久しぶりにしたいなぁ、最近買うのは完全新作か続き物の1冊だなぁ、と思い立って、がばっと。

昔は、妖魔夜行+百鬼夜翔がばっと2,30冊買いとかした私ですから、まだまだなんですがね!
まだ変身を3回残しています、て感じ。

さて、そういうわけで買った本は、最近アニメ化したらしい「鋼殻のレギオス」です。
選んだ理由としては、アニメ化もあるんですが、それより何より、読む本で作者の名前を時々みていたから、です。
好きな本の作家さんが、名前をあげてるって気になりますよね!

というわけで、やっとこさ今10巻まで読み終わった結果。
なかなか面白い本です!
設定とか、いろいろ多そうでわくわく!
そして、フェリが可愛い!
感覚的な問題なので、なにがどう、ともいえないけれど、無表情系に見えて実はーみたいなギャップには、きゅんと……(キモイです)

もう最新刊に追いつくので、次は前世界譚も行きます。
これくらい大量に読んでいると、ああ、読むようなスピードで文章が書けないかなぁと思うわぁ……。
posted by 海月歩空 at 02:36| Comment(0) | TrackBack(0) | ライトノベル

2009年03月14日

LimeChat2のjavaScriptでダイス作成(5)

漫画的インフレ大好き、海月歩空です。こんばんは。

前回でダイスの基礎基本が完成しました! やりましたね!
というわけで、今回からはダイスの機能拡張が始まります。
これからのパターンとしては、ある機能を追加したい→仕様に起こす(イメージを言語化)→機能開発、という流れになります。
無駄に多機能にしていく予定です。無駄、大好き!
では、前回の要約から。

・関数化は多機能化の一歩。
小さいものを組み合わせて積み木でお城を造ろう!
・見通しよくプログラム。
基本は100行も行かないように小分け小分け。

ざっくりですね!
関数化(javascriptだとクラス化も含む)なら、小さく小分けで書いていく方があとあと便利です。
同じことを繰り返し書くなら、それを関数化すること考えましょう。
2回で関数化できるか考え、更に出現すると関数化が必要と思う、位のスタンスで行けばオッケー。

そんなよくある説明はいいのよ!
今日で普通のダイスは完成なのよ!?(え、もう決まっていました?)
さあ、基本ダイスを作成しなさい!

・ダイス作成(5) 機能拡張・その1−基本ダイス作成(ぱらららーん)

さて、前回までで、基本的なダイスができたわけで、すごろくや麻雀そのほかのゲームするときには、これで十分ことたります。
ですが、さいころ振ってその結果を計算して……というような処理が必要になるなら、このままでは足りません。
というわけで、今回は、ネット上そこらにあるダイスでも対応されているものが多い”ダイスの結果に対して四則演算をしたい”という要望を追加したいと思います。
機能追加の仕様
1.メッセージへデータ入力。
・入力形式は、元の○d△に対して、
通常の四則演算(+-/*)を行えるようにする。
例:4+3d6+1-4
・かっこの計算も可とする。
例:4d6*(4+4)
・スペースで区切ることによって、
メッセージも追加できる(おまけ)。
例:3d6+3 高めでろー
2.メッセージへデータ出力。
・出力形式の、【ダイス結果の合計値】を
【ダイス結果と四則演算の計算結果】に訂正。
・出力形式に、ダイス結果の合計値を改めて追加。
×:○d△+▲=([.□.□.]=●)=■で、
入力者:【ダイスの個数】d【ダイスの面数】【四則演算等】=
([.【ダイス一個の結果】.【ダイス一個の結果】.]=
【ダイス結果の合計値】)【四則演算等】=
【ダイス結果と四則演算の合計値】(実際は1行)

はい、こんな感じで拡張します。
パワーアップ!(これでやっと他と同じレベルです)

イメージとしては、○d△を、ダイスの結果に置き換えるような仕組みにして、最後に計算させればいいわけですね。
というわけで、これを形にしてみましょう。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
var matchWords =
new RegExp(/^([0-9+*/()-]*?[1-9]\d*d[1-9]\d*[0-9+*/()-]*?)([  ].*)?$/i);
//textの中に○d△があるとき、
//ダイス要素部分を取り出す
if (text.match(matchWords))
{

//通常ダイス関数呼び出し
var dice = normalDice(RegExp.$1);

//文字列出力処理
send(channel, prefix.nick + " : " + dice.words
+ " = " + dice.disp + " = " + dice.sum);
}
}

/******************************************************
通常ダイス関数

基本説明
ダイスの要素を含む文字列を受け取り、○d△の形を抽出。
ダイスを振り、結果をダイス要素に置き換えたものと、
結果を計算したものをオブジェクトとして返却する。
in
diceWords:入力ワード(ダイス要素を含む文字列)

out
ダイス結果object
[
disp:ダイス表示用
(ダイスを振った結果で置き換えた文字列)
sum:ダイス結果合計値(計算した結果の数値)
]
*******************************************************/
function normalDice(diceWords)
{

//返却オブジェクト
var dice = new Object();

//入力文字列保存
dice.words = diceWords;

//ダイスマッチ用正規表現
var diceMatch =
new RegExp(/^[0-9+/()*-]*?([1-9]\d*)d([1-9]\d*)[0-9+/()*-]*?$/i);

if (diceWords.match(diceMatch))
{
//ダイス個数
var diceNum = parseInt(RegExp.$1);
//ダイス面数
var diceFace = parseInt(RegExp.$2);

//ダイス結果格納
var diceData = diceRoll(diceNum, diceFace);
}

//表示置き換え
dice.disp = diceWords.replace(/(\d+d\d+)/i,
"([." + diceData.array.join(".") + ".]="
+ diceData.sum + ")");

//計算式置き換え
var cal = diceWords.replace(/(\d+d\d+)/i, diceData.sum);

//計算結果入れ
dice.sum = eval(cal);

//結果返却
return(dice);
}

/******************************************************
ダイス基本関数

基本説明
ダイス個数回分、ダイス面数で指定されたダイスを振り、
ダイスの振った結果をオブジェクトとして返却する。

in
diceNum:ダイス個数(正数)
diceFace:ダイス面数(正数)

out
ダイス結果object
[
array:ダイス結果配列(Array)
sum:ダイス結果合計値
]
*******************************************************/
function diceRoll(diceNum, diceFace)
{
//返却用ダイスobject
var dice = new Object();
//返却用ダイス結果合計値
dice.sum = 0;
//返却用ダイス結果配列
dice.array = new Array();

if (diceNum <= 0 || diceFace <= 0)
{
dice.array.push(0);
return(dice);
}

//ダイス個数分、ダイス面数で指定されたダイスを振る。
for (var i = 0; i < diceNum; i++)
{
//ダイスを振った結果をダイス結果配列に。
dice.array.push(Math.floor(Math.random() * diceFace) + 1);

//ダイスを振った結果を合計値に足していく。
dice.sum += dice.array[i];
}

//結果返却
return(dice);
}

前回から変数名と関わっていますが、何となく気に入らなかったので変えちゃいました(適当すぎます)
実際は、もうちょっと名前とかをこだわっておくと、こんなことはあまりなくなります。
仕事でするならば、オブジェクトとかを返すときはもっとこだわる必要ありまくりです。
返す形さえ変えてなければ、バグ修正しても相手には迷惑かけずにすみます。要チェック。
私は適当なので、気にしない気にしない(気にしなさい)

というわけで、ダイスのロール部分と、ダイスの要素取り出し及び計算部分、テキストの入力受付部分というように分けました。
こうやってみると、同じような処理の積み重ねですね。
今回初めて入ったものは、replaceです。
一つめの引数にマッチしたものを、二つめの引数に置き換える処理です。

さてさて。
この形だと、更にひとつ機能が追加できそうですよね。
そう、ダイス要素を四則演算する機能です!
計算方法としては、(○+○)d△という方法と、○d△+○d△という方法があります。
おまけとして、ダイスの面数も計算できそうです。
機能追加の仕様
1.メッセージへデータ入力。
・(追加)入力形式は、(○+○)d△など、
ダイスの個数に四則演算(+-/*)を行えるようにする。
例:(4+3)d6+1-4
※ダイスの個数の計算結果が少数を含む場合、切り捨てとする。
※0以下になった場合は、ダイスを振った結果を0として扱う。
・(追加)入力形式は、○d△+○d△など、
ダイスの結果同士に四則計算を行えるようにする。
例:4d6+3d6

仕様として、このような形になりますね。
さて、さくっとこの部分も追加しましょう。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//ダイス要素っぽいものがあれば取り出し
if (text.match(/^([0-9()d./+*-]+)([  ].*)?$/i))
{

//通常ダイス関数呼び出し
if (dice = normalDice(RegExp.$1))
{

//文字列出力処理
send(channel, prefix.nick + " : " + dice.words
+ " = " + dice.disp + " = " + dice.sum);
}
}
}

/******************************************************
通常ダイス関数

基本説明
ダイスの要素を含む文字列を受け取り、○d△の形を抽出。
ダイスを振り、結果をダイス要素に置き換えたものと、
結果を計算したものをオブジェクトとして返却する。
通常の数式を入れた場合も計算をする。
in
words:入力ワード(ダイス要素を含む文字列)

out
ダイス結果object
[
disp:ダイス表示用(ダイスを振った結果で置き換えた文字列)
sum:ダイス結果合計値(計算した結果の数値)
cal:計算式(ダイスを振った後の計算過程の計算式)
diceWords:渡された入力文字列
]
*******************************************************/
function normalDice(diceWords)
{
//try(今回の注目)
try

{
//返却オブジェクト
var dice = new Object();

//入力文字列保存
dice.words = diceWords.replace(/d/ig, "D");

//かっこ計算処理
while (diceWords.match(/(\([^d(]+?\))/i))
{
//かっこ計算後置き換え(今回の注目)
diceWords = diceWords.replace(/(\([^d(]+?\))/i,

(function (cal) {return eval(cal);}));

}

//置き換え用に、初期文字列を入れる
dice.disp = diceWords;
dice.cal = diceWords;

//正規表現定数化
var diceMatch =
new RegExp(/((0|[1-9]\d*)(\.[0-9]+)?)d((0|[1-9]\d*)(\.[0-9]+)?)/i);

//ダイスの要素を取り出し
//(小数点を含む場合の正規表現の関係で、
//括弧対応の取り出しは1番目と4番目)
while (dice.disp.match(diceMatch))
{
//ダイス個数(小数点を含むときは切り捨て)
var diceNum = Math.floor(parseFloat(RegExp.$1));
//ダイス面数(小数点を含むときは切り捨て)
var diceFace = Math.floor(parseFloat(RegExp.$4));

//ダイス結果格納
var diceData = diceRoll(diceNum, diceFace);

//表示置き換え
//(ループしないようにDをMに一時的に置き換え)
dice.disp = dice.disp.replace(diceMatch,
"(" + diceNum + "M" + diceFace +
"=[." + diceData.array.join(".") + ".]="
+ diceData.sum + ")");

//計算式置き換え
dice.cal = dice.cal.replace(diceMatch , diceData.sum);
}

//表示置き換え
dice.disp = dice.disp.replace(/M/ig, "D");

//計算結果入れ
dice.sum = eval(dice.cal);

//結果返却
return(dice);
}
//catch(今回の注目)
catch(e)

{
log(e);
//エラー時にはnullを返却。
return(null);
}
}

/******************************************************
ダイス基本関数

基本説明
ダイス個数回分、ダイス面数で指定されたダイスを振り、
ダイスの振った結果をオブジェクトとして返却する。

in
diceNum:ダイス個数(正数)
diceFace:ダイス面数(正数)

out
ダイス結果object
[
array:ダイス結果配列(Array)
sum:ダイス結果合計値
]
*******************************************************/
function diceRoll(diceNum, diceFace)
{
//返却用ダイスobject
var dice = new Object();
//返却用ダイス結果合計値
dice.sum = 0;
//返却用ダイス結果配列
dice.array = new Array();

//0以下のときには0を返す。
if (diceNum <= 0 || diceFace <= 0)
{
dice.array.push(0);
return(dice);
}

//ダイス個数分、ダイス面数で指定されたダイスを振る。
for (var i = 0; i < diceNum; i++)
{
//ダイスを振った結果をダイス結果配列に。
dice.array.push(Math.floor(Math.random() * diceFace) + 1);

//ダイスを振った結果を合計値に足していく。
dice.sum += dice.array[i];
}

//結果返却
return(dice);
}

いえーい、完成です! やんややんや!
というかすごい長!?
案外簡単……といいつつ、正規表現が一番たいへんだったりしました。
つまり逆説的に言えば、正規表現をマスターすれば、文字列編集もマスターしたも同然! やはー!

さて、今回の注目は2点です。
案外便利な二つのjavascriptらしい要素。
”try〜catch”と”無名関数”です!

”try〜catch”といえば、javaなどの最近のクラスを使うプログラム言語を使用していたら出てくるベーシックなものですが、try文でありえなーいってエラーがでたとき、catch文に飛ばされるという、おおざっぱにぶっちゃければ、goto文の亜種ですね(おおざっぱすぎです)
今回で言うと、文字入力処理で複数の関数を呼び出している場合、ちゃんとしないとエラーでぼこんと落ちてしまうのですが、これを助けてくれるんです。

”無名関数”は、関数を作るほどでもない、けれど、関数じゃないと処理できない、的なものを行うjavascriptらしい関数です。
そう、repleaceなんかは、マッチした要素を関数で加工することができないんですが、無名関数を引数に渡してあげることによって、加工することができるようになります。
……今回の例だと、例になっていないんですよね。

それに目をそらしつつ、基本ダイスは完成しました!
いえーい!

というわけで、今回分のダイス(dice.js)をアップしておきます。
ソースには保証がないけれどちょっぴり著作を小さく主張。
使い心地とか、バグとか教えていただければ、ありがたく思ったりします。
posted by 海月歩空 at 21:22| Comment(0) | TrackBack(0) | プログラム

2009年03月08日

LimeChat2のjavaScriptでダイス作成(4)

ランダム大好き、海月歩空です。こんばんは。

今日でダイスの基本形が完成!
いえーい!
そう、ここからダイスの多機能化開発の道が始まるわけです。
無駄に多機能、私が大好きな言葉のひとつ!
では、前回の要約から。

・入力制御は重要な処理(前回と重複)
チャット上では1行文の入力なため、この操作ができれば基本的な操作はできるようになる。
ダイスの個数とダイスの面数は取り出せるようになりました。

・macthと正規表現は文字列操作に強い関数。
はじめは目的に合う関数を探して、使い方を調べることが大切。後、正規表現は最高です!

ざっくりですね!
前回は、前々回とかぶっているので、似たようなことを言っていますが気にしない!

今回は処理をダイス作成まで行くのだわ!
そして、自作関数の形にしていくのよ! 命令だわ!(何様ですか)
さあ、処理のメインを作成しなさい!

・ダイス作成(4) 処理・関数化(ぱらららーん)

というわけで、前回ののソースを呼びましょう。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//textの中に○d△があるとき、取り出す
if (text.match(/^(\d+)d(\d+)$/i))
{
//文字列出力処理
send(channel, prefix.nick + ":" + "ダイスの個数=" + RegExp.$1
+ "/ダイスの面数=" + RegExp.$2 );
}
}

必要なものを取り出す処理までができていますね。
さあ、後はさいころの機能を追加するだけです。
さいころとは、”ランダム”に、”1〜ダイスの面数”までの値を返すものです。
つまり、ランダム関数(Math.random())を使う、ということですね。

ただ、機能として、ランダム関数は0以上1未満の浮動小数で結果を返すので、ちょっと計算が必要ですね。
いわゆる、かけて端数切り下げて足して、という、ランダム関数で実数を取り出すベタなものです。
さあ、組み込んでダイスを作成してみましょう。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//textの中に○d△があるとき、取り出す
if (text.match(/^([1-9]\d*)d([1-9]\d*)$/i))
{
//ダイス個数
var diceNum = parseInt(RegExp.$1);
//ダイス面数
var diceFace = parseInt(RegExp.$2);
//ダイス結果配列
var diceAns = new Array();
//ダイスの合計値
var diceSum = 0;

//ダイス個数分、ダイス面数で指定されたダイスを振る。
for (var i = 0; i < diceNum; i++)
{
//ダイスを振った結果をダイス結果配列に。
diceAns.push(Math.floor(Math.random() * diceFace) + 1);

//ダイスを振った結果を合計値に足していく。
diceSum += diceAns[i];
}

//文字列出力処理
send(channel, prefix.nick + ":" + diceNum + "D" + diceFace
+ "=[." + diceAns.join(".") + ".]=" + diceSum);

}
}

シンプルですが、これでダイスが完成しました!
いきなり、かなり多めに処理が入ってきてしまいましたね。
ついてきてますか? ついてこれなくてもついてきてください!(横暴です)

機能的には、コメントを見ればわかるようになっているはずですが、変更・追加があったところを上から解説していきましょう。

まずは、ダイスの正規表現が変更になりました。
うっかり0個でも0面でも振れるようになっていたのと、0123みたいな数でもオッケーになっていたので(うっかりすぎです)、正数を表す正規表現に直しました!
ちなみに、0と正数を表す正規表現は/0|[1-9]\d*/となり、小数点も含めば、/0|[1-9]\d*(.\d+)?/という感じ……だったと思います(え、適当?)
メジャーどころの正規表現は、どこかにあると思いますので、調べてみてください! というか、私は”好き”なだけでできる子じゃないので!

次は、変数宣言中に、parseIntですね。実数化する関数です。マッチで取り出したのは、一応文字列なので(javascriptは読替で勝手に数値化することもありますが)関数で数値化させます。

そして、forループで、ダイス個数分繰り返し、その結果を結果の配列と結果の合計値に入れていきます。
ランダム関数を含む処理の結果を、pushで配列に入れて、そこから取り出して結果に足していきます。

最後は、結果表示。結果配列の出力処理ですね。

これで、基本は完成ですね!
やりましたー!(ぱちぱちぱち)
たった30行以下で基礎基本がかけるものでした!

さて、これで基本ができたのですが、これからいろいろと拡張していく場合、どんどんとプログラムのソースが伸びていってしまいますね。
見づらくなってしまいます。
こういうものは、細かくばらばらに、1機能をひとまとまりにするのがマナーでルールです。
すると、後で拡張するとき便利です。

というわけで、関数化させましょう。
機能として更に拡張する予定なので、複数結果を返却できるようオブジェクトで返す関数です。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//textの中に○d△があるとき、取り出す
if (text.match(/^([1-9]\d*)d([1-9]\d*)$/i))
{
//ダイス個数
var diceNum = parseInt(RegExp.$1);
//ダイス面数
var diceFace = parseInt(RegExp.$2);

//ダイス基本関数呼び出し
var dice = basicDice(diceNum, diceFace);

//文字列出力処理
send(channel, prefix.nick + ":" + diceNum + "D" + diceFace
+ "=[." + dice.diceAns.join(".") + ".]=" + dice.diceSum);

}
}


/******************************************************
ダイス基本関数

基本説明
ダイス個数回分、ダイス面数で指定されたダイスを振り、
ダイスの振った結果をオブジェクトとして返却する。

in
diceNum:ダイス個数(正数)
diceFace:ダイス面数(正数)

out
ダイス結果object
[
diceAns:ダイス結果配列(Array)
diceSum:ダイス結果合計値
]
*******************************************************/
function basicDice(diceNum, diceFace)
{
//返却用ダイスobject
var dice = new Object();
//返却用ダイス結果合計値
dice.diceSum = 0;
//返却用ダイス結果配列
dice.diceAns = new Array();

//ダイス個数分、ダイス面数で指定されたダイスを振る。
for (var i = 0; i < diceNum; i++)
{
//ダイスを振った結果をダイス結果配列に。
dice.diceAns.push(Math.floor(Math.random() * diceFace) + 1);

//ダイスを振った結果を合計値に足していく。
dice.diceSum += dice.diceAns[i];
}

//結果返却
return(dice);
}


そのまんま、関数化しただけですね。
今回は入力処理側に、文字処理を預けてしまっています。
これは人の好みとか開発のルールとか、そういうものです。今はそこ以外入力処理がないことと、入力→入力制御処理(→ダイス処理”関数部分”)→出力、というのが見通しがいい感じなのでそのままにしてあります。
でも、この後拡張していく上で、どうやっていくか、を考えつついきましょう。

ちなみに補足というか蛇足ですが、関数化させると見通しがよくなります。しかし、関数化にともなって汎用性を高めると逆に処理が遅くなってしまうときもあるので、べたーと書いている人が悪いというわけではありません。
ようは、目的がわかっていて、そのためにどうするか、を考えて答えられればよいのですね。
ただ、関数化するときは、関数の説明はしっかり書いておくこと。これ重要! 超重要!

さて、ダイスとしてはこれで完成で、これだけでダイスを使用するゲームもできるのですが、便利ではありません。
というわけで、次回から、拡張していきましょうっ!
わくわく、拡張でーす!
posted by 海月歩空 at 20:26| Comment(0) | TrackBack(0) | プログラム

2009年03月06日

LimeChat2のjavaScriptでダイス作成(3)

スクリプト大好き、海月歩空です。こんばんは。

前回も、前々回も、注目だのなんだの言いつつ、説明すらしていないという体たらく。
し、調べて学ぶ猶予を作っているだけですよ!
勢いで書いている行き当たりばったりとか言わないで!
というわけで、前回のおさらい(要約)から。

・プログラムとは、入力・処理・出力の三大要素でできている。
元々の入出力イメージの仕様ができていれば外枠はできる。後は処理だけ。
・入力後最初に行う処理の入力制御。
文字の入力制御は、文字列操作・判定は正規表現を使うと便利。
こちらの意味が何となくわかるようになるとエクセレント!

ざっくりですね!
というか、毎回、この要約を見てから、前回の話のソースを見ればいいのかも。
そうすると、何となくわかるかな……はっ、すごく問題?

そんなこと言っている暇はないわ!
勢いで書いているうちに、最後まで行くのだわ!
(どなたですか?)
今回は入力制御ですわっ!

・ダイス作成(3) 入力制御(ぱらららーん)

というわけで、前回の入力制御後のソースを呼びましょう。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//textの中に○d△があるか
if (text.match(/^\d+d\d+$/i))
{
//文字列出力処理
send(channel, prefix.nick + ":" + text);
}
}

ここから、必要なものを取り出す機能を作ります。
さて、やっと前回やる予定だった、ダイスとはなんぞやを始めたいと思います。

Q.ダイスとはなんぞや?
A.さいころです。

お終い……あいたっ! ものなげないでっ!?
ということはジョークとして、さいころといえば、一般の方はわかりやすいですね。
メジャーなのは、1〜6の目がある6面の正方形です。
実際には、いろいろな面数のあるさいころがあるわけで、今回の仕様がダイスの個数とダイスの面数を入力するようになっていたわけですね。
……という説明は、こういう機能を作ろうとする人には、何となく嘘くさい教育番組的な感じがしているかも。

それはともかく。

今回必要なのは、○つまりダイスの個数と、△いわゆるダイスの面数ですね。
それを取り出せるように変更しましょう。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//textの中に○d△があるとき、取り出す(今回の注目A)
if (text.match(/^(\d+)d(\d+)$/i))

{
//文字列出力処理(今回の注目B)
send(channel, prefix.nick + ":" + "ダイスの個数=" + RegExp.$1
+ "/ダイスの面数=" + RegExp.$2 );

}
}

ほんのちょっと変わっただけですね(手抜き手抜き!)
手抜きとか言わないの!

変わったところと言えば、今回の注目Aのmatchの丸かっこが増えたことと、今回の注目BのRegExp.$1、RegExp.$2ですね。
これは、お察しの通り関係あります。
matchで丸かっこと対応する部分を、何番目、という感じで取り出す技なのです!(ばばーん)
そこで、○と△が取り出せる様になりました。やったね、べいべ!

ちなみに、別の方法で書くパターンもあります。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//textの中に○d△があるとき、取り出す(別パターン)
var matchData;
if (matchData = text.match(/^(\d+)d(\d+)$/i))

{
//文字列出力処理
send(channel, prefix.nick + ":" + "ダイスの個数=" + matchData[1]
+ "/ダイスの面数=" + matchData[2] );

}
}

どちらも同じです。ただ、うっかりいろいろやったあとに取りだそうとすると、RegExpの方では取り出せなくなってしまうかもしれません。
例えば、macth使っちゃうと上書きされてダメダメ。

ただ、個人的好みでは、RegExpなので、このまま行きます。
次回で、基本のダイス完成!
……基本? ということはまた別の方向が……?
お楽しみに!
posted by 海月歩空 at 02:14| Comment(0) | TrackBack(0) | プログラム

2009年03月01日

LimeChat2のjavaScriptでダイス作成(2)

大無反応連載中、海月歩空です。こんばんは。

すごい地味なことに対して、無駄に長く書いてしまっているため、読み取りづらいですが、ついてきていますでしょうか。
私は無理です(ならしないの!)
というわけで、前回のおさらい(要約)から。

・目的のプログラムを作るためには、なにが必要か。
どう動いて欲しいかの仕様が必要。
・そこで今回のダイススクリプトの仕様。

1.メッセージへデータ入力
・入力の形式は、○d△で、【ダイスの個数】d【ダイスの面数】とする。
2.メッセージにデータ出力
・出力の形式は、×:○d△=[.□.□.]=●で、入力者:【ダイスの個数】d【ダイスの面数】=[.【ダイス一個の結果】.【ダイス一個の結果】.]=【ダイス結果の合計値】とする。

ざっくりですね!
本当はココで、ダイスとはなんぞやとか始めないといけないんですが、出だしはプログラムの三大要素の入力、出力から行った方がわかりやすいのでこれで十分です。

ところで、このダイススクリプトのお話、誰に向けて話しているんでしょうか。
最低限、プログラムを書いたことがある人(JavaScriptをさわったことがある人)で、一番最初のハローワールド的なところは、LimeChat2のヘルプを見ている人、というかなりの隙間産業な方々です。
……それって、何人?(笑)

それはともかく。
ダイススクリプトを一気に作れる、なんて思わない方がいいわ!
プログラムは、試行錯誤の連続なのよ!(どなた様?)
というわけで、まず基本、ハローワールド的な状態のものを作りましょう。

・ダイス作成(2) 入出力の処理を書く(ぱらららーん)

つまり、ひな形ですね。これから拡張していきます。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//文字列出力処理
send(channel, prefix.nick + ":" + text);
}

これを使用すれば、あなたの発言を返してくれるスクリプトができたと思います。
event::onChannelTextってなんだろう的な話は、やっぱりLimeChat2のヘルプを見て確認してください(投げっぱなし)
これで基本の基本、入出力ができたわけです。
やっほう!

……早すぎるかも。

というわけで、正しい入力だけ反応するようにしましょう。
入力→処理→出力、という形にする第一歩、正しい入力の判断です。
今回は、○d△の○と△は正数、そして、そういう文字のみで入力されたメッセージのみ返却、という形にします。
ファイル名:dice.js
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{
//textの中に○d△があるか(今回の注目)
if (text.match(/^\d+d\d+$/i))
{

//文字列出力処理
send(channel, prefix.nick + ":" + text);
}
}

これで、3d8とか、2d6とか入力したときのみ、反応するようになったはずです。
これで、イメージ通りの入力制御ができるようになりましたね。

さて、今回の注目。
matchについてのお話。
matchは、正規表現を使って、その文字列があっているかどうかの結果を返します。
チャットは文字列加工が基本なので、この機能はとても重要!
この後もばんばん出てくるので、覚えておいてください。
正規表現覚えると入力制御がすごく便利!
日常じゃあまり使わないですけれど、便利!

ちなみに、私は正規表現がとても大好きですが、あんまり使い道がないです。
残念。
posted by 海月歩空 at 22:25| Comment(0) | TrackBack(0) | プログラム

LimeChat2のjavaScriptでダイス作成(1)

今回から大好きプログラムのコーナーを始める海月歩空です。こんばんは。

日記のリハビリを含めて、説明文章を書くことであたまをぐにぐにーと動かすために、はじめちゃいます!
いえ、最近妄想はかなりしているんですが、ここ最近の妄想を日記に書くと怪しいというか、ちょっとやばめなので封印しないといけないので、妄想ネタがないんです。
ネタがないのは、死んでいるのと同じよねー……。

というわけで、話のネタというかタネはたっぷりあるけれど、誰も求められていないLimeChat2のJavaScriptでダイス作成コーナーを始めたいと思います!

LimeChat2とはなんじゃらほい、みたいな人は速攻でおいていくのでそのつもりで(ひどい)
グーグル先生に聞きなさい!(スパルタ先生だ)

プログラム作成のお勉強といえば、”ハローワールド”に続いて行うのは、ランダムに結果を返すダイス(さいころ)プログラムです。
なぜなら、プログラムの三大要素、”入力”・”処理”・”出力”があって、更に処理の要素といえば、”判断”、”反復”、”計算”、この三つ。
これをまんべんなく組み込めて、バグが入り込む要素が多分にあり、プログラムの楽しさと難しさがえられるもの、これがダイスプログラムなのです!(私の持論)
というわけで、そんなダイスを作りたいと思います。

さて、プログラムを作る場合、なにを一番最初に始めますか?
あ、LimeChat2を用意するとか、そういうベタなことはおいといてくださいね!
ハイ、そこの人! 答えて!
まずは書いてみる? それも正しいです。
殺してでも奪い取る? 手に入れたものが正義ですからね。
ただ、ちょっと問題があります。法に触れるとかそういう感じの。
そう、一番の正解は妄想をする! うまく動いている姿を想像するです!
……ごほん、もとい、”仕様を決める”ですね。

・ダイス作成(1) 仕様を決める(ぱらららーん)

ものを作るときには、仕様を決めないといけません。
これ基本。要チェックや!(古い)
例えば、肉じゃがを作ろう、と思って料理の準備をします。
なれている人なら、準備しながら作ることができるかもしれません。
ただ、普通は料理のレシピを準備しないといけません。
レシピ=仕様なのです!(ばばーん)

というわけで、ダイススクリプトの仕様を決めましょう。
今回は、メジャーなダイスの仕様をいくつか引き継いで、以下のようにします。
正しい書き方わからないので、イメージだけ……というか通常個人で作る場合はイメージで十分ですね。
・ダイス仕様(基本のダイス)

1.メッセージへデータ入力
・入力の形式は、○d△で、【ダイスの個数】d【ダイスの面数】とする。
2.メッセージにデータ出力
・出力の形式は、×:○d△=[.□.□.]=●で、入力者:【ダイスの個数】d【ダイスの面数】=[.【ダイス一個の結果】.【ダイス一個の結果】.]=【ダイス結果の合計値】とする。

これは、基本の基本部分なので、拡張する機能とかもある予定……というよりも、実際はもうできているわけですが。

というわけで、おおざっぱにイメージができたところで、次は作成してみましょう。
posted by 海月歩空 at 15:15| Comment(0) | TrackBack(0) | プログラム

2009年02月23日

スクリプトのこと

書く書くと何度か言ってかいていない、そんな海月歩空です。こんばんは。

他の方のスクリプトを書いているブログを見て、コメント書いていたら、自分のところでなにもしていなかったことを思い出したわけです。
なので、LimeChat2のJavaScriptで、使える小技をひとつ。
(普通のJavaScriptでも使えるのですが、便利さの問題でLimeChat2向け)

LimeChat2では、”スクリプトの設定”で有効/無効が選べます。
つまり、機能ごとにファイルを区分けすることで、必要なものだけオンにすることができるのです。
これは便利!

しかし、ファイルごとを飛び越えて関数呼び出しとかはできません。
そのため、共通関数とか定数ファイルとかを別途作ることができないわけです。
これは不便!

というわけで、今回は共通関数とか定数ファイルとかを外から呼び出す方法です。


外部読み出し例
//読み込み処理
//外部ファイルオープン
var fileObj = openFile("共通関数の入ったjsファイル");
//読み込めた
if (fileObj)
{
try
{
//文字列読込
var fileStr = fileObj.readAll();
//ファイル閉じる
fileObj.close();
//関数読込(今回の注目点)
eval(fileStr);

//例えばココで読み込んだファイルからオブジェクト生成やらなにやら

//ロード成功
log("ロード成功");
}
catch(e)
{
//ファイルロードor関数読込失敗など。
//読み込む予定のファイルの関数の置き換えなどごちゃごちゃ
log("ロード失敗");
}
}
else
{
//読み込めない
//ファイルロードor関数読込失敗など。
//読み込む予定のファイルの関数の置き換えなどごちゃごちゃ
log("ファイルのっとふぁうんど");
}

(少し修正。onloadで囲んでしまうと、その中でしかできないため)
すごく単純に、”文字列を読み込んで、それをeval関数で再評価”という、よく使われる技法なんですけれどね。
ファイル間同士の行き来ができないという制限があるところでは、使い勝手がいいわけです。
というわけで、上の例をアレンジして使えば、他のファイルにある関数や定数は呼び出せるようになります。
後は、ファイル名を関数名にして、関数型プログラミング的な使用方法をするもよし。
設定ファイルを単純に取り込むのもよし。
フリーのJavaScriptファイルを取り込む形式にしておいて、取り込めば機能アップできるように編集するもよし。

eval関数が嫌いな人も多いと思いますけれど、私はスクリプトといえばevalなのです。
スクリプト好きとして愛する関数。
このevalを使ってみてください。

……というわけで、私に変な発言やらなにやらを期待しているひとは、すみません。
プログラムやらスクリプトのときはまじめな私なのです!
大好きだぁぁぁ!
posted by 海月歩空 at 00:26| Comment(0) | TrackBack(0) | プログラム

2009年02月15日

妄想練習中

ただいま脳味噌回復作業中の海月歩空です。こんばんは。

去年はいろいろとぐーたらしていたのでさびついてしまった、妄想脳を復活させるためただいま頑張り中でございます。
エロからギャグまで、こうしたら面白いんじゃないか、みたいな想像を真っ昼間から一日1時間はするような、そんな特訓。
なんて大変……!

え、妄想は楽しいじゃないか?
あ、あなたは私のお仲間なんですね。
でも、大変なのは、そこじゃないんです。

なにが一番大変かというと、妄想しているうちに「にへらー」となってしまうのを隠さないといけないということ。
そう、端から見たら、変な人になってしまうんですよ!

……いや、いつも変な人だとかはいわないでね!
自覚はなくもないけれど!
posted by 海月歩空 at 21:52| Comment(0) | TrackBack(0) | 日記

2009年02月08日

すごいごぶさターン

お久しぶりゲッツ!

……ごまかしきれない気配の海月歩空です。こんばんは。

昨年はどたばたばたんと大暴れで、ブログを書いている暇がなく……というわけでもなく、家の引っ越しをしてその後すっかり放置気味でした。
こら! 悪い子私!

小ネタは、いっぱいいろいろとあったのですが、旬物なので残念さん。
ゴーオンジャーのエキストラの人にあった話とか、いろいろあるんですけれどね。
というわけで、これからはちょくちょく書いていきたい、そう思いました。

というわけで、地味に次回からは、ネタがなくてもいろいろ書いていきたいと思います。
たとえば、去年は、文章パワーが落ちてきていたので、その分Limechat2用ダイススクリプトとかを作ったりしていました。
なので、それをアップしたり作り方を解説したりしつつブログを活性化!
javascriptタイプのダイススクリプトを書いている人はそんなにいなさそう、なのでちょっとは興味を持たれるかなーと。

……え、文章は?
そ、そのうちね……。
posted by 海月歩空 at 12:49| Comment(0) | TrackBack(0) | 日記

2008年01月06日

お年玉

もう、年始は支出の方が多い海月歩空です。こんばんは。

今現在、お年玉なんか上げる側になったりしているのですが、懐の痛みに泣いちゃう感じです!
ああ、あの金額があれば、本が何冊買えるのかしら……とか思ってしまう、私。
そして、そんな風に思ったら、本が買いたくなって、更に倍出費。

うひー!? 財布の中には紙がない!?

そうして、財布の中に残ったのは、小銭だけ。
私の財布は玉だらけ、そんなお正月後半でした。
posted by 海月歩空 at 02:14| Comment(0) | TrackBack(0) | 日記