2010年06月07日

画像からプログラムを作る

東京での初めての梅雨入りが近づきつつある今日この頃。
はたして、我が家の洗濯物事情は、この季節を乗り越えられるのだろうか・・・雨
こんにちは、ハラですわーい(嬉しい顔)

ちょっと面白い言語の事を知ったので、それについて書いてみたいと思いますメモ

スクリプト言語やバッチファイルなどを使い、定型的な作業を楽に行いたいと思った場合、
共通した泣き所があったりしますもうやだ〜(悲しい顔)

その作業の中に、GUIツールの操作が含まれているケースですパンチ

特定のメニューを開き選択肢、出てきたダイアログのボタンをクリックして・・・・
といった工程を実現しようとするとかなり大変ですバッド(下向き矢印)


これらの問題を解決出来るかもしれないのが、「SIKULI」というプログラミング環境ですひらめき

このSIKULIの面白い所は、スクリーンショットカメラを使ってプログラムを組めるという所です。
現在の画面や保存しておいた画像ファイルを使い、一部分を選択します。
その選択した部分をプログラムに使えてしまうんですね。

例えば、「click」というコマンドでは、↑で指定した画像の一部分を
現在の画面内から探し、その画像の中で指定した場所を左クリックする。
という機能を提供してくれます。

他にも、「指定した画面が現れるまで待つ機能」や
「文字列を入力する機能」など色々実現出来そうな機能が揃っていますひらめき

何か面白い事はできないかと、実際に触ってみました。
が・・・・意外と難しい・・・・ふらふら

画像で比較するため、複数の場所で候補が見つかる画像が使えなかったり、
実際に実行した時に別のウィンドウを開いていて、正しく動作しなかったりと
今までの言語とは違うコツが要りそうですあせあせ(飛び散る汗)

また、画像での比較を行うため、全体的に動作が遅いという特徴もあります。


このSIKULI自体がベータ版であるように、これから拡張・改良されていくのだと思います。
すごく可能性を感じるだけに、今後の進展に期待したいですねわーい(嬉しい顔)

検索してみると色々と情報が見つかりますので、
興味がある方は調べてみても面白いと思いますよ。

posted by 管理人 at 16:22 | Comment(0) | プログラミング

2010年04月09日

using

こんにちは、イワムーですわーい(嬉しい顔)

スギ花粉が終息し、ホッと一息ついていたのもつかの間、次はヒノキ花粉が猛威を奮っていますねたらーっ(汗)
以前に無花粉スギの開発に成功したというニュースを見て大喜びした覚えがありますが、無花粉ヒノキの開発も切に願ってやみません・・・。(もうあるかもexclamation&question


さて、今日はC++プログラムの小ネタを紹介しようと思いますひらめき
継承ポリモーフィズムの話です。
(分からない方は詳しく解説された他のWebページがあるので、そちらを参照してください)

class CharacterBase {
public:
  CharacterBase(void){}
  ~CharacterBase(void){}

  //初期化処理
  virtual void init(const Vector& position, const Vector& direction);

private:
  // メンバ定義
};

class Player : public CharacterBase {
public:
   Player (void){}
   ~Player (void){}

   //初期化処理
   void init(const Vector& position, const Vector& direction, const Vector3& scale);

private:
   // メンバ定義
};

上記例では、ポリモーフィズムの概念上、コンパイラは警告を出しますふらふら
警告が出る・出ないはコンパイラ、またコンパイラの警告レベルに依存します

initという名前のメソッドは基底クラスの仮想関数になっています。
今回のケースでは、派生クラスで同名のメソッドを宣言しているため、コンパイラ側からは「基底の仮想関数をオーバーライドするつもりで、引数を間違えたのではないか?」と見えてしまいます。
ですが、コーダーの意図としては「基底側と同様に機能としては初期化処理なのでinit()という名前のメソッドにしているが、引数や戻り値の異なる、基底側のinit()とは別のメソッドとして定義した」わけなので、コンパイラにその意図を知らせてあげればよいわけです。

class Player : public CharacterBase {
public:
   Player (void){}
   ~Player (void){}

   //初期化処理
   using CharacterBase::init; // ※この宣言に注目!!
   void init(const Vector& position, const Vector& direction, const Vector3& scale);

private:
   // メンバ定義
};

ここで using の登場ですexclamation×2
このように基底クラスの同名メソッドをusing宣言しておくことで、警告を回避できるわけですグッド(上向き矢印)
using は名前空間を使用する際によく用いられる機能ですが、上記ケースでの利用はあまり知られていない(?)かと思ったので、紹介させていただきましたわーい(嬉しい顔)
何かのお役に立てばと思いますexclamation

補足:
上記例では、コンパイラの警告を除外することでも回避できます。
もちろん init()でなく、initPlayer()のようにメソッド名を変えるだけでも解決できます。
基底クラスと派生クラスで初期化処理を分けなければいけないような設計自体を見直すことも考えるべきかもしれません。
このあたりはケースバイケースですねー(長音記号2)

posted by 管理人 at 14:01 | Comment(0) | プログラミング

2010年02月05日

合体っ!

最近は、4月並みの暖かさ晴れになったり、いきなり冷え込んだり雪と不安定な気候が続いていますね。
こんな時こそ体調を崩しやすいものです。ちなみに、私はちゃんと風邪を引きましたふらふら
早く治さないと駄目ですね・・・・
こんにちは、ハラです。

今回は、何回かぶりにRubyについて書いてみたいと思います。
以前、色々な種類のテキストデータを読み込み、バイナリデータとして出力する方法を書いてみました。
続きとして、その出力したバイナリデータを合体exclamation×2して、1つのファイルにしてみたいと思います。

サンプルとして、「3つのファイルを読み込み、ファイルサイズを付加して中身を繋げる」スクリプトを
書いてみますメモ
 # 繋ぎ合わせるファイルの名前
fileNameArray = ["file1.dat", "file2.dat", "file3.dat"]

# 書き込み先のファイルをバイナリで開く
File.open("result.dat", "wb") do | dstFile |
# 繋ぎ合わせるバイナリファイルを順に開く
fileNameArray.each do | fileName |
File.open(fileName, "rb") do | srcFile |
# データを読み込み
data = srcFile.read

# データサイズを書き込み
dstFile.write [data.size].pack("L")

# データを書き込み
dstFile.write data
end
end
end

実行して貰えれば、3つのファイルを繋げた1つのファイルが出来上がることが確認できると思いますひらめき

このスクリプトでは、読み込むファイルを固定していたり、
ファイルの中身に関する情報がサイズしかありませんバッド(下向き矢印)

読み込むファイルを「指定したディレクトル内のファイル全部」に変えたり、
ファイルサイズの直後にファイルの種類を追加したりすれば、
さらに汎用性が増していきますねグッド(上向き矢印)


ちなみに、複数のファイルを1つのファイルにする理由は色々あるのですが、
その1つに「少ないファイル数の方が、読み込み時間が少なくなる」というのがあります時計

例えば、10000バイトのファイルを1つ読み込むより、
100バイトのファイルを100個読み込む方が多く時間がかかりますたらーっ(汗)

提出作品をハードディスクから実行する場合は、さほど気にならないかもしれません。
ですが、極端にファイル数が多い場合や、CDCDから実行した場合などは、
ファイル数を減らす事による読み込み時間の減少を実感できると思います。

今は役に立たなくても、いつか役に立つかもしれませんよ?
良ければ、頭の片隅にでも覚えておいて下さいな。

posted by 管理人 at 10:39 | Comment(0) | プログラミング

2010年01月27日

確率の問題

こんにちは。
1月も終わりに近づき、周りから正月らしさが消えていくのを残念に思っている、ナカムラです。
といっても、私が正月らしさを感じていたのは、もっぱら年末年始の特番からですがたらーっ(汗)
私が年始に観ていた番組で、面白いクイズぴかぴか(新しい)を出していました。
今回はその紹介をしたいと思います。

*

あなたは、あるクイズ番組に出場しています。
あなたはそのクイズ番組で優勝し、いよいよ最後の賞品をもらえるゲームにチャレンジすることになりました。
そのゲームとは、中身が見えない3つの箱プレゼント(A,B,C)の中から、賞品が入っている1つの箱を当てるというもの。

あなたは、Aの箱を選びました。
すると司会者は、次のような行動を取ったのです。

「Aの箱を選びましたね?
 では私だけ、残りのBとCの箱の中を確認させて頂きます。
 (中身を確認)
 …ふむふむ、なるほど。
 では、賞品の入っていないCの箱をこの場から取り除きます。
 さて、最後のチャンスです。
 今なら、Bの箱に変えてもいいですよ?どうします?」

さて、あなたは最初の選択を信じ、Aの箱のままでいたほうが良いのでしょうか?
それとも、Aの選択をひるがえし、Bの箱を選んだ方が良いのでしょうか?
もちろん司会者は、Cの箱に賞品が入ってるのに取り除く…なんてズルはしてませんよ!

*

「最後に残った2つの箱の内、どちらかに賞品が入ってるんだから、どちらを選ぼうとも確率は1/2でしょ?」

と思いがちですが、実は違うんです。
ポイントは、司会者が箱の中身を確認した上で、ハズレの箱を取り除いているという所にあります。
正解は、10行後バッド(下向き矢印)exclamation










正解は…最初の選択をひるがえし、司会者が残してくれた箱を選んだ方が賢明手(チョキ)です。
最初に自分が選んだ箱が当たる確率は1/3で、司会者が残してくれた箱が当たる確率は、2/3になります。
ちょっと納得できませんか?では話を極端にしてみるとどうでしょう?

*

あなたの目の前に、100個の箱があります。
あなたはその内の1つを選びました。
司会者は、残りの99個の中身を確認し、1つを残してハズレである98個を除外してくれました。
さて、あなたは最初の選択を変えずにいるべきでしょうか?
それとも、司会者が99個の中から残してくれた1個を選ぶべきでしょうか?

*

これは、
「あなたが最初に選んだ1個が当たる確率と、司会者が確認した99個の中に当たりがある確率、どちらが高いでしょう?」
と聞いているのと同じです。
これなら、後者が正解ぴかぴか(新しい)であることが分かりやすいのではないでしょうか?

まだ納得できませんか?
ではもしあなたがプログラムを組めるのなら、プログラマー独特の検証方法がありますexclamation
そうです、実際に上記のクイズをシミュレートするプログラムを組めばいいのですexclamation×2
私も試しにプログラムを組んで試してみたところ、
10000回のシミュレーション中、最初の選択を変えずに当たった回数が、3354回。
逆に、変えた方が当たっていた回数が 6646回と、ほぼ 1/32/3 の関係になっていました。

このプログラムを組んでいる最中、実際にシミュレーションを行うまでもなく、

「あ、これは…選択を変えた方が 2/3 の確率で当たるわひらめき

というのが理解できるようになるかと思います。
不具合の内容を人に説明している内に、バグの原因が分かる事があるのと同じように、上記のクイズのアルゴリズムを考えながらコーディングしている内に、理屈が腑に落ちるのだと思いますわーい(嬉しい顔)

プログラムを組める方は、是非チャレンジしてみて下さい手(グー)


posted by 管理人 at 15:26 | Comment(5) | プログラミング

2010年01月26日

C++ 参照

こんにちは。平尾です。
寒い時期になってから移動には電車を利用していましたが、
がんばって自転車に戻すようにしています。
人間ドックを気にしてというわけじゃないですよわーい(嬉しい顔)
受ける予定ではありますが(笑)

***

今日はC++の参照についてちょこっとだけお話します。
C言語をメインに使ってきた人だと全部ポインタで出来る!パンチ
なんて思ってしまいがちですが、
それぞれのメリットとデメリットを知った上でちゃんと使い分けるのが良いですねひらめき


参照は関数の引数で使うことが多いです。
こんな感じです。
int function(Param& param);

メリットとしては必ず実体が入ってくるため、
不正アドレス使用によるメモリ破壊を起こさないということです。
なのでポインタと比べ、安全性が高いと言われますグッド(上向き矢印)

デメリットとしてはポインタの様にNULLを渡すことができないので、
例外的な判定を行うことはできなくなりますバッド(下向き矢印)




もうひとつ変わった使い方になるかもしれませんが、
参照をエイリアス(別名)として使用する方法があります。

ゲームでキャラクターを作成しているとき、
メモリを節約するために各行動で共用するフリーのワークを用意することがあります。
class Soldier {
:
// それぞれの行動処理内で自由に使用できるワーク
unsigned int freeWork[FREE_WORK_COUNT];
};

これをエイリアスで置き換えて使用することもできます。
int attack(void)
{
// 攻撃中にダメージを受けた回数。一定以上超えるとダメージへ
unsigned int& damageCount = freeWork[0];
:
}

参照をしているので、damageCount という名前で freeWork[0] を直接操作することができます。
分かりやすい名前に置き換えておけば、別の担当者が見たときに読みやすくなりますサーチ(調べる)ぴかぴか(新しい)

ただし、あちこちで書きすぎると逆に分かりにくくなってしまうので要注意です!!ふらふら
関数の先頭で渡す程度にしておくのが良いと思います。


***

健康な体が生きていく上で最も高価な資本です!有料(プライスレス)
健康体でモリモリがんばれるよう、自転車に乗って体力をつけていきたいですね手(グー)

posted by 管理人 at 14:44 | Comment(0) | プログラミング

2010年01月18日

Type Traits(型特性)

お久しぶりです。みやじーです。exclamation×2
今日は、最近はまっている"C++のテンプレート"についてお話したいと思います。わーい(嬉しい顔)

標準C++ライブラリのvectorやlistなどでテンプレートを使ったことのある方も多いと思いますが、
実は、テンプレートを駆使するとコンパイル時にいろいろと特殊なことができます。
なかでも面白いのが、コンパイル時に型の特性を判断するというものです。るんるん

簡単な例として
以下のようにプログラムすると、型がポインタ型かどうか判別できます。
(注)ここでテンプレートの部分特殊化という機能を用いています。
詳しくは http://www.geocities.jp/ky_webid/cpp/language/037.html


#include <stdio.h>

template<typename T>
struct IsPointer
{
    static const bool value = false;
};

// 部分特殊化
template<typename T>
struct IsPointer<T*>
{
    static const bool value = true;
};

int main()
{
    printf("int is %s pointer.\n", IsPointer<int>::value ? "" : "not");
    printf("int* is %s pointer.\n", IsPointer<int*>::value ? "" : "not");
    return 0;
}

上記のような型の特性を調べるテンプレートを組み合わせることで、
コンパイル時に型の継承関係などを調べることができます。わーい(嬉しい顔)

このようなテンプレートの使い方に関しては
"C++テンプレートテクニック"という本がコンパクトにまとまりつつも、深くまで踏み込んでいてお勧めです。手(チョキ)

http://www.amazon.co.jp/dp/4797354534

うーん。テンプレートの世界は奥が深いなぁ。たらーっ(汗)

posted by 管理人 at 21:02 | Comment(0) | プログラミング

2009年12月16日

浮動小数点誤差

こんにちは。平尾です。
朝布団から出るのが辛い時期になってきました雪
ついつい二度寝…なんてことをしたくなります。
そんな折、こんな商品があるのを発見!
http://www.sleeptracker.jp/
意外と高額です…。
サンタさんが運んで来てくれないでしょうかクリスマスプレゼント



気を取り直して、今日は浮動小数点誤差について話をします。
プログラムを始めた頃は誰もがハマってしまう道ではないかと思います。

C言語にはfloatという小数を扱える型(浮動小数点型)があります。
ところが、意外なことに正確な 0.1 を表現できないのですもうやだ〜(悲しい顔)
これだけ技術が進歩した世の中なのに、なぜなのでしょうか…。



コンピュータは2進数で数値を記憶します。
floatの場合、一般的には
  ・符号部 1 ビット
  ・指数部 8 ビット
  ・仮数部 23 ビット
といった形になります。(特殊なハードは除きます)

0.1を2進数で表現する場合、
001111011100110011001100110011001100110011001100...
と割り切れない値(循環小数)になってしまうため、どこかで区切らないといけませんend
32bit float の場合、33bit目が丸められて
00111101110011001100110011001101
という形になります。


このように最後のビットが丸められるため、正確な値を保持できません。


例えば次のような処理を行ったとします。
    float val = 0.0f;
for( int i=0; i<10; i++ ) {
val += 0.1f;
}

if( val != 1.0f ) {
printf("val は 1.0です");
} else {
printf("val は 1.0ではありません");
}

10回0.1を足しているので1になってくれないと困るのですが、「1.0ではありません」と表示されますがく〜(落胆した顔)
これは上記の丸め誤差があるため、正確に1.0にならないためです。
浮動小数点を=で比較するのはいけません。
ではどう比較すれば良いのでしょうか?


続きはWEBで…


あ、WEB上でしたわーい(嬉しい顔)
「一定の範囲で比較する」というのが答えです。
    if( ((1.0f - 0.1f) < val) && (val < (1.0f + 0.1f)) ) {
printf("val は 1.0です");
} else {
printf("val は 1.0ではありません");
}

でもさすがに0.1の誤差は大きすぎます。


そんな時に使用するのが FLT_EPSILON という定義です。
FLT_EPSILON は float.h で定義されているもので、
値としては 1.192092896e-07F (つまり0.0000001192092896) となっています。
定義内容としては「1.0+FLT_EPSILON !=1.0 となる最小値」となっています。
ちょっと乱暴ですが、分かりやすく言うと「すごく小さな値」ということになります。


浮動小数点の誤差を考慮する場合、この値を利用して判定するのが一般的ですひらめき
    if( ((1.0f - FLT_EPSILON) < val) && (val < (1.0f + FLT_EPSILON)) ) {
printf("val は 1.0です");
} else {
printf("val は 1.0ではありません");
}


使用用途などによってはFLT_EPSILONでは判定できない、なんてこともあるかと思います。
そういうときは
  ・単純に判定する範囲を広げる
  ・double型を使用して精度を上げる(double型の場合はDBL_EPSILONになります)
  ・固定小数点(整数型で小数点を表現する)
など、いろいろ解法はあると思います。


浮動小数点にはこういった誤差が存在しますので、単純な比較をしないよう、皆さんも十分ご注意下さい!ぴかぴか(新しい)



こういったプログラム話が大好きな学生の方、ご応募お待ちしております!わーい(嬉しい顔)

posted by 管理人 at 15:24 | Comment(0) | プログラミング

2009年12月01日

ちょっと変わった範囲選択

こんにちは、マイキーですexclamation

今日から12月です。
12月といえばクリスマスクリスマスクリスマスといえばクリスマス商戦パンチ
今年も多くのビッグタイトルが発売されますね。
僕もいくつか買う予定をしていますが、積んであるソフトも数多く・・・。
年末は積みゲー解消に勤しむことになりそうですあせあせ(飛び散る汗)

***

本日はテキストエディタの矩形選択(ブロック選択)をご紹介しようと思います。
以前平尾さんが紹介して下さったVisualStudioのブックマーク機能もそうでしたが、
「便利だけどあまり知られていない機能」の一つではないでしょうか。

使い方はVisualStudioなら「Altキーを押しながら範囲選択」、キーボードなら「Alt + Shift + 方向キー」で
20091201_kukei
このように矩形範囲を選択できます。

これを使うと指定列以降のみインデント調整ができたり、複数行の特定列だけ切り取ることができたりと、複数行に渡ってのソース整理が非常に簡単に行えます。
また上記Altキー(+ Shiftキー)に加えて、Ctrlキーを押しながら操作すると単語単位での矩形範囲選択になるので、より手早く範囲選択する事が可能です(多少の慣れは必要ですが・・・)。

そう頻繁に使う機能ではありませんが、ソースを整理する時に使ってみると意外と役に立ちます。
年末の大掃除ならぬ大ソース整理の際に、お試しあれぴかぴか(新しい)

posted by 管理人 at 11:25 | Comment(0) | プログラミング

2009年11月30日

char型のキャストに注意

こんにちは、イワムーですわーい(嬉しい顔)

昨日のボクシングの試合はすごかったですねexclamation×2
TVを見終わった後、鏡の前で思わずシャドーボクシングをしてしまったのは私だけではないはず・・・あせあせ(飛び散る汗)

さて、学生の皆さんはそろそろ就職活動の時期ですね!!
リクルートスーツに身を包んだ初々しい姿を街で見かけるようになり、当時の記憶がよみがえってきますひらめき

専門学校に通っている方は就職作品作りに精を出しているのではないでしょうか?
そこで今日は、就職作品制作時に私が陥った恥ずかしいバグを皆さんに公開しようと思いますたらーっ(汗)
(少しでも参考になれば幸いです・・・)

// char型の-1を終了を示す値として扱う
#define ARRAY_END (0xff)

// 配列サイズ削減のため、char型でテーブルを定義
char array[] = {
  1,
  2,
  3,
  4,
  ・
  ・
  ・
  ARRAY_END
};

bool func(char no)
{
   switch( no )
   case 1:
     // 処理
     break;
   case 2:
     // 処理
     break;
   ・
   ・
   ・
   case ARRAY_END:
     return true;
   }
   return false;
}

int main(void)
{
   int cnt = 0;
   for( ; ; ){
     if( func( array[cnt++] ) ){
       break;
     }
   }
   return 0;
}

このコードですが、予期せぬ動作をします。
なぜなら関数func()内のswitch文の終了を示す「case ARRAY_END:」の箇所に処理が来ないからです。
これはC言語ではswitch文に値を渡すと、暗黙にint型にキャストされるという仕様になっているせいです。
つまり、char型の-1のつもりで記述した0xffが、intに型変換された時点で0xffffffffに符号拡張されてしまうわけですねバッド(下向き矢印)

上記例では、int型の4byteをケチってchar型のテーブルを定義したことで、この問題を引き起こしていますが、同じような理由でint型を使用せずにchar型を使用した経験がある方も多いのではないでしょうか。

もし同じようなコードを書く場合は、注意してみてくださいねパンチ
(※処理系により、char型の符号付きが変わります)

では、充実した就職活動をわーい(嬉しい顔)
ヘキサドライブへの応募もモチロンドシドシお願いしますexclamation×2
応募はコチラ

posted by 管理人 at 18:18 | Comment(0) | プログラミング

2009年09月11日

アナログスティックの値

こんにちは。平尾です。
ドラクエのプレイ時間は150を超えました。まだまだ遊びます!パンチ


今回はアナログスティックの入力について少し話をしたいと思います。

就職作品などでコントローラーの入力を取ってきてゲームに使用したりすると思います。ゲーム
最近だとXbox360のコントローラをPCに差せばすぐ使えるので、お手軽ですよね。

アナログスティックの値は、中心からの位置が返ってきます。
20090911_00.png

スティックを触っていない状態でも中心部分では小さな値が入ってしまいます。
これはハード的にどうしようもない部分なので、
中心から一定距離は反応させないようにする必要があります。
20090911_01.png


このときに、やってしまいがちな判定として、次のようなものがあります。
if( abs(x) < deadValue ) {
x = 0;
}
if( abs(y) < deadValue ) {
y = 0;
}
こう記述してしまうと、中心部分はいいのですが、赤い部分の細かい値も消されてしまうため、黒い軸上へと補正されてしまいます。
20090911_02.png

これはもったいない!ふらふら
というわけで、補正する場合は次のような式がいいですね。
if( (abs(x) < deadValue) && (abs(y) < deadValue) ) {
x = 0;
y = 0;
}
こうすれば赤い部分のみ、値が0に補正されます。わーい(嬉しい顔)
20090911_03.png
もちろん、中心からの距離を求める方がより綺麗に円形で補正できますよ。ひらめき



少し変わった方法として、距離をn乗させるという手法もあります。
中心からの最大距離を1として、その値をn乗すると次の図のような形になります。
20090911_04.png

青い線がアナログスティックから取得した値です。それをn乗した値が下の青以外の線です。
(左の灰色部分は、先ほどの灰色の円と同じく、0に補正する範囲です)
こうしておけば中心付近の値がほぼ0になりますので、0に補正する処理が不要となります。
中心でもすごく細かい値が入るので、何か細かい操作をさせたいときに有効です。
また、0に補正する処理が無くなるため、急に入力が入った感じなどを消すことが出来ます。
よりアナログ的な入力ができるわけです。手(チョキ)
nの値をどの辺に落ち着けるかは、実際のゲームを触りつつ、調整していくのがいいと思います。


いかがでしたでしょうか。少しは役に立ちましたか?
少しの工夫でゲームの操作感が良くなったりすることは多いと思います。
広い視野でいろんな創意工夫ができるよう、がんばっていきたいと思います!手(グー)ぴかぴか(新しい)


posted by 管理人 at 19:00 | Comment(0) | プログラミング