VBAでパフォーマンスの良いライフゲームをつくろう その5 Ver7と8.1
- はじめに
このコーナーも第5回。
飽きたか飽きてないかでいうと
飽きてきました笑
- Ver7は配列
Ver7はめちゃ速くなります。
このアイディアは思い浮かんではいたものの
実装するとすごいめんどくさくなりそうだなー
と思って放置していたのですが
いいやり方を思いついたのでようやく実装できます。
シートへのアクセスを減らして速度を上げることが一番簡単な手法。
今回はまずシートの情報を配列に書いて
配列の中身を書き換えて
最後に配列をシートに貼り付けます。
今まではシートの情報を取得して
計算の結果を配列に書いて
最後に配列を貼り付ける
というやり方でした。
ちょっと中途半端なやり方でしたが
シート情報を配列に入れてしまうと配列のサイズを決められてしまいます。
ふつうはそれは便利な特徴なのですが
そうなってしまうと配列の中に「隅」や「端」ができてしまいます。
それらの周囲は8マスではなくなってしまうので
計算するのに特別なやり方が必要になってしまいます。
これはまぁ書けばいいのですがちょっと大変そうだなぁ
と思って書いていませんでした。
ただ今回思いつきました。
読み込むシート情報を本来必要なものより一回り大きく読み込めばいいんです。
たとえばRange(cells(2,2),cells(9,9))の88マスを扱いたい場合は
Range(cells(1,1),cells(10,10))の1010マスを読み込んで
実際に処理するのは8*8マス分にすれば解決します。
配列で説明すると
10*10のシート情報をStockに書き込むと
Stock(1 to 10, 1 to 10)として書き込まれます。
そしてcell_jdgでは
For i = 2 to 9 For j = 2 to 9 ‘処理をする Next Next
みたいにすれば大丈夫です。
ただ処理の仕方も今までとは少し違うのでcell_jdgのちゃんとしたコードを載せますね。
Function cell_jdg(f_size, stock, q) As Variant() Dim p1 As Variant Dim trgt As Range Dim cnt As Integer Dim ans() As Variant ReDim ans(1 To f_size + 2, 1 To f_size + 2) '------------------------------------------------ 'field内の各セルに対して '自身と周囲の計9マスの生きているセルを数えて 'それによって生死を判定します '生きている場合はそのセルに対応するans()に1を入れる '------------------------------------------------ For i = 2 To f_size + 1 For j = 2 To f_size + 1 cnt = stock(i - 1, j - 1) + stock(i - 1, j) + stock(i - 1, j + 1) + _ stock(i, j - 1) + stock(i, j) + stock(i, j + 1) + _ stock(i + 1, j - 1) + stock(i + 1, j) + stock(i + 1, j + 1) Select Case stock(i, j) Case 1 If cnt = 3 Or cnt = 4 Then ans(i, j) = 1 End If Case Else If cnt = 3 Then ans(i, j) = 1 End If End Select Next j Next i cell_jdg = ans End Function
これで速度がどうなるかというと。
f_size\Version | Ver6_1 | Ver7 |
---|---|---|
30 | 調査終了 0.078125 | 調査終了0.0078125 |
更新終了 0.0625 | 更新終了0.0546875 | |
50 | 調査終了 0.21875 | 調査終了0.0078125 |
更新終了 0.109375 | 更新終了0.109375 | |
70 | 調査終了0.4208984 | 調査終了0.015625 |
更新終了0.21875 | 更新終了0.15625 |
調査時間が30倍くらい?に上がりました。
更新時間はCell_dscをいじっていないので特に変わらず。
このコーナーの初めのほうで決めた目標が100*100のセルに対して1秒間隔で画面を更新していくことでした
なんだか行けそうなので試してみますか。
調査終了0.046875
更新終了0.328125
余裕ですね笑
これにてチャレンジクリア!
。。。
というのもあっけないですね。
Ver7にケチをつけるなら
更新速度の遅さ。
7070 つまり4900マスで0.15秒
100100 10000マスで0.32秒
これは遠からず壁が来ますね。
更新速度にこだわったVer8を作ってみましょう。
- 更新速度を上げよう
これはシンプルなやり方がありますよね。
書き込むセル数が肝なら
それを減らせばよい。
1行の内容を1つのセルに入れてみましょう。
ただしこれを行うと欠点もあります。
セルの条件付き書式が使えなくなることと
数値以外のものを扱わねばならいことと
1つのセルに対するデータ量が増えてしまうこと。
ちなみに初期画面はこんな感じです。
“■”が生きているセル
”□”が死んでいるセル
という風に表します。
速度を測るぞ~
いまさら100*100に耐えられない仕様は論外なので
F_sizeは100で計測します。
じゃん。
調査終了 0.1411133
更新終了 0.21875
ってこれだけじゃよくわからないですね。
先ほどのVer7と比較してみると
Ver7 | Ver8 |
---|---|
調査終了0.046875 | 調査終了 0.1411133 |
更新終了0.328125 | 更新終了 0.21875 |
んー。これは。。
更新速度は速くなりましたが
調査速度が遅くなりました。
トータルではいい勝負?
ちなみにf_sizeを150にしてみると。
Ver7 | Ver8_1 |
---|---|
調査終了0.078125 | 調査終了0.3276367 |
更新終了0.722168 | 更新終了0.4853516 |
んー。
両者のいいところ悪いところがはっきり出ていますね。
これは正式にはバージョンアップできないなぁ。
- まとめ
Ver7はVer6の意思を引き継がない形となってしまいました。
sheetの中身を配列に移すにはVariant型でないといけないらしいんですよね。
Ver8はうまいこといかなかったー
かといって悪いこともない。
Ver8_1としておきますか。
Ver7もVer8_1もいいところと悪いところがそれぞれあり
これらのいい点を統合出来たらバージョンアップということにしましょう。
ただちょっとやり方が思いつかないので
今回のライフゲームのコーナーはここまでにしましょうか。
当初の100*100はクリアしたしねっ