メルマガ:あゆしゃのC言語プログラミング
タイトル:あゆしゃのC言語プログラミング(Vol.530) 2次元配列の行を代入・削除  2005/01/19


/*========================================================*/
    <<<あゆしゃのC言語プログラミング>>>
/*========================================================*/
 第530回 2次元配列の行を代入・削除
 発行    2005年1月21日(水曜日)
 発行数   約2600

{magclick}
/*========================================================*/
 はじめに ( 決り文句 )
/*========================================================*/
・このメールマガジンは、主にまぐまぐさんから発行しています。
・ジャンルは、マルチメディアのプログラム、C言語です。
・横60文字で作成し、インデントは大抵半角スペース4つです。
・ここで扱うプログラムは、C言語と半光年以内のものです。
・登録解除は、メルマガのホームページでお願いします。
・過去ログはバックナンバー(下欄参照)を活用して下さい。
・内容は私が感じたもので、最新の技術も、へたれもあります。
・わかりやすさを優先させる為、たまに嘘があるかもしれません。
・セキュリティ突破のため、暗号化された単語があります。

/*========================================================*/
 ご挨拶
/*========================================================*/

 こんにちは。あゆしゃです。

 現在、暇があるとGIBSを作っています。

 以前紹介した状態遷移図についてデバッグを進めているのです。

 ユニットの移動やマップの制圧が完成し、ファーストコンタクト
(両軍のユニットが始めて接触し戦闘を行う)のデバッグ中です。

★とんでもない動きをしたりして、少し面白いのですが、

 ブレークポイントやステップ実行が使えないので、少々苦戦して
います。

 変数の書き間違えなども良くやるので、Perlの文法チェックを
やってくれるツールでもないものかと思いましたが、良くわかりま
せんでした。

{magclick}
/*========================================================*/
 今回のお題  << 2次元配列の行を代入・削除 >>
/*========================================================*/

 それを踏まえて今回は、Perlのお話です。

 GIBSのシステム上、ターン終了処理の1回のアクセスで、最大
1000ユニットを処理しなければなりません。

 これは100ユニット*5ラウンド*2プレイヤーという計算
ですが、原作は200ユニットなので、所要時間に余裕があれば
2000ユニットを処理したいところです。

 そこで、Perlでポインタを使用する技をいろいろと考えて
きました。

 今回、また新しい技に気がつきました。

# 2次元配列の初期化
@data = ([]);

# 2次元配列の0行目のポインタを取得
*pd0 = $data;

# 2次元配列の0行目の5列目に代入
$pd0[ 5 ] = 2;

 こういうポインタの使い方を、前回までに紹介しました。

 今回、困ったのは、破壊されたユニットの情報を消す処理と、
マップにいるユニットをカウントする処理です。

/*========================================================*/

 ユニットが破壊された場合、そのユニットの情報を持つ行を
1行削除します。

 この1行削除を、ループをはってちまちまと””を代入して
いては、日が暮れます。

 そこで、

@data[ 35 ] = ();

 みたいな処理ができないものかと、いろいろ工夫していました。

 これをそのまま実行させると死ぬのですが、以下のようにすると
思惑通りに動きました。

@{ $data[ 35 ] } = ();

 これで data の35行目をすべて消しています。

 @{}については、2次元配列のファイル入出力処理で紹介した
ポインタから配列へキャストする方法です。

 そして配列に対して空の配列()を代入することにより、行が
ばっさりと消える、というスンポーです。

/*========================================================*/

 もう1つ困ったのが、ユニットのカウントです。

 ジャブローに5ユニットいるという場合、各ユニットの処理で
ジャブローのユニット数にあたる変数をインクリメントすればOK
です。

 しかし。
 そのユニット数は、1ラウンド分のユニット数でなければ
なりません。

 さらに。
 ラウンドごとの処理で、前のラウンドのユニット数を使用したい
のです、制圧や撤退の条件として。

 前のラウンドのユニット数は保持しつつ、今回のラウンドの
ユニット数を0からカウントするには、バッファを2種類持つほか
ありません。

 でも。
 ラウンドの終了時に、前回のユニット数を消し、今回のユニット
数を反映しなければなりませんが、これをループをはってちまちま
とやっていては、日が暮れます。

 ここで行コピーを使いたいのです。

 しかし行コピーを行う方法を知りませんでした。

 しかも敵は2次元配列です。良くわかりませんでした。

 そこで、ユニット削除です。

@{ $data[ 35 ] } = ();

 これと同じことをしようと考えました。つまり、

# ラウンドの最初にカウンタ(バッファ)をゼロクリア
@num = ([]);
# ユニットループ
for( $i = 1; $i <= 100; $i++ ) {
    # 勢力ループ
    foreach $now_side ( $e_side, $side ) {
        # ポインタを取得
        *data = $now_side == $side ? *fd_data : *fd_e_data;
        *udd = $data[ $fi_data_unitdata_top + $i ];
        # 現在の勢力・マップのユニット数をインクリメント
        $mapno = $udd[ $fi_data_unitdata_map ];
        $num[ $now_side ][ $mapno ]++ if( $mapno );
    }
}
# 今回カウントした内容をメインデータに反映
@{ $data[ 5 ] } = @{ $num[ $side ] };        # 自分用自分分
@{ $data[ 6 ] } = @{ $num[ $e_side ] };      # 自分用相手分
@{ $e_data[ 5 ] } = @{ $num[ $e_side ] };    # 相手用相手分
@{ $e_data[ 6 ] } = @{ $num[ $side ] };      # 相手用自分分

 という感じでカウンタ処理を組みました。

 2次元配列の1行から2次元配列の1行へコピーしています。

 ギgレrンの野望に登場するマップの数は78です。

 78のループをまわすより、行コピーのほうが早い(かなぁ?)
ということに加えて、この方が気持ちがいいです。

/*========================================================*/

 現在、通常の画面処理が150msであり、16ユニットが存在
する状態でのターン終了時が200msです。

 つまり、16ユニット*5*2を処理するのに、約50ms
かかっています。

 これはデスクトップ上のアパッチ(デバッグソフト)の処理速度
であり、実際のサーバは5倍〜10倍ぐらい早いです。

 このmsという単位は、ミリ秒ですが、SOLDOUT で表示される
CPUs と同じようなものです。

 SOGの画面の CPUs が約 0.1 CPUs ですので、100msほど
かかっている、ということになります。

 負荷が大きいとサーバを追い出されてしまいますが、300ミリ
秒ぐらいまでなら、大丈夫かと思っています。

 本当でしょうか?

{magclick}
/*========================================================*/
 さいごに
/*========================================================*/

 自分で作るとしても、派手なものは製作に時間がかかるので
ちょっといやです。

 しかし、変数のチェックだけなら、簡単なツールとして作成
できるかもしれません。

{magclick}
/*========================================================*/
 次回予告
/*========================================================*/

 次回は1月21日(金曜日)に、第531回をお送りします。
 お題は「GIBS 0.5 先行試作版」

 現状、どのようになっているのか、少し公開してみましょう。

 ただし、ユーザの新規登録処理が動かないようにしておきます。

 お楽しみに!

/*========================================================*/
 最後の決り文句
/*========================================================*/
 このメールマガジンは、まぐまぐさんから発行しています。
 このメールマガジンを解除したい場合は、まぐまぐさんをご利用
ください。このメルマガのまぐまぐアイディーは最後にあります。
 このメールマガジンには広告が挿入されていますか?
 このメールマガジンの内容に文面の引用はありませんか?
 めーらっくすの場合はめーらっくすの利用方に従ってください。
 このメールマガジンの内容の、転用、流用、宣伝、リンク、
少しだけよ? なんて大歓迎です。

{magclick}
/*========================================================*/
 
/*========================================================*/

発行者 あゆしゃ

ホームページ::あゆしゃの世界
http://ayusya.hp.infoseek.co.jp/

ご意見・ご感想・ご質問メール
mailto:ayusya@flamenco.plala.or.jp

まぐまぐ::アイディー
0000020674

まぐまぐ::登録と解除
http://www.mag2.com/m/0000020674.htm

まぐまぐ::バックナンバー
http://jazz.tegami.com/backnumber/frame.cgi?id=0000020674

めーらっくす::アイディー
MM3E1AEE285AB4F

めーらっくす::登録と解除
http://www.mailux.com/mm_dsp.php?mm_id=MM3E1AEE285AB4F 

めーらっくす::バックナンバー★最近のものならこちらが便利★
http://www.mailux.com/mm_bno_list.php?mm_id=MM3E1AEE285AB4F

ブラウザの閉じるボタンで閉じてください。