素人プログラマーの日常

効率の良いコード、美しいコードなんて書けません。

進化

前回、タワーディフェンスを作ろうか、な~んてことを書きましたが、いまいち良いアイディアが浮かばず、急遽予定変更です。まあ、気分で作っていくようなことは過去に書きましたが、自分でも全部を変更するとは思いませんでした(笑



で、何を作るかというと、実際に私がやってみて面白いと感じた落ち物パズルです。それをパクオマージュして同じシステムで作ります。どんな感じかというと、同じブロックを3つ以上隣接させると合体し一段階進化して、進化するごとに落とすブロックの種類が増えてきて複雑になっていきます。次の進化をさせるためのブロックは出てこないので、既存のブロックを進化させて上手く隣接させなければなりません。10種類くらいになるとかなり難しくなります。難しいので、従来の落ち物のように次から次へとブロックが落ちてくるものではなく、自分で落とすまでじっくり考える時間があります。

このゲームはブロックを落とすエリアが狭いほうが手頃な面白さになりますが、私はそれをちょっと広げてブロックが15種類くらいまで進化できるようにしようと考えています。というのも、狭いとなんだか物足りない感覚になるんですよね。その物足りなさで「もう1回やろう!」となるので悪いことではないんですが、私としては「もっとお腹いっぱい楽しみたい!」それなら「自分で作ろう!」となったわけです。


というわけでお腹いっぱいになる落ち物パズル作成中です。


実は少し前から取り掛かっています。ただ、特に記事にすることもないかな~と、ブログは放置のまま進めていました。ですが、ここでようやく書くことが見つかったので書いていきます。


これからブロックの隣接判定に入るところです。ここは正直なところどうしようかと悩みました。基点となるブロックから隣接ブロックがあれば1回ずつ範囲を広げて for文で探索という考え方が最初はありましたが、「これって再帰でイケる!」ということに気付き、隣接したブロックをまた基点として関数を再帰呼び出しすることにしました。元々の基点を進化させることを考えると微妙に複雑になりそうな予感です。まともに再帰を使うのは初めてですが、この方法でやってみます。

ざっくりとこんな感じ

void EvolusionSearch( int x , int y ){

    右のブロックが同じなら EvolutionSearch( x+1 , y );
    左のブロックが同じなら EvolutionSearch( x-1 , y );
    上のブロックが同じなら EvolutionSearch( x , y-1 );
    下のブロックが同じなら EvolutionSearch( x , y+1 );

}



これに、無限再帰にならないための条件や、エリア内の判定、後から全部一度に消すためにマーキングなどを追加します。


それと、ブロックの出現率を乱数だけに任せるのではなく、ある程度均一にそれでいて新しいブロックは出現率を低めに設定したい(すぐに次の進化が出来ないように)ということから、出現率に相関関係を持たせることにしました。relative[ 20 ]をそれぞれのブロックの出現に合わせて増減させます。この値が高ければ出現確率が高いということです。一度出現したらマイナスして再度出現しにくくして、他はプラスします。まだ出てこないブロックは1のまま放置。マイナスよりもプラスを多くすることで、1回落とすごとに合計値は増えていきます。増えれば増えるほど新しいブロックの相対的な出現確率は低くなります。確率が低ければプラスされる確率は高くなるので、何回かブロックを落としていると他のブロックと同程度の確率になっていきます。



わかりやすく書いたつもりですが、文章だけでは理解しにくいかな?プログラミングをやったことない人には読んでも全然わからないんだろうな~、なんて思っています。経験者でもわかりづらいかもしれませんが(笑