C言語何でも質問掲示板


アンケートにご協力下さい → >> アンケートフォーム <<

規約と使い方

 
   メモリって   
     ・[14787] バグ 
     ・[14788] ぜt 
     ・[14789] 管理人 
     ・[14793] tkmakwins15 
     ・[14795] 雷 
     ・[14797] ぜt 
     ・[14799] tkmakwins15 
   STGのボスの考え方につ ....   
     ・[14735] バグ 
     ・[14736] 管理人 
     ・[14738] 管理人 
     ・[14739] nayo 
     ・[14742] 管理人 
     ・[14744] バグ 
     ・[14759] nayo 
     ・[14765] nayo 
     ・[14766] 管理人 
     ・[14783] nayo 
   線と線の当たり判定   
     ・[14778] GPGA 
     ・[14779] 雷 
     ・[14782] Justy 
   多重配列での値の取り ....   
     ・[14768] 管理人 
     ・[14769] やそ 
     ・[14770] box 
     ・[14771] やそ 
     ・[14775] バグ 
   画像を動かす   
     ・[14752] 管理人 
     ・[14754] kazuoni 
     ・[14755] やそ 
     ・[14757] kazuoni 
     ・[14758] 管理人 
     ・[14762] やそ 
     ・[14763] 管理人 
   VC6.0++なんですが、サ ....   
     ・[14748] 管理人 
     ・[14750] バグ 
     ・[14756] アニエス 
   微妙な位置にいるとき   
     ・[14723] 管理人 
     ・[14724] 管理人 
     ・[14728] nya 
     ・[14731] 管理人 
     ・[14740] nya 
     ・[14743] 管理人 
     ・[14747] nya 
     ・[14749] 管理人 
   コマンドラインから入 ....   
     ・[14589] box 
     ・[14590] ぽん 
     ・[14592] box 
     ・[14593] ぽん 
     ・[14594] 組木紙織 
     ・[14646] ぽん 
     ・[14649] box 
     ・[14703] ぽん 
     ・[14704] フリオ 
     ・[14705] やそ 
     ・[14741] ぽん 
   配列のオーバーフロー ....   
     ・[14687] 管理人 
     ・[14688] 管理人 
     ・[14690] 管理人 
     ・[14693] GPGA 
     ・[14695] たかぎ 
     ・[14715] GPGA 
     ・[14730] たかぎ 
   ぷよぷよ   
     ・[14676] 管理人 
     ・[14696] バグ 
     ・[14697] 管理人 
     ・[14698] バグ 
     ・[14700] 管理人 
     ・[14706] バグ 
     ・[14708] 管理人 
   AA動画について。   
     ・[14692] 管理人 
   無題   
     ・[14670] box 
     ・[14671] taro 
     ・[14672] やそ 
     ・[14673] 管理人 
     ・[14675] taro 
     ・[14677] 管理人 
     ・[14678] 管理人 
     ・[14679] taro 
     ・[14681] 通りすがり 
     ・[14682] taro 
   教えていただきたいで ....   
     ・[14668] やそ 
     ・[14680] 管理人 
   visual c++ express 2 ....   
     ・[14662] やそ 
     ・[14663] 管理人 
   クラスのデータ共有   
     ・[14639] 組木紙織 
     ・[14650] Nikol 
     ・[14651] バグ 
   VisualC++ 入力候補表 ....   
   無題   
     ・[14644] 管理人 
   マルチスレッドクラス   
     ・[13860] たかぎ 
     ・[13861] たかぎ 
     ・[13862] たかぎ 
     ・[13936] 組木紙織 
     ・[13943] Justy 
     ・[13950] たかぎ 
     ・[14034] 組木紙織 
     ・[14037] Justy 
     ・[14167] 組木紙織 
     ・[14173] Justy 
     ・[14190] 組木紙織 
     ・[14199] Justy 
     ・[14202] 組木紙織 
     ・[14241] Justy 
     ・[14291] 組木紙織 
     ・[14304] Justy 
     ・[14502] 組木紙織 
     ・[14504] Justy 
     ・[14510] 組木紙織 
     ・[14511] Justy 
     ・[14512] Justy 
     ・[14519] 組木紙織 
     ・[14521] たかぎ 
     ・[14524] Justy 
     ・[14632] 組木紙織 
     ・[14633] Justy 
     ・[14637] 組木紙織 
     ・[14641] Justy 
   二つの配列の合併につ ....   
     ・[14622] box 
     ・[14624] 組木紙織 
     ・[14625] しょう 
     ・[14626] box 
     ・[14627] しょう 
     ・[14628] 組木紙織 
     ・[14629] しょ 
   Rainboard   
     ・[14620] ナメ 
   ポインタについて質問   
     ・[14597] 組木紙織 
     ・[14619] 管理人 
   iostreamとwchar_t   
     ・[14615] tkmakwins15 
     ・[14616] Blue 
     ・[14617] たかぎ 
     ・[14618] tkmakwins15 
   超初歩的な質問なので ....   
     ・[14610] たかぎ 
     ・[14611] Justy 
     ・[14612] ステル 
     ・[14613] ステル 
   BCCを使っているのです ....   
     ・[14602] box 
     ・[14603] 特に 
     ・[14604] Justy 
     ・[14605] 特に 
     ・[14606] Justy 
     ・[14607] 特に 
     ・[14608] Justy 
   回転処理と削除アニメ ....   
     ・[14580] シュバ 
     ・[14587] バグ 
     ・[14591] バグ 
     ・[14595] シュバ 
     ・[14599] バグ 
     ・[14601] シュバ 
   ゲームの終了のさせか ....   
     ・[14583] 管理人 
     ・[14598] tkmakwins15 
   ヘッダでのマクロの定 ....   
     ・[14586] GPGA 
     ・[14588] kz 
   ご教授下さい><   
     ・[14581] てむてむ 
   雑談版   
     ・[14471] クロカモ 
     ・[14474] 雷 
     ・[14506] 管理人 
     ・[14509] tkmakwins15 
     ・[14518] 管理人 
     ・[14522] 組木紙織 
     ・[14523] tkmakwins15 
     ・[14525] 管理人 
     ・[14526] tkmakwins15 
     ・[14527] 雷 
     ・[14536] tkmakwins15 
     ・[14537] 管理人 
     ・[14545] クロカモ 
     ・[14575] tkmakwins15 
     ・[14578] kura 
   オリジナルのパズルゲ ....   
     ・[14563] 組木紙織 
     ・[14564] バグ 
     ・[14576] 赤羽 
   グローバル変数を巧い ....   
     ・[14544] バグ 
     ・[14546] tny 
     ・[14549] GPGA 
     ・[14550] たかぎ 
     ・[14551] バグ 
     ・[14552] たかぎ 
     ・[14553] GPGA 
     ・[14554] tny 
     ・[14556] たかぎ 
     ・[14558] tny 
     ・[14559] 管理人 
     ・[14561] tny 
     ・[14572] たかぎ 
     ・[14573] たかぎ 
     ・[14574] tny 
   音楽関数について   
     ・[14560] 管理人 
     ・[14566] 木霊 
     ・[14567] 木霊 
     ・[14570] 管理人 
     ・[14571] パソピ 
   敵?   
     ・[14569] 管理人 
   テンプレート関数につ ....   
     ・[14532] Justy 
     ・[14533] はね 
     ・[14534] Justy 
     ・[14535] GPGA 
     ・[14541] はね 
     ・[14547] GPGA 
     ・[14555] Justy 
     ・[14562] はね 
     ・[14568] GPGA 
   教えてください   
     ・[14540] やそ 
     ・[14542] バグ 
     ・[14548] Gantetsu 
   プロセスの優先度とfp ....   
     ・[14529] へろり 
     ・[14530] nullぽ 
   mallocなどを使わずに ....   
     ・[14514] box 
     ・[14515] tkmakwins15 
     ・[14516] box 
     ・[14517] 黒猫 
   なぜか重い壁┃oT)    
     ・[13918] やそ 
     ・[13920] ф魔理沙ф 
     ・[13928] 管理人 
     ・[13931] やそ 
     ・[13932] 管理人 
     ・[13947] ф魔理沙ф 
     ・[13949] 管理人 
     ・[13958] tkmakwins15 
     ・[14018] ф魔理沙ф 
     ・[14026] 管理人 
     ・[14086] クロカモ 
     ・[14106] 管理人 
     ・[14328] ф魔理沙ф 
     ・[14501] ギョピ 
     ・[14505] 管理人 
     ・[14507] ギョピ 
     ・[14508] tkmakwins15 
   無題   
     ・[14469] 管理人 
     ・[14472] ちょこ 
     ・[14475] 雷 
     ・[14503] 木霊 
   メンバ変数に配列を格 ....   
     ・[14497] GPGA 
     ・[14498] ゆも 
     ・[14499] GPGA 
     ・[14500] ゆも 
   c++のmap宣言にて。   
     ・[14484] たかぎ 
     ・[14486] みらの 
     ・[14487] バグ 
     ・[14490] 組木紙織 
     ・[14494] GPGA 
     ・[14495] たかぎ 
   小数の桁数を指定した ....   
     ・[14481] 組木紙織 
     ・[14482] たかぎ 
     ・[14485] たかぎ 
     ・[14488] たか 
     ・[14489] 組木紙織 
     ・[14491] バグ 
     ・[14492] たか 
     ・[14493] バグ 

Name: ぜt  ..かけだし(1,272ポイント)   Date: 2008/03/07(金) 21:42   No:14784       
Title: メモリって    
メモリ2ギガっていいほう?


2倍のポイントを手に入れた! 20ポイント を手に入れた。


Name: バグ  ..比類無きプログラマー(78,268ポイント)   Date: 2008/03/07(金) 22:29   No:14787     
Title: Re:メモリって    
環境にもよると思いますが、Windowsを動かすだけならば充分過ぎでしょう。

19ポイント を手に入れた。

Name: ぜt  ..かけだし(1,310ポイント)   Date: 2008/03/07(金) 22:32   No:14788     
Title: Re:メモリって    
なら4ギガはかなりいいほうなの?

2倍のポイントを手に入れた! 38ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(531,183ポイント)   Date: 2008/03/07(金) 23:07   No:14789     
Title: Re:メモリって    
いい方とか悪い方とかは置いておいて、自分が何をするか、自分が行う範囲で支障がなければ何ギガでもいいのではないでしょうか。

何かの研究をするとか、大規模なシミュレーションをするとかいう必要があるのなら2ギガでも足らない場合があるかもしれませんし、
Meでメモ帳しか使わないよという人なら256でも十分でしょう。

一般的には現在は512M〜1ギガが主流だと思います。
4ギガ積んでいる人はつい最近までは少なかったと思います。
ただココ最近突然メモリの値段が下がったので、自作とか増設とかされる人はもう4Gにしたって人いると思います。
私も4Gにしました。1Gが1980円で売っているので本当に安くなったものです。


175ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(59,189ポイント)   Date: 2008/03/08(土) 09:58   No:14793     
Title: Re:メモリって    
あれっ? 確かVistaでも4GBが限界だと聞いたことがありますが…

15ポイント を手に入れた。

Name:  ..プログラマー(29,005ポイント)   Date: 2008/03/08(土) 12:44   No:14795     
Title: Re:メモリって    
OSの種類で32ビットが3ギガが限界のはず。
64ビット版のが今のところ考えられないくらい多くつむことができる立ったかな?

ただ、対応したソフトが少なすぎるはずだが・・・


43ポイント を手に入れた。

Name: ぜt  ..かけだし(1,321ポイント)   Date: 2008/03/08(土) 13:52   No:14797     
Title: Re:メモリって    
じゃ4ギガはだめってこと?

11ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(59,263ポイント)   Date: 2008/03/08(土) 14:00   No:14799     
Title: Re:メモリって    
32bitマシンだったら大抵ポインタは4byteくらいと思います。という訳で、4GBが限界かと思います。(たぶん大丈夫とは思います)

40ポイント を手に入れた。



Name: nayo  ..ぴよぴよ(877ポイント)   Date: 2008/03/04(火) 21:37   No:14734       
Title: STGのボスの考え方について    
管理人様やここの方たちのお陰でなんとか東方に近いシューティングゲームができ、
今度はステージや敵追加のためデータを外部読み込みにしたりと
プログラムを効率が良いように書き換えているのですが
ちょっと以前のプログラムだとボスの考え方の部分があまりに力技過ぎたので質問させてください

ボスはHPに応じて弾幕が変わるのですがその移行部分を皆さんはどのようにやっているのでしょうか

私はボスのHPを例えば1000とすると1000~800の間は1のパターンなどとやっていました
しかしこれだとHPが800になった瞬間にとあるエフェクトを出したいが弾が複数当たるなどして
スキップされてしまったりなど色々不便で…
またHPの表示もそれぞれの部分で設定してやらねばならず非常にプログラムが効率悪くなってしまいました
HPをそれぞれの弾幕に応じて設定してやればいいのではと思いましたが
ボスを普通の敵と同じ構造体で扱っているためHPが0になると消滅してしまい…w
ボスの出現フラグを2などとしてみるなどすればいいのでしょうが…

と少しわかりにくいかもしれませんがどなたか御願いします


380ポイント を手に入れた。


Name: バグ  ..比類無きプログラマー(78,458ポイント)   Date: 2008/03/04(火) 21:48   No:14735     
Title: Re:STGのボスの考え方について    
シューティングは作った事がないので、適当なことを言うかもしれませんが…

>>しかしこれだとHPが800になった瞬間にとあるエフェクトを出したいが弾が複数当たるなどして
スキップされてしまったりなど色々不便で…

これを解消したいならば、HPが800になった瞬間にボスを無敵状態にしてしまって、エフェクトが終了次第、無敵状態を解除すればいいのではないでしょうか?


5ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,108ポイント)   Date: 2008/03/04(火) 22:10   No:14736     
Title: Re:STGのボスの考え方について    


状態遷移の考え方をすればいいんですよ。

ボスの初期状態を0としましょう。
状態0のままHPは段々減少していきます。
そして今800に差し掛かったとしましょう。

if(状態==0 && boss.hp<800){
  エフェクト発動;
  状態=1;
}

こうすればスキップされません。
さらに400以下になったときにまたエフェクトをかけたければ

if(状態==1 && boss.hp<400){
  エフェクト発動;
  状態=2;
}

こんな感じでしょう。
大ボスが第二形態に変身したりするようなエフェクトなら
バグさんの仰る方法がいいかもしれませんし、
もし東方風にやるなら状態遷移でしょう。

>またHPの表示もそれぞれの部分で設定して
>やらねばならず非常にプログラムが効率悪くなってしまいました

HPの表示を設定するとはどういうことでしょうか?
HPの表示は描画部のボス担当部分でやればいいだけだと思います。

>HPをそれぞれの弾幕に応じて設定してやればいいのではと思いましたが
>ボスを普通の敵と同じ構造体で扱っているためHPが0になると消滅してしまい…w
>ボスの出現フラグを2などとしてみるなどすればいいのでしょうが…

実は私もボスの構造体と雑魚の構造体は同じ物を使っています。
弾の量は違いますが、そこはベクターでどうにでも増えますし。
構造が同じなら同じ関数で処理できるのでこちらの方が楽なんですよね。

私は雑魚が死んだ状態で雑魚が発射した弾がまだ残っている時は2のフラグを
使っているのでボスは10にしました。
まぁその辺どうでもいいですが。
別にフラグが10の時は0になっても規定回数復活するようにすればいいと思いますよ。
 


499ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,476ポイント)   Date: 2008/03/04(火) 22:21   No:14738     
Title: Re:STGのボスの考え方について    
実は状態遷移って裏ワザのキーによく使います。
私が今まで作ったゲームにも公開していないだけで結構そういう裏ワザキーが設定されています。

なぜかと言うとリリースしたゲームそのものでデバッグできるからです^^;
大きな声でいえないので小さな声で言いますが

一応私にしかわからないキーを押せば違う面にとんだり、ボスが一瞬で倒せたり、パワーがマックスになったり0になったりします。
・・と言うのもデバッグ時に設定した機能を消してリリースしたら何かしらそこが影響して何か変ってしまうかもしれないからです。
リリースしたゲームそのものでバグチェックすれば、そこでバグが出なければ少なくともチェックしたバグは出るはずが無いですからw


そこで、例えばゲーム中に「debug」と入力したらデバッグモードになるとします。(龍神録ではなりませんよw)
分りやすく言えば



if (状態==0 && key[KEY_INPUT_D]==2)
状態=1;
else if(状態==1 && key[KEY_INPUT_E]==2)
  状態=2;
else if(状態==2 && key[KEY_INPUT_B]==2)
  状態=3;
else if(状態==3 && key[KEY_INPUT_U]==2)
  状態=4;
else if(状態==4 && key[KEY_INPUT_G]==2)
  状態=5;
else if(他のキー入力があった)
  状態=0;

if(状態==5){
  デバッグモード発動;
  状態=0;
}

こんな感じで状態が5になればデバッグモード発動です。
昔ストツーとかで
上R下LYBXAとかで裏ワザやったと思いますが、そういうのも状態遷移ではないでしょうか。



368ポイント を手に入れた。

Name: nayo  ..ぴよぴよ(969ポイント)   Date: 2008/03/04(火) 22:35   No:14739 解決!     
Title: Re:STGのボスの考え方について    
バグ様、管理人様、素早い御回答ありがとうございます

なるほど、状態遷移ですか
これを参考にやらせていただきます

プログラムって作り直すたびに昔の自分の効率の悪さに苦笑してしまう…w

しかし面白そうな例ですねw
これも参考にさせていただきます


92ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,626ポイント)   Date: 2008/03/05(水) 09:05   No:14742     
Title: Re:STGのボスの考え方について    
状態を作ると必ず初期化ミスが付きまとうので、何か一つの構造体に当てはめておいて、
memsetでいつも初期化することを忘れないようにして下さい。

>プログラムって作り直すたびに昔の自分の効率の悪さに苦笑してしまう…w

普通にみんなそうじゃないですかね^^;
多分昔からプログラムをやってる人や熟練者ではない限り、みんなプログラムを書くこと自体毎日勉強なんだと思いますm(_ _)m


150ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,474ポイント)   Date: 2008/03/05(水) 09:39   No:14744     
Title: Re:STGのボスの考え方について    
いっそのこと、構造体ではなくクラスにしてはいかがでしょうか?
コンストラクタで初期化しておいて、あとは初期化用のメンバ関数を準備しておいたら便利かな?


16ポイント を手に入れた。

Name: nayo  ..ぴよぴよ(993ポイント)   Date: 2008/03/05(水) 18:50   No:14759     
Title: Re:STGのボスの考え方について    
バグ様提案有難うございます
私もグローバル変数が多すぎるのでクラスを利用したいと思っているのですが
中々理解できず苦戦しております…w

ネットや図書館を利用してクラスについて現在学んでいますがこれが中々…


24ポイント を手に入れた。

Name: nayo  ..かけだし(1,644ポイント)   Date: 2008/03/06(木) 21:47   No:14765     
Title: Re:STGのボスの考え方について    
と、もう少しだけ質問させていただいて宜しいでしょうか

ボスの移動についてなのですが

特定座標へ移動するというのなら楽なのですが例えば
特定の周期でランダムな位置(ただしプレイヤーのいるx方向へかつ画面上部維持)、に移動する
といった動きを実現するにはどうすればいいでしょうか
と、ちょっとわかりにくいですね…

今無理やりやっている方法は
	if(enemy[i].counter%180==0){//180カウントに一回移動する角度を決める

if(Player.x-enemy[i].x>0&&enemy[i].y<160&&enemy[i].x<340)
enemy[i].angle=atan2(GetRand(5),GetRand(10));//右下へ移動
if(Player.x-enemy[i].x<0&&enemy[i].y<160&&enemy[i].x>100)
enemy[i].angle=atan2(GetRand(5),-GetRand(10));//左下へ移動
if(Player.x-enemy[i].x>0&&enemy[i].y>160&&enemy[i].x<340)
enemy[i].angle=atan2(-GetRand(5),GetRand(10));//右上へ移動
if(Player.x-enemy[i].x<0&&enemy[i].y>160&&enemy[i].x>100)
enemy[i].angle=atan2(-GetRand(5),-GetRand(10));//左上へ移動
}
if(enemy[i].counter%180<60){//180カウントの内、60カウント間移動
enemy[i].x+=3.0f*cos(enemy[i].angle);
enemy[i].y+=3.0f*sin(enemy[i].angle);
}

といった感じなのですが
問題としては一定速度では移動しない、無駄が多い?でしょうか…
ブレーキをかけるようにストップするのはこれだと楽なのですが…


651ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,972ポイント)   Date: 2008/03/07(金) 00:00   No:14766     
Title: Re:STGのボスの考え方について    
enemy構造体に「目標到達地点」なる変数を設定し、そこに向かって移動させたらいいのではないでしょうか?

そうしたら決まった範囲内を移動させるのも楽ではないでしょうか。

10,10 ~ 300,100の座標内を移動させたければすぐそう出来ますし。


2倍のポイントを手に入れた! 184ポイント を手に入れた。

Name: nayo  ..かけだし(1,770ポイント)   Date: 2008/03/07(金) 21:20   No:14783 解決!     
Title: Re:STGのボスの考え方について    
お返事遅くなってしまい申し訳ないです

管理人様のおっしゃったようにやって上手くいきました
移動させたい座標と敵番号を送って移動してやる関数を別に作ってやると便利でした

お忙しいところ有難うございました


2倍のポイントを手に入れた! 126ポイント を手に入れた。



Name: rarara  ..ぴよぴよ(127ポイント)   Date: 2008/03/07(金) 18:13   No:14777       
Title: 線と線の当たり判定    
はじめまして。
早速質問なのですが、
線と線の当たり判定はどのようにすればいいのでしょうか?
四角形同士の判定ならサイトにあるとおりに出来るのですが・・・
自分で調べてみると、一応、線同士の当たり判定を書いているサイトはあったのですが、
線の交点まで求めるものばかりで、ソースが長く、処理が重いものばかりでした。
アクションゲームで使いたいので、交点の座標は必要なく当たっているかいないかだけわかればいいのですが、
どのようにすればいいでしょうか?


127ポイント を手に入れた。


Name: GPGA  ..熟練のプログラマー(43,195ポイント)   Date: 2008/03/07(金) 18:26   No:14778     
Title: Re:線と線の当たり判定    
ここのサイトの判定ではだめですか?


55ポイント を手に入れた。

Name:  ..プログラマー(28,962ポイント)   Date: 2008/03/07(金) 18:32   No:14779     
Title: Re:線と線の当たり判定    
線を座標で処理してはどうでしょうか?
線は点の連続描画であるので、全て点で管理してしまえば当たり判定も楽ではないかと思います。
アクションゲームであるとの事なので、1ドットではなく、多少大きいかと思いますので…

現在判別する座標と、各線を構成する点が同じでないかどうかというのではどうでしょうか?
画像使用であれば、
始点のときは、画像1(片方が切れているやつ
終点のときは、画像2(上に同じ
始点フラグON&終点フラグOFFの時、画像3(両方が切れているやつ

これで対処できないでしょうか?
試したことがないので、ただの考えですが・・・

交差の判定は、動いた直線の始点を検査座標にして、他の線の座標とかぶっていないかどうか調べる
関数に座標と調べたい直線も渡す。
内部で、x座標が等しいか調べ、等しいならy座標も調べる。

あんまり早い処理じゃない気がしますが…参考になりますか????


18ポイント を手に入れた。

Name: Justy  ..ハッカー(178,634ポイント)   Date: 2008/03/07(金) 21:08   No:14782     
Title: Re:線と線の当たり判定    
>線と線の当たり判定はどのようにすればいいのでしょうか?
 どのサイトを見たのかはわかりませんが、多分その参考にしたサイトに
あるとおりの判定だと思います。

 ただ、高速化の方法はいろいろあると思いますよ。
 たとえば、各「線分の中心から、線分の端点を通過する円」同士の
交差判定を先に行い、交差しないので有れば線も交差しないのでスキップし、
円が交差しているようなら、線分も交差している可能性があるとして、
ちゃんと計算して調べる、とか。

 円じゃなくても線分の端と端を対角線とするボックス同士をチェックしてから
でもいいですね。


>処理が重いものばかりでした
 実際にそんなに重かったですか?


202ポイント を落としてしまった。



Name: 初心者  ..初心者(7,172ポイント)   Date: 2008/03/07(金) 08:18   No:14767       
Title: 多重配列での値の取り方    
0か1を記憶でいるBOOL型で10×10の多重配列 bool Data[10][10]; をつくります。

この変数の中に一定時間ごとにランダムであたいが入ります。

この中から連続した縦横3×3マスが1だったらというフラグを立てる処理を考えているのですが、

思いつきません・・・

{0,0,0,0,0, 1,1,1,0,0}, //
{0,0,0,0,0, 1,1,1,0,0}, //
{0,0,0,0,0, 1,1,1,0,0}, //
{0,0,0,0,0, 0,0,0,0,0},
{0,0,0,0,0, 0,0,0,0,0},



みたいなかんじです。

考えて見たのは
void CheckTask(void)
{
int x,y;

for(x=0;x<CEL_MAX_W;x++){
for(y=0;y<CEL_MAX_H;y++){
if(GameData[y][x] != 0 && Block[0][GameData[y][x]].Ptn == 1){
CheckTbl(x,y); //9マスの左上を取って関数に送る
}
}
}
}

void CheckTbl(int sx,int sy)
{
short CcheckTbl[3][3];
short Ccount;
int x,y;
bool CFlg;

Ccount=0;

CFlg=false;

for(x=0;x<3;x++){
for(y=0;y<3;y++){
CcheckTbl[y][x] = Block[0][GameData[sy+y][sx+x]].Ptn; //左上から順番に仮テーブルに代入
}
}

for(x=0;x<3;x++){
for(y=0;y<3;y++){
if(CcheckTbl[y][x] == 1)
Ccount+=1; //仮テーブルの1の数を数える
}
}

if(Ccount>=9) CFlg = true;
}

ってかんじです・・・
C++始めたばかりでわかりませんw
どなたかご教授お願いできないでしょうか?


463ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(531,008ポイント)   Date: 2008/03/07(金) 09:14   No:14768     
Title: Re:多重配列での値の取り方    
ざっとしか見てないのですが、
3x3を全部掛け算して0なら、1ならでフラグをわけたらいいだけではないでしょうか??


36ポイント を手に入れた。

Name: やそ  ..プログラマー(26,153ポイント)   Date: 2008/03/07(金) 09:56   No:14769     
Title: Re:多重配列での値の取り方    
10×10の配列の連続した3×3マスが1ならCFlgをTrueにする
と言うことなら・・・

int main(){
int Data[10][10]; 
int x,y,x2,y2,csum;
bool CFlg;
/* x=たて y=よこ */

/* 配列初期化 */
for(x=0;x<10;x++){
for(y=0;y<10;y++){
Data[x][y]=0;
}
}

for(x=0;x<8;x++){
for(y=0;y<8;y++){
/* チェックの基点となる座標をチェック */
if(Data[x][y]==1){
csum=0;
/* 3×3マスを集計する */
for(x2=x;x2<x+2;x2++){
for(y2=y;y2<y+2;y2++){
csum *= Data[x2][y2];
}
}
/* 集計結果=1 ・・・3×3マス全てが1 */
if(csum==1){
CFlg=True;
}
}
}
}
}

でどうでしょうか?

配列の型をintにしたのは・・・特に意味は無いです(笑)
ポイントは「連続した」3×3マスなのでチェックの起点を8までしかとっていないとこでしょうか。
これで、無駄なループ回数を減らせます^^


314ポイント を手に入れた。

Name: box  ..ハッカー(108,047ポイント)   Date: 2008/03/07(金) 11:21   No:14770     
Title: Re:多重配列での値の取り方    
>やそさん

csumの初期値がゼロなのはまずいでしょうね。
ゼロに何を掛けてもゼロのままです。


11ポイント を手に入れた。

Name: やそ  ..プログラマー(26,300ポイント)   Date: 2008/03/07(金) 11:40   No:14771     
Title: Re:多重配列での値の取り方    
boxさん、素敵な指摘ありがとさんです^^

最初、3×3のマスを「足し算」で集計させていたのですが、管理人さんの「掛け算」投稿を先に投下されてしまったので、急遽変更を加えたのですが、初期化部分を忘れてましたね(恥)


if(Data[x][y]==1){
csum=1;

  ・
  ・

もしくは


if(Data[x][y]==1){
csum=Data[x][y];

ですね^^;


147ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,249ポイント)   Date: 2008/03/07(金) 12:20   No:14775     
Title: Re:多重配列での値の取り方    
こんなのはどうでしょう?分かりやすさ重視です(笑)


void CheckTable(bool pResult[TABLE_WIDTH][TABLE_HEIGHT], bool pTable[TABLE_WIDTH][TABLE_HEIGHT], int iPosX, int iPosY)
{
for (int x = iPosX; x < iPosX + 3; x++)
{
for (int y = iPosY; y < iPosY + 3; y++)
{
// 配列の領域外が指定された場合は、それ以上の処理は無駄なので何もしない
if (x < 0 || x >= TABLE_WIDTH ||
y < 0 || y >= TABLE_HEIGHT)
return;

// 検査箇所の内、1箇所でもfalseが見つかった場合は、それ以上の処理は無駄なので何もしない
if (pTable[x][y] == false)
return;
}
}

// 3×3マスが全てtrueだったので、バッファの3×3マスにtrueを代入する
for (int x = iPosX; x < iPosX + 3; x++)
for (int y = iPosY; y < iPosY + 3; y++)
pResult[x][y] = true;
}


266ポイント を落としてしまった。



Name: kazuoni  ..かけだし(1,006ポイント)   Date: 2008/03/05(水) 13:48   No:14751       
Title: 画像を動かす    
お久しぶりです。春休みになって、情報系に進んだんで、ゲームを作ってみようと意気込んで、何からやっていいかわからなかったので、
http://dixq.net/g/#0
を一からやっているものです。
↑の12番の「画像を動かす」まで進んだのですが、サンプルコードをコピーして実行すると、数秒間なにも表示されない状態が続き、最後に画像が真ん中ぐらいの場所に表示されるだけなんです。本当は動いているように見えないと成功じゃないんですよね?どうしたらよいでしょうか?
ちなみに、裏画面処理の方はうまくいきました。osはvistaで、visual c++ 2008 express editionを使用しています。
よろしくお願いします。


170ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(530,586ポイント)   Date: 2008/03/05(水) 14:21   No:14752     
Title: Re:画像を動かす    
こんにちは。
私もVistaを使っていて、同じ状態になったことがあります。
何故かしばらく表示されないんですよね。

それ以来私はVistaをやめてXPを使っているのでよくわからないのですが、
一度ランタイムを入れてみて下さい。
http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=2da43d38-db71-4c1b-bc6a-9b6652cd92a3


それでも解決しない場合は
使用しているDXライブラリが最新バージョンである事を確認の上、本家できいてみて下さい。


22ポイント を手に入れた。

Name: kazuoni  ..かけだし(1,117ポイント)   Date: 2008/03/05(水) 15:03   No:14754     
Title: Re:画像を動かす    
やはりだめでした。本家で聞いてみることにします。
あと、このまま質問続けてしまうのですが・・・
23. 行けない所を作る。〜1D〜
で、「横幅は480ピクセルありますから、32で割ると、20個の区間があります。」とありますが、どういう計算をして20個と出たのでしょうか?


111ポイント を手に入れた。

Name: やそ  ..プログラマー(25,369ポイント)   Date: 2008/03/05(水) 15:16   No:14755     
Title: Re:画像を動かす    
>「横幅は480ピクセルありますから、32で割ると、20個の区間があります。」

 そこは突っ込んじゃいけないところです(>_<)

横幅は640じゃないかな??


77ポイント を手に入れた。

Name: kazuoni  ..かけだし(1,229ポイント)   Date: 2008/03/05(水) 15:30   No:14757 解決!     
Title: Re:画像を動かす    
すみません。プログラミングの勉強の前に空気を読む勉強をしたいと思います。
ご回答ありがとうございました。


2倍のポイントを手に入れた! 112ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,598ポイント)   Date: 2008/03/05(水) 16:59   No:14758     
Title: Re:画像を動かす    
いやいや、やそさんのは、ただの冗談ですよ^^;

ご指摘ありがとうございます、修正しますね。


12ポイント を手に入れた。

Name: やそ  ..プログラマー(25,839ポイント)   Date: 2008/03/06(木) 13:06   No:14762     
Title: Re:画像を動かす    
うーむ、冗談も使い方に気をつけないと、こっちこそ空気読め!って突っ込まれそうです(笑)
ここのサイトのように講座や掲示板で親切に教えてくれるサイトは貴重ですね。
ただ、ミスの指摘って非常に難しいんですよね^^;

間違いのように見えても実は後でそれが活きてくるようなことも有ったり無かったり^^
まあ、今回の横幅に関しては明らかな書き間違いですから安心して指摘してあげましょう(笑)
人のプログラムを見て粗捜しが出来るというのは成長(上達)の証です^^

「シューティングゲームの館」についてはそのうち刷新されると思います。
そのまえにミスを見つけまくって、管理人さんをつつき回して遊んであげるといいんじゃないかな(笑)





2倍のポイントを手に入れた! 470ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,788ポイント)   Date: 2008/03/06(木) 13:22   No:14763     
Title: Re:画像を動かす    
>そのまえにミスを見つけまくって、管理人さんをつつき回して遊んであげるといいんじゃないかな(笑)

タダでさえプロのゲームプログラマーの先生方々が沢山いらっしゃるこのサイトでこんな青二才プログラマーがコード公開するだけでも
恥ずかしいのに、つつき倒したら起き上がれなくなりますよw


80ポイント を手に入れた。



Name: アニエス  ..ぴよぴよ(38ポイント)   Date: 2008/03/05(水) 12:09   No:14746       
Title: VC6.0++なんですが、サンプルが動きません    
よろしくお願いします。

この度、VC6.0++ SP6 が手に入ったので
少しプログラミングをしようと頑張ってみようかと思いこのページに辿り着きました。

DXライブラリをダウンロードして
「サンプルプログラム実行用フォルダ」を開き
"DxLib.sln"を実行すると
[選択されたファイルは Visual Studioのソリューションファイルではありません]
と警告が出てしまいます。

サンプルというか入門編以降はVC6.0++では動作しないのでしょうか?
動かない場合はどのように進めていけばよろしいでしょうか?

こちらと書かれたページから飛んで以下の設定を行いサンプルは動作しました。
ttp://homepage2.nifty.com/natupaji/DxLib/dxuse_vc6.html

本当に初歩的で申し訳ありませんがよろしくお願いします。


38ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(530,504ポイント)   Date: 2008/03/05(水) 12:25   No:14748     
Title: Re:VC6.0++なんですが、サンプルが動きません    
DxLib.dsw

こちらじゃないでしょうか?


24ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,515ポイント)   Date: 2008/03/05(水) 12:27   No:14750     
Title: Re:VC6.0++なんですが、サンプルが動きません    
どうでも良い事ですが、VisualC++6.0ですから…

×VC6.0++

○VC++6.0

ですよ。


41ポイント を手に入れた。

Name: アニエス  ..ぴよぴよ(83ポイント)   Date: 2008/03/05(水) 15:27   No:14756 解決!     
Title: Re:VC6.0++なんですが、サンプルが動きません    
> DxLib.dsw
>
> こちらじゃないでしょうか?

管理人様。
ありがとうございました。

DxLib.slnではなかったんですね。
無事に動かす事ができました。

> どうでも良い事ですが、VisualC++6.0ですから…

バグ様。
ご指摘ありがとうございました。

VC++6.0ですね。
覚えました。

これからコツコツやっていこうと思います。
また何かあったらよろしくお願いします。





45ポイント を手に入れた。



Name: nya  ..ぴよぴよ(145ポイント)   Date: 2008/03/04(火) 15:46   No:14712       
Title: 微妙な位置にいるとき    
はじめまして。(と言っても私の方は友人の紹介で数年間見てました。)

ここの掲示板とかゲームの作り方のページとか見て、私もゲーム作りたいって事で、
初心者ですけどDXライブラリで作っているところです。

で、ボ○バーマンのパロディ(笑)を作ってるのですが、
キャラクタが通れる所とブロックの微妙な位置に立ってる時、
自 <こんな具合
 ■
ずれて動いてくれるようにするには、どんなプログラムを書くべきでしょうか…
(上の場合、↓を入力するとちょっと左にずれてくれる、みたいな。)
キャラの座標を小数で設定すると、色々と変なことになってしまうのです…


145ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(528,998ポイント)   Date: 2008/03/04(火) 17:17   No:14723     
Title: Re:微妙な位置にいるとき    
初めまして。

お〜まさに私と同じ所でつまずいていらっしゃいますね(笑
私もボンバーマンは作ったのですが、そこで苦労しました。

座標がちょうど32で割れる時だけしか十字方向に進めないシステムではものすごく操作性が悪いので、
中間でもスムーズに動かないといけないんですよね。

まぁ単純に考えられるのが、画像のような中途半端な位置で上ボタンを押した時、上には行かず、
現在の位置から近い左右どちらかの方に進ませる方法ですよね。

フィーリングとしてこんな感じですかね?
(1区間が32ピクセルだと仮定します)


if(上方向が押されている){
if(xが32で割り切れない位置){
if(座標%32>=16)
右に進ませる;
else
左に進ませる;
}
else{
上に進ませる;
}
}

 
ただこれではカクカク動いて美しくないので、カドッコに来たら曲線を描くようにしました。
ややこしいんで、最初はやらない方がいいと思います^^;


310ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(529,023ポイント)   Date: 2008/03/04(火) 17:20   No:14724     
Title: Re:微妙な位置にいるとき    
なお、曲線にしなくても、こんな風に軌跡を描かせても見た目随分滑らかに動いているように見えました。
というか、むしろ見た目これと全く違いがわかりません。
もし上の方法ではあまりにカクカクしすぎると思ったときはこちらで実装してみてはいかがでしょうか。

もうご覧になったかもしれませんが、実装したらこんな感じになりました。


25ポイント を手に入れた。

Name: nya  ..ぴよぴよ(328ポイント)   Date: 2008/03/04(火) 19:02   No:14728     
Title: Re:微妙な位置にいるとき    
おぉ、早速ありがとうございます。

実は、管理人さんの作られたボンバーマンもちゃっかり持ってます。全クリしましたw

それで、実はそんな感じのプログラムを組んでるんですが、
キャラクタのスピードを設定するのに、

if(下が押された){

if(左下が壁){
(キャラのx座標)+=0.5+(0.5*スピード);
}
(キャラのy座標)+=0.5+(0.5*スピード);

}


として、表示する時に (int)(キャラの座標) みたいにして動かしてるんです。
そうすると、スピードが速い時に絵のように壁にめり込んで…

微妙なスピードでキャラを動かすにはどうすべきなんでしょうか?
画面の更新(垂直同期がどーとか)とは別個にこういう数値を変える方法があるんでしょうか?


183ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(529,609ポイント)   Date: 2008/03/04(火) 20:30   No:14731     
Title: Re:微妙な位置にいるとき    
え、マジですか!配布していないゲームを持っていらっしゃるとは結構こちらも存じている可能性が・・。
あのゲームは爆弾を蹴るとたまに変な残像が表示されます(笑


え〜とプログラムがはっきり想像出来ませんが、例えば32で割り切れる座標を区間の境目として計算していますか?

32の倍数の座標はスピードが+1、+2なら通りますが、+3なら通りません。+4なら通ります。
そういった加算がうまくいってないとかそういう意味でしょうか?
でも、小数点を使っていると言う事は座標はdouble型で管理しているんでしょうか?

マップがどういった管理になっているのか、配列を使っているのかもわかりませんし、
これだけじゃなんともいえないのですが、

例えば添付ファイルのような3x3の二次元配列で管理した時、属する要素は[y/32][x/32]=[1][0]ですからねぇ。
見た目属している区間は[2][1]のようですが、そういうのに気をつけないといけませんね。

もうちょっと移動制御の部分を詳しく書いてもらえるとわかるかもしれません。


2倍のポイントを手に入れた! 586ポイント を手に入れた。

Name: nya  ..入門者(3,694ポイント)   Date: 2008/03/04(火) 22:57   No:14740     
Title: Re:微妙な位置にいるとき    
本文長いです、スミマセン…
ソースまるごとはチト恥ずかしいので、勘弁してください…
あと、無駄に絵とか貼っちゃってモウシワケナイ…


>え、マジですか!配布していないゲームを持っていらっしゃるとは結構こちらも存じている可能性が・・。
友人が以前ここでC言語のお勉強をしてました。私自身は確かにはじめましてです。
ちなみに来月から大学生の予定です。(まだ受かってませんが)


管理人さんが言わんとしている事が分かるような分からないような…

すみませんが、こっちが解像度320x240、1ブロック16x16でやってるので、
それで話を進めさせてください。

まず、マップのデータは
unsigned char STAGE_MAP_DATA[20*15]={

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, 0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0
};

という感じで作ってます。0が通れないブロック、1が通れるブロックです。

で、どんなマップでも同じ動きをするよう汎用性を持たせたかったので、
キャラクタの上下左右を調べて、そこに該当するブロックが何か調べたりしてます。
画像の淡灰色の■がキャラで、赤い点が調べる位置です。

//キャラの上側のブロック当たり判定。0:動けない  1:動ける

unsigned char BlockJudge_U(int x,int y,unsigned char *map){
if( map[ ((y+16)/16)*20 + (x+8)/16 ] == 0 ) return 0;
else return 1;
};


こんな感じで上下左右作ってます。それで、

if( Key[ KEY_INPUT_UP ] ){		//上ボタンが押されたら

if(BlockJudge_U((int)ch.x,(int)ch.y,STAGE_MAP_DATA)==1){ //上が動けるブロックで
if( (int)ch.x%16!=0 ){ //微妙な位置のとき、
if( BlockJudge_L((int)ch.x,(int)ch.y-16,STAGE_MAP_DATA)==1 ) //左上が動けるなら(-16は1ブロック上の意)
ch.x-=(0.5+ch.speed*0.5); //xの値を1減らす
if( BlockJudge_R((int)ch.x,(int)ch.y-16,STAGE_MAP_DATA)==1 ) //右上が動けるなら
ch.x+=(0.5+ch.speed*0.5); //xの値を1増やす
}
ch.y-=(0.5+ch.speed*0.5); //yの値を1減らす
}
}

そうそう、 ch.x と ch.y はdouble型、ch.speed はint型です。けど、こうやって書いちゃえばいいかなぁなんて…
元々整数値にしてたんですが、それだけだと急激に速くなるので、小数を使ってみました。
そうすると、「ch.x+=1」とかと等しい値になるとちゃんと画像のように行ってくれますが、
やっぱり3とか5とかX.5になると移動しすぎで右側のブロックにズボッとなります。(ならない場合もあったりしちゃう)


…なんか16の約数の問題っぽい気もしてきましたが。うまく思いつかない…


2倍のポイントを手に入れた! 3,366ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,093ポイント)   Date: 2008/03/05(水) 09:18   No:14743     
Title: Re:微妙な位置にいるとき    
こういうのは1次元配列で扱うとバグの元になると思います。
2次元の問題は2次元配列で扱うとわかりやすいです。

まずマップを
STAGE_MAP_DATA[15][20]で書いたほうがよさそうです。


unsigned char STAGE_MAP_DATA[15][20]=
{
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0},

(略)

{0,1,1,1,1,1,1,1,1,1,1,1,1,1,0, 0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0}
};

こういう形で初期化したとき、[y][x]になるので気をつけて下さい。
現在属している配列要素が

map[y][x]だとしたら、
上にいけるかどうかは単純に言えば

if(map[y-1][x]==1)
return 通れる;

で判定できます。まぁここの判定は仰るようにちょっと面倒なわけですが。


そして

ch.x-=(0.5+ch.speed*0.5);

このspeedが大きいと、16の倍数の座標を通り越してしまうということが
問題だと仰っているのでしょうか?
足し算をするとき、私はループ分で行いました。

ch.x += 3;

じゃなく、

for(i=0;i<3;i++){
ch.x += 1;
if(ch.xが境界線なら)
break;
}

こうすれば、境界線を踏み越える事がありません。
 
 


533ポイント を落としてしまった。

Name: nya  ..入門者(3,771ポイント)   Date: 2008/03/05(水) 12:25   No:14747 解決!     
Title: Re:微妙な位置にいるとき    
ありがとうございます!

そんな単純なことだったんですか。
配列も二次元で書くよう気をつけます…

なんか複雑に考えようとしてた自分がバカみたいです。

自分の中ではスッキリしたので、解決とさせてください。

今後も何かあったら宜しくお願いします…


77ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(530,564ポイント)   Date: 2008/03/05(水) 12:27   No:14749     
Title: Re:微妙な位置にいるとき    
多分そんなに簡単には解決せず、色々と苦労するとは思いますが、頑張って下さい^^;
作ってみると「あ〜ハドソンもここで苦労したんだろうな〜」とか分ってくるのでおもしろいですよねw


60ポイント を手に入れた。



Name: ぽん  ..初心者(6,560ポイント)   Date: 2008/02/29(金) 16:35   No:14584       
Title: コマンドラインから入力するプログラムについて質問です    
久しぶりに投稿します<ぽん>です。
いま、コマンドラインからの入力という問題に挑戦中なのですが、ダブルポインタなどがでてきてしまい、作業が途中で止まってしまっています。
教えてくださいm(>_<)m

***
コマンドラインから入力された文字列に小文字のアルファベットが含まれていれば、すべて大文字に変え、文字列を昇順に並べ替えて表示させましょう。
パラメータ文字列が2つ以上入力されなければエラーメッセージを表示して終了させること。

>>sample Ichi
と入力した場合
Usage : STR1 STR2 [STR3 ... ]

>>sample matsuki harada
と入力した場合
** Str data **
matsuki
harada

** Changed str **
HARADA
MATSUKI

>>sample no3 no2 no1
と入力した場合
** Str data **
no3
no2
no1

** Changed str **
NO1
NO2
NO3

というように実行させたいのですが、ソートと大文字への変換がうまくできません。


#include<stdio.h>

int main(int argc, char *argv[])
{
int i;
if(argc < 2)
{
printf("\nUsage %s STR1 STR2 [STR3 ... ]\n",argv[0]);
return 1;
}

printf("\n** Str data **");

for(i = 1; i < argc; ++i)
{
printf("\n%s",argv[i]);
}

printf("\n\n");

void change(int, char **);
void sort(int, char **);

printf("** Changed str **");

for(i = 1; i < argc; ++i)
{
printf("\n%s",argv[i]);
}

printf("\n");

return 0;
}

void change(int cnt, char **pp)
{
int i;
char *p;

for(i = 1; i < cnt; i ++)
{
for(p = pp[i]; *p !='\0'; p++)
{
if((*p>='a')&&(*p<='z'))
{
*p = *p - 'a' + 'A';
}
}
}
}

void sort(int cnt, char **pp)
{
int i;
int j;
int k;
char *p;

for(i = 0; i < cnt-1; i++)
{
for(j = cnt-1; 1 + i < j; j--)
{
for(k = 0; pp[j][k] == pp[j-1][k]; k ++);
{
if(pp[j][k] < pp[j-1][k])
{
p = pp[j];
pp[j] = pp[j-1];
pp[j-1] = p;
}
}
}
}
}

***
いまのところ作ってみているのが上記のものです。
void change(int, char **);
void sort(int, char **);
の部分が間違っているのだろうとは思うのですが・・・どうでしょうか?
ソートと変換の部分もかなり怪しいですが;

<!--12-->


916ポイント を手に入れた。


Name: box  ..ハッカー(107,423ポイント)   Date: 2008/02/29(金) 20:56   No:14589     
Title: Re:コマンドラインから入力するプログラムについて質問です    

言語はC++ですか?Cだと、

> void change(int, char **);
> void sort(int, char **);

ここのところで、「ここで宣言はできない」という内容の
コンパイルエラーが出るはずですからね。

というわけで、上記はプロトタイプ宣言の書き方です。
change関数とsort関数を宣言しているだけで実行していません。

両関数の内容そのものは正しいようです。
main関数から、正しく呼び出してください。


125ポイント を手に入れた。

Name: ぽん  ..初心者(6,800ポイント)   Date: 2008/02/29(金) 22:03   No:14590     
Title: Re:コマンドラインから入力するプログラムについて質問です    
ああ!そうでした;
エラーが出ていたのに記入しておりませんでした;
おまけに呼び出し忘れに気づかずに・・・すみません;
言語はCです。

ありがとうございます、きちんと実行できました!
ところで、質問なんですが・・・

> void change(int, char **);
> void sort(int, char **);

この部分はmainの中に書くよりも、外に出した方がいいのでしょうか?

まだまだC言語の勉強が足りてないので・・・今回のプログラムもエラーを直しながら作成しているので、ソースの理解が出来ておらず。。。

もし何か他に気づいたことやご指摘があれば、よろしければ教えてくださいm(__)m



240ポイント を手に入れた。

Name: box  ..ハッカー(107,734ポイント)   Date: 2008/02/29(金) 22:33   No:14592     
Title: Re:コマンドラインから入力するプログラムについて質問です    
プロトタイプ宣言を書くのであれば、ソースファイルの先頭付近で、
すべての関数の外側に来るように書くのがよくあるやり方です。
プライベート・ヘッダファイルにまとめて書いたりもします。

また、プロトタイプ宣言を書かずにすませる方法もあります。
今回の例であれば、

change関数
sort関数
main関数

あるいは

sort関数
change関数
main関数

の順に書く方法です。
要するに、ある関数を呼び出すよりも「前」に、
当該関数のプロトタイプ宣言または実体があればよいです。

ただし、プロトタイプ宣言を書かずにすませる方法の場合、
関数の実体を書く順序によってはコンパイル時に
エラーあるいは警告が出ます。例えば、仮に、change関数の中で
sort関数を呼び出すようになっていたとすると、

sort関数
change関数
main関数

の順に書けばエラーや警告は出ません。しかし、

change関数
sort関数
main関数

の順に書くと、コンパイル時、コンパイラがchange関数の中で
sort関数の呼び出しを発見したときに
sort関数の引数や戻り値の型がその時点では不明なため、
エラーあるいは警告が出ます。

プロトタイプ宣言を書くか、書かずにすませるかは、
個人の流儀であったり開発チーム内の規約であったりします。
どちらの方法がいいとも悪いともいえないと思いますが、
少なくとも、一つのプログラムの中では混在させない方がよいでしょう。
軸を決めたらぶれさせない、という考えです。


311ポイント を手に入れた。

Name: ぽん  ..初心者(7,395ポイント)   Date: 2008/02/29(金) 22:59   No:14593     
Title: Re:コマンドラインから入力するプログラムについて質問です    
なるほど〜。
ありがとうございます、とても分かりやすくて勉強になります!

もう少し、お時間あれば教えてください。
配列の先頭アドレスを指定する際に、【&配列名[0]】という形で書きたいのですが下記の@〜Dの部分は、こういった形に出来ないものでしょうか?
@は&を付け加えても問題なかったのですが、A以降はエラーがでたり実行がうまくいきませんでした。
【&配列名[0]】の形では書けないと言う事でしょうか。

それと、ポインタ変数を扱う際に、配列([ ])として扱わず、間接参照演算子(*)を用いて書きたいのですがこのプログラムではどこの部分に当たるのでしょうか?

質問ばかりしてスミマセン;
自分でもやってみるんですが途中でこんがらがってしまいました;

***

#include<stdio.h>

void change(int, char **);
void sort(int, char **);

int main(int argc, char *argv[])
{
int i;
int cnt;
int pp;

if(argc <= 2)
{
printf("\nUsage %s STRING1 STRING2 [STRING3 ... ]\n",&argv[0]); /*@*/
return 1;
}

printf("\n** String data **");

for(i = 1; i < argc; ++i)
{
printf("\n%s",argv[i]);  /*A*/
}

printf("\n\n");

change(argc, argv);  /*Bargc,argvどちらも*/
sort(argc, argv);   /*Cargc,argvどちらも*/

printf("** Changed string **");

for(i = 1; i < argc; ++i)
{
printf("\n%s",argv[i]);  /*D*/
}

printf("\n");

return 0;
}

void change(int cnt, char **pp)
{
int i;
char *p;

for(i = 1; i < cnt; i ++)
{
for(p = pp[i]; *p !='\0'; p++)
{
if((*p>='a')&&(*p<='z'))
{
*p = *p - 'a' + 'A';
}
}
}
}

void sort(int cnt, char **pp)
{
int i;
int j;
int k;
char *p;

for(i = 0; i < cnt-1; i++)
{
for(j = cnt-1; 1 + i < j; j--)
{
for(k = 0; pp[j][k] == pp[j-1][k]; k ++);
{
if(pp[j][k] < pp[j-1][k])
{
p = pp[j];
pp[j] = pp[j-1];
pp[j-1] = p;
}
}
}
}
}

***


595ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(42,015ポイント)   Date: 2008/03/01(土) 00:23   No:14594     
Title: Re:コマンドラインから入力するプログラムについて質問です    
>【&配列名[0]】の形では書けないと言う事でしょうか。
【配列名】と【&配列名[0]】はどちらも配列の先頭要素へのポインタを返しています。
よって【配列名】と表記可能な部分はすべて【&配列名[0]】に置き換え可能です。

ここで問題にしているのは、change()の引数のchar**の部分を【&配列名[0]】に表記
したいということでしょうか?

argvはchar*の配列と宣言されているので、その先頭要素へのポインタはchar**と同じ型になり
求めている形で表現可能です。
argcはint型なので(もともと配列ではないし)求めている形で表現は型が一致しないので不可能です。


(型の自動変換についての言及は省いています。)


>それと、ポインタ変数を扱う際に、配列([ ])として扱わず、間接参照演算子(*)を用いて書きたいのですがこのプログラムではどこの部分に当たるのでしょうか?

直接の答えにはなりませんが、ヒントとしてはこんな感じです。
(してはいけないような書き方を一部お遊びでしているので真似をしないでください。)

#include <stdio.h>

int main(void)
{
int a[3],i;
for(i=0;i<3;i++)
printf("&a[%d]: %p\n",i,&a[i]),
printf("(a+%d): %p\n",i,(a+i)),
printf("\n");
return 0;
}


# ソースコードの中に全角空白はやめてほしいと思います。


413ポイント を手に入れた。

Name: ぽん  ..初心者(7,836ポイント)   Date: 2008/03/03(月) 01:47   No:14646     
Title: Re:コマンドラインから入力するプログラムについて質問です    
ありがとうございます。
ヒントを参考に直してみました。
エラーはでませんが、実行結果でソートがされなくなってしまいました;
ソート部分を([])を使った書き方から(*)を使う書き方に直したかったのですが、直し方がダメだったのでしょうか?(ポインタのポインタを使用した場合の直し方がいまいち理解できていなくて;)


void sort(int cnt, char **pp)
{
int i;
int j;
int k;
char *p;

for(i = 0; i < cnt-1; i++)
{
for(j = cnt-1; 1 + i < j; j--)
{
for(k = 0; *(*pp+j+k) == *(*pp+(j-1)+k); k ++);
{
if(*(pp+j+k) < *(pp+(j-1)+k))
{
*p = *(*pp+j);
*(*pp+j) = *(*pp+(j-1));
*(*pp+(j-1)) = *p;
}
}
}
}
}

実行例:
>>sample matsuki harada
と入力した場合
** Str data **
matsuki
harada

** Changed str **
MATSUKI
HARADA ←本来なら「HARADA」が先に来て「MATSUKI」が後に来ないといけないのですが。



441ポイント を手に入れた。

Name: box  ..ハッカー(108,036ポイント)   Date: 2008/03/03(月) 06:40   No:14649     
Title: Re:コマンドラインから入力するプログラムについて質問です    

3重ループではなく、2重ループでできるのではないか、
と思います。
また、

> for(k = 0; *(*pp+j+k) == *(*pp+(j-1)+k); k ++);

最後のセミコロンは、何を意味しているのでしょうか?


59ポイント を手に入れた。

Name: ぽん  ..初心者(8,289ポイント)   Date: 2008/03/04(火) 01:21   No:14703     
Title: Re:コマンドラインから入力するプログラムについて質問です    
すみません!
書き間違いですね、セミコロンは必要なかったです;
2重ループ・・・for文を減らすことができるということでしょうか。(どうすれば・・・;)

void sort(int cnt, char **pp)

{
int i;
int j;
int k;
char *p;

for(i = 0; i < cnt-1; i++)
{
for(j = cnt-1; 1 + i < j; j--)
{
for(k = 0; *(*((pp+j)+k)) == *(*((pp+(j-1))+k)); k++)
{
if(*(*((pp+j)+k)) < *(*((pp+(j-1))+k)))
{
*p = *(*(pp+j));
*(*(pp+j)) = *(*(pp+(j-1)));
*(*(pp+(j-1))) = *p;
}
}
}
}
}

少し書き直してみたのですが、やはりソートができません。([ ]で記述したときはきちんと実行できたということはこの書き方が間違って・・・;)
・・・strcmpを使って文字列を比較するというのはこのプログラムの場合どうすればいいのでしょうか?
strcmpを使えば文字列比較に便利だと本に書いてあったのですがよく分からなくて・・・。

それとmainの中でchangeを使うときに先頭アドレスを渡すとはどういうことでしょうか?

質問ばかりでごめんなさい;
どこをどういじればいいのか段々わからなくなっておりますが。
ポインタやソートについての分かりやすい初心者向けの本でオススメがあればどなたか教えてください(>_<)



453ポイント を手に入れた。

Name: フリオ  ..上級者(21,943ポイント)   Date: 2008/03/04(火) 04:42   No:14704     
Title: Re:コマンドラインから入力するプログラムについて質問です    
 
 小文字を大文字に変換するための、"toupper"という関数があります。


> [ ]で記述したときはきちんと実行できたということはこの書き方が間違って・・・
 []演算子の式を*演算子の式に変換する場合は、
p[i] -> *(p + i)
です。
また、それ以外は変える必要はありません。


 "sort"関数の文字列を比較する処理は、
同じ文字列が渡されたらどうなるか、考える必要があります。


> strcmpを使って文字列を比較するというのは
> このプログラムの場合どうすればいいのでしょうか?
 "strcmp"は、文字列を文字コード順で比較する関数なので、
文字列を比較している処理の部分を"strcmp"に置き換えてやればいいだけです。


160ポイント を手に入れた。

Name: やそ  ..上級者(24,752ポイント)   Date: 2008/03/04(火) 11:53   No:14705     
Title: Re:コマンドラインから入力するプログラムについて質問です    
ポインタについての本

「C言語のポインタがゼッタイにわかる本」・・・ 秀和システム

etc


26ポイント を手に入れた。

Name: ぽん  ..初心者(8,441ポイント)   Date: 2008/03/05(水) 02:25   No:14741 解決!     
Title: Re:コマンドラインから入力するプログラムについて質問です    
ありがとうございます!
無事にプログラムを完成させることができました<(_ _)>

> 小文字を大文字に変換するための、"toupper"という関数があります。

こんな便利な関数があるんですね!
さっそく調べて使ってみました。

ポインタの本も本屋に行って探してみます。

長々とありがとうございました。
またお世話になると思いますが、そのときは宜しくお願いします。



152ポイント を手に入れた。



Name: 管理人 [URL]  ..伝説のハッカー(526,019ポイント)   Date: 2008/03/03(月) 18:19   No:14685       
Title: 配列のオーバーフローについて    
配列のオーバーフローについて語るトピをこちらに立てさせていただきました。

以下、他トピからうつした記事です。


10ポイント を落としてしまった。


Name: 管理人 [URL]  ..伝説のハッカー(526,338ポイント)   Date: 2008/03/03(月) 18:21   No:14687     
Title: Re:配列のオーバーフローについて    
(以下コピー)

    ****dixq****

村に入ってからゲームを始めた時、ドレス変身、低速移動時に
レーザーが表示されないというバグ修正しました。

ひぃ、やっぱりオーバーフロー怖いですね〜。

#define CH_CHANGE_NUM1 3
#define CH_CHANGE_NUM2 2

int img_cshot1[CH_CHANGE_NUM1][CH_CHANGE_NUM2];

img_cshot1[3][0] = LoadGraph( "dat/img/char/cshot30.png" );//レーザー画像
      ↑

その後、村に入った時、全然関係無いところで宣言したhumanに対して

memset(human,0,sizeof(human_t));

これを処理した瞬間画像が無くなって(呼び出せなくなって)いました。
オーバーフローした時コンパイラが怒ってくれたらいいのに・・。




    **** バグ ****

私もよくやります(苦笑)
配列なのに添え字自体を書き忘れていて、正体不明のアドレスにデータを書き込んでしまい、例外が発生しました。冷静に考えたら、恐ろしいことをしてしまったなぁ…と(^_^;)




    ****GPGA****

C/C++の 配列[要素数] は単純にアドレスの足し算を行うだけなので
配列オーバーの判断はしないのではないでしょうか?
上記のため、以下のソースはコンパイルが通ります。


#include <stdio.h>

int main(void)
{
printf("%c\n", 3["abcde"]);
return 0;
}
 

Eclipse+CDTのコンパイルは行ったことがないのですが、上記のソースはコンパイルが通るのですかね?
もし通らないのであれば、言語の規格に沿っていないことになるのかも・・・。




    ****dixq****

>>>GPGAさん
>上記のため、以下のソースはコンパイルが通ります。

奇怪に見えますねw
Eclipsの話をしておきながら、Eclipsは使えないので(JAVAが得意な友人の様子を見ていただけ)確認出来ませんが、
オーバーフローの指摘があっただけでかなりのバグは抑えられる気がするのですが・・。
まぁ単純に管理が出来ていないだけだということもありますが(汗






319ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(527,727ポイント)   Date: 2008/03/03(月) 18:25   No:14688     
Title: Re:配列のオーバーフローについて    
    ****GPGA****

Javaとしてコンパイルした場合ですと、エラーを出してくれますね。
これはたぶんJavaの言語仕様で決まっていることなのだと思います。
Javaにはポインタがありませんから。

配列オーバーのチェックですが、私が考えられる方法は3つあります。

一つ目は全てをenumで管理するやり方です。これはチェックというより管理ですね。

enum {
CH_CHANGE_NUM1_IDX0,
CH_CHANGE_NUM1_IDX1,
CH_CHANGE_NUM1_IDX2,

CH_CHANGE_NUM1,
};

int img_cshot1[CH_CHANGE_NUM1];
img_cshot1[CH_CHANGE_NUM1_IDX0] = 0;
 
このように、全ての配列アクセスをenumで定義した値で行うことで、危険を回避します。


二つ目はstd::vectorのatメソッドを使用することです。
このメソッドは配列アクセスを行う際に、指定されたインデックスのチェックを行い
要素外の値の場合は std::out_of_range を投げます。

#include <iostream>
#include <vector>

int main(void)
{
std::vector<int> ary(4);

try {
ary.at(5) = 10;
} catch (std::out_of_range e) {
std::cout << "配列オーバー:" << e.what() << std::endl;
}
return 0;
}
 
三つ目はstd::vectorを継承して、自分独自のクラスを作成し、そのクラスでoperator[] を定義して
チェックを行うというものです。


#include <iostream>
#include <vector>

template<class T>
class myvector : public std::vector<T> {
public :
myvector(int n) :
std::vector<T>(n)
{
}
~myvector() {
std::vector<T>::~vector();
}

T& at(int idx, const char* file, int line) {
if (idx < 0 || (unsigned int)idx >= size()) {
std::cout << file << ":" << line << "行目 " << "配列オーバー" << std::endl;
throw std::out_of_range("invalid myvector<T> subscript");
//return std::vector<T>::operator[](0);
}
return std::vector<T>::operator[](idx);
}
const T& at(int idx, const char* file, int line) const {
if (idx < 0 || (unsigned int)idx >= size()) {
std::cout << file << ":" << line << "行目 " << "配列オーバー" << std::endl;
throw std::out_of_range("invalid myvector<T> subscript");
//return std::vector<T>::operator[](0);
}
return std::vector<T>::operator[](idx);
}

T& operator [](int idx) {
if (idx < 0 || (unsigned int)idx >= size()) {
std::cout << "配列オーバー:" << idx << std::endl;
throw std::out_of_range("invalid myvector<T> subscript");
//return std::vector<T>::operator[](0);
}
return std::vector<T>::operator[](idx);
}
const T& operator [](int idx) const {
if (idx < 0 || (unsigned int)idx >= size()) {
std::cout << "配列オーバー:" << idx << std::endl;
throw std::out_of_range("invalid myvector<T> subscript");
//return std::vector<T>::operator[](0);
}
return std::vector<T>::operator[](idx);
}
};
#define at(n) at(n, __FILE__, __LINE__)

int main(void)
{
myvector<int> vec(1);

try {
vec[1] = 20;
} catch (...) {
}
try {
vec.at(1) = 20;
} catch (...) {
}

return 0;
}
 
ただ、本来std::vectorやstd::stringなどのSTLは継承用に作られていないので、継承した場合
元のデストラクタが標準で呼び出されません。(デストラクタにvirtualが付いていない)
ですので、継承先のデストラクタで継承もとのデストラクタの呼び出しを行っているのですが
これが正しいかどうか、わかりません。もし間違っているのであれば、どなたかご指摘ください。

もしこれで問題がない場合、使い方はstd::vectorと何も変わりません。
ただ、このクラスでは[]アクセスの際にオーバーした場合 atメソッドと同じように例外を投げてくれます。
また、atメソッドの方にも改良を加え、[]の代わりにatメソッドを使用した場合、問題が発生した
ファイルと行数を見れるようにしてあります。ただし、at用のマクロを定義するか、__FILE__と__LINE__を
常に入れる必要があるのが難点です。




    ****dixq****

なるほど、詳しくありがとうございます。
私も必要な配列要素数がよくわかるものにはベクターは使うのでは、これは単なる配列より処理が遅くなるのではと思い、
固定でいいものや小さい配列には普通の配列を使っていました。
問題になるほどの処理速度の違いは無いんでしょうか?




    ****組木紙織****

>元のデストラクタが標準で呼び出されません。(デストラクタにvirtualが付いていない)
基底クラスのポインタでオブジェクトを扱った時
(簡単に言うとポリモーフィズムで扱うとき)
にはこのような状態になりますが、
オブジェクトそのもので扱った時にはきちん基底クラスのデストラクタは呼ばれます。

なのでこの場合にはデストラクタを明示的に呼ぶ必要はないのではないかと思います。
また。オブジェクトの解体は継承された部分から解体していくことになっていたはずなので、
先に継承元のオブジェクトを解体すると、何か悪いことが起こるような気がします。

std::vectorを継承して使わずに、メンバに入れて扱う方が良いのではないかと思います。


#include <iostream>
using namespace std;

class Hoge
{
public:
Hoge(){cout << "begin Hoge" << endl;}
~Hoge(){cout << "end Hoge" << endl;}

};

class HogeHoge :public Hoge
{
public:
HogeHoge(){cout << "begin HogeHoge" << endl;}
~HogeHoge(){cout << "end HogeHoge" << endl;}
};

int main()
{
Hoge *p = new HogeHoge;
delete p;
return 0;
}




1,389ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(527,974ポイント)   Date: 2008/03/03(月) 18:26   No:14690     
Title: Re:配列のオーバーフローについて    
    ****GPGA****

確実に配列オーバーしない保障があると思うものに関しては
普通の配列を使用しても問題ないと思います。

vectorに関しては、アセンブル出力をして調べたことがないので、正確な速度はわかりませんが
配列参照一回に付き、関数呼び出し一回分くらいの速度の低下は考えておいたほうがいいかもしれません。
ただ、うまく配列の扱えば速度低下はかなり抑えられると考えております。

まず先ほどの、myvectorは毎回配列チェックを行っているので、かなり重い処理です。
ですが、チェックを行うのはデバッグ時のみで、リリース時に必要ないのであれば


#ifdef _DEBUG
typedef myvector<int> IntArray;
#else
typedef std::vector<int> IntArray;
#endif
 
とすることで、リリース版では余計なチェックを入れないようにすることができます。

次に、配列の高速な使い方の例を示します。
まずシューティングの弾の構造体を以下とします。

struct BulletData {
int x, y, flg;
} bullet[100];
 
そして、以下は処理するプログラムです。


for (int i = 0; i < 100; ++i) {
BulletData* p = &bullet[i];
if (p->flg != 0) {
p->x = 0;
p->y = 0;
}
}
 
処理する前にポインタに格納し、後はポインタから操作を行うだけで
余計な配列アクセスを行わないので、処理を高速化することができます。
以上実装した上でのアクセス数であれば、処理速度はそれほど気にする必要はないと思われます。


247ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(42,841ポイント)   Date: 2008/03/03(月) 18:42   No:14693     
Title: Re:配列のオーバーフローについて    
>>組木紙織さん
>オブジェクトの解体は継承された部分から解体していくことになっていたはずなので、
>先に継承元のオブジェクトを解体すると、何か悪いことが起こるような気がします。
>std::vectorを継承して使わずに、メンバに入れて扱う方が良いのではないかと思います。
やはりこうなってしまいますかね。
安全性を考えると、この方法が一番だということはわかっているのですが
今回これをやるということは、vectorのメソッドを全てラップする必要が出てくるんですよね。
myvectorのあり方は、vectorクラスに追加機能を加えるというものですから
vectorを継承して使用せず、メンバに持って全てのvectorクラスのメソッドのラップを作るというのは
オブジェクト指向の考え方に背いているような感じがします。


335ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(35,420ポイント)   Date: 2008/03/03(月) 19:17   No:14695     
Title: Re:配列のオーバーフローについて    
厳密な意味での安全性という観点では、std::vector からは継承しない方がよいのですが...

std::vector から継承したクラスを定義し、なおかつ動的多相性を実現したいのであれば、boost::shared_ptr を使うとよいでしょう。
これなら、仮想デストラクタがなくても正しく振舞ってくれます。
また、テンプレートを用いて、静的な多相性を発揮させる上では何の問題もありません。

個人的には、セマンティックスが異なるのであれば、異なるインタフェースを持たせるのが筋のように思います。
例えば、非メンバの at 関数を用意するなどです。


243ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(42,987ポイント)   Date: 2008/03/04(火) 16:27   No:14715     
Title: Re:配列のオーバーフローについて    
>std::vector から継承したクラスを定義し、なおかつ動的多相性を実現したいのであれば、boost::shared_ptr を使うとよいでしょう。
これはmyvectorをポインタとして扱うとき、以下のようにするということでしょうか?

template<class T>
class myvector : public std::vector<T> {
・・・
};

boost::shared_ptr<myvector<int> > vec;
 


146ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(35,489ポイント)   Date: 2008/03/04(火) 19:25   No:14730     
Title: Re:配列のオーバーフローについて    
> これはmyvectorをポインタとして扱うとき、以下のようにするということでしょうか?

そうです。
shared_ptr のコンストラクタは、実引数の静的な型に応じて、delete 用の関数を内部で管理します。
そのため、仮想デストラクタがなくても、あたかも仮想デストラクタがあるかのように動作します。


69ポイント を手に入れた。



Name: バグ  ..比類無きプログラマー(78,309ポイント)   Date: 2008/03/03(月) 16:46   No:14667       
Title: ぷよぷよ    
少し前にぷよぷよの作成方法について質問をされていた方が居まして、いくつかサンプル関数を作ってみたのですが、どうせ乗りかかった舟ならば…と、コンソールアプリで最低限の機能しか搭載していないぷよぷよを作ってみました。


/* 動作環境 */
Windows XPでのみ確認しています。


/* 操作方法 */

ぷよぷよ.exeファイルを実行して、何かを押すとゲームスタートします。

カーソルキー左右で横移動、上で高速落下、下で1マス落下です。

Z、Xで回転させることができます。

汚いソースコードですが、一応、添付しておきますので、自由に使っていただいて構いません。


192ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(525,719ポイント)   Date: 2008/03/03(月) 17:51   No:14676     
Title: Re:ぷよぷよ    
ウィンドウがコラムスに見えてしまうw
バグさんパズルゲーお好きですね〜^^
パズルゲーはAIを作るのが難しいのでもう限界です・・。
複雑なカードゲームとかも難しそうですが、ゲームプログラミングで一番難しいのってAIじゃないですかね??


119ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,400ポイント)   Date: 2008/03/03(月) 19:45   No:14696     
Title: Re:ぷよぷよ    
本当はカラードロップとかも、今ソースを見ると『いやぁ!見ないでぇ!』って感じなので、全部作り直したい気持ちなんですよね(苦笑)

今回のはあの頃よりは内部的に、かな〜りスッキリしてます。ゲームそのものよりも、むしろカラードロップ1や2の頃のソースと今のソースを比較して欲しいかな〜?とか思いますね(笑)

それでも、まだまだ勉強する事はテンコ盛です(^_^;)


156ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(528,374ポイント)   Date: 2008/03/03(月) 19:53   No:14697     
Title: Re:ぷよぷよ    
あ、やっぱそうですよね??
プログラム書くたびに書き方が変るんですがみんなそうですかね〜^^;
多分書くたびに効率よいプログラムに変更するのは効率いい書き方を知らないからだと思いますがw

私は高速に弾幕を計算出来るような処理を何度も書き直しました^^;


2倍のポイントを手に入れた! 40ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,405ポイント)   Date: 2008/03/03(月) 20:08   No:14698     
Title: Re:ぷよぷよ    
今回のぷよぷよは、メイン関数の短さに注目してほしいですね。やり過ぎやろ!って感じです(笑)
ただ、カプセル化した事で、描画と入力関係さえ直せばDxLib用に移植する事も容易いと思っての事なので、ネタだと思って笑ってください(笑)


5ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(528,414ポイント)   Date: 2008/03/03(月) 23:00   No:14700     
Title: Re:ぷよぷよ    
短っw
でも確かにメイン関数は短くしたいですよね〜。
昔メイン関数に1000行位書いていた反動でしょうかw

あ、バグさんは龍神録見てくれました?!


40ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,453ポイント)   Date: 2008/03/04(火) 12:14   No:14706     
Title: Re:ぷよぷよ    
今、ダウンロードしてみたのですが、解凍に失敗して、遊べません(T-T)
ミラーサイトから落としたのも同じ結果でした…OTL


48ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(528,688ポイント)   Date: 2008/03/04(火) 12:44   No:14708     
Title: Re:ぷよぷよ    
朝のバージョンアップで入れたデータファイルの中にシステムファイルが入っていてエラーが起きていたようです。
v1.20としてアップしましたので、試してみて下さいm(_ _)m


75ポイント を手に入れた。



Name: akira  ..ぴよぴよ(5ポイント)   Date: 2008/03/03(月) 18:26   No:14689       
Title: AA動画について。    
//ファイル名が違う場合はダブルコーテーション内をいじってください
sprintf(name,"image0/raki %7d.bmp",cnt+1
この部分をどのように変更すればいいのでしょうか?
よろしくお願いします。


5ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(528,146ポイント)   Date: 2008/03/03(月) 18:38   No:14692     
Title: Re:AA動画について。    
投稿される時は以前と同じお名前をお使い下さい。
規約とさせていただいておりますのでよろしくお願いします。

sprintf(name,"image0/raki %7d.bmp",cnt+1。。。

これは普通にファイル名をnameに代入しているだけですから、ファイル名が変われば変ったとおり変更すればいいです。

例えばファイル名がrakiじゃなくlakiとかになったならlakiに書き換えて下さい。

%の次に0を書けば文字である0を自動的に詰めてくれます。


193ポイント を手に入れた。



Name: taro  ..ぴよぴよ(80ポイント)   Date: 2008/03/03(月) 17:10   No:14669       
Title: 無題    
とても初歩的な質問なのですがvisualC++でfor文をつかって縦、横の大きさを入力すると*によって枠だけの四角形を描くようなプログラムを作りたいのですが、お願いいたします。


(実行例) 4 5
      *****

* *

* *

*****


80ポイント を手に入れた。


Name: box  ..ハッカー(108,036ポイント)   Date: 2008/03/03(月) 17:14   No:14670     
Title: Re:無題    
手で書くとしたらどういう手順を踏むかを考えてみてください。

Name: taro  ..ぴよぴよ(100ポイント)   Date: 2008/03/03(月) 17:18   No:14671     
Title: Re:無題    
すいません、、、 よくわからないです。 本当に初心者なもので、、

20ポイント を手に入れた。

Name: やそ  ..上級者(24,726ポイント)   Date: 2008/03/03(月) 17:38   No:14672     
Title: Re:無題    
boxさんがおっしゃっているのは、
処理の流れを一つ一つ順を追って書き出してみると良い。
と言うことです。

*を使った四角形の表示。
まずは*で塗りつぶす四角形を考えてみてください。

それが出来ればあとちょっとの工夫で出来るはずです。

たて、横の数値の入力はとりあえずscanf()関数でも使って入力させてみては?
その数字が取得できればfor文でまわしてあげるだけですね。

int i, j, tate, yoko;

scanf("たて",&tate);
scanf("よこ",&yoko);

for(i=0;i<tate;i++){
for(j=0;j<yoko;j++){
printf("*");
}
printf("\n");
}


ご参考まで^^


289ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(525,689ポイント)   Date: 2008/03/03(月) 17:38   No:14673     
Title: Re:無題    
実行例がちゃんとかけてなかったので書き直しておきました。
また、プログラムでかけなくとも、taroさんは手ではかけますよね。
手で書くときどうやって書くか詳しく書いてみればわかってくるでしょう。


50ポイント を手に入れた。

Name: taro  ..ぴよぴよ(135ポイント)   Date: 2008/03/03(月) 17:49   No:14675     
Title: Re:無題    
ありがとうございます。*で塗りつぶす四角形は書けるのですが、、どうしても枠だけにするのができません。


35ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(525,849ポイント)   Date: 2008/03/03(月) 17:54   No:14677     
Title: Re:無題    
塗りつぶしたくない時に、塗りつぶさないようにすればいいだけです。
taroさんは「いつ」塗りつぶしたいのですか?
それをよく考えてみて下さい。



答え
y=0
y=3の直線と
x=0
x=4の直線上にあるとき


130ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(525,954ポイント)   Date: 2008/03/03(月) 18:01   No:14678     
Title: Re:無題    
ほぼ答えになってしまいますが、
例えば10x10のエリア上にy<=xかつy>=x-4の範囲で塗りつぶしたい時は以下のようにかけますよね。



#include <stdio.h>

int main(void)
{
int i,j;
int x_Length=10, y_Length=10;
for(i=0;i<y_Length;i++){
for(j=0;j<x_Length;j++){
if(j>=i && j<=i+4)
printf("*");
else
printf(" ");
}
printf("\n");
}
printf("\n");
return 0;
}


実行結果

*****
*****
*****
*****
*****
*****
****
***
**
*


105ポイント を手に入れた。

Name: taro  ..ぴよぴよ(174ポイント)   Date: 2008/03/03(月) 18:03   No:14679     
Title: Re:無題    
やりたいことはわかっているのですがプログラムにすることができません、、、。すいません未熟者で、、

39ポイント を手に入れた。

Name: 通りすがり  ..初心者(7,074ポイント)   Date: 2008/03/03(月) 18:06   No:14681     
Title: Re:無題    
質問者はわからないわからないばかりじゃなく、質問しているのなら、
回答者のアドバイスや指示通りまずやってみたらどうですか?

いくらなんでも手で書く手順位分ると思いますよ。


52ポイント を手に入れた。

Name: taro  ..ぴよぴよ(192ポイント)   Date: 2008/03/03(月) 18:10   No:14682 解決!     
Title: Re:無題    
ありがとうございました。 ようやく完成することができました。お手数掛けました。

2倍のポイントを手に入れた! 18ポイント を手に入れた。



Name: TERU  ..ぴよぴよ(58ポイント)   Date: 2008/03/03(月) 16:03   No:14665       
Title: 教えていただきたいです;;    
質問です。
横スクロールアクションのゲームを作ろうと思っているのですが画像のスクロールというのはどのように行なえばいいでしょうか??
ぜひ教えていただきたいです(m。_。)m


58ポイント を手に入れた。


Name: やそ  ..上級者(24,437ポイント)   Date: 2008/03/03(月) 17:04   No:14668     
Title: Re:教えていただきたいです;;    
それだけではちょっと情報不足な気がします(^^;

以前にも横スクロールアクションの話題が有りましたので参考になさってください。

http://www.play21.jp/board/formz.cgi?action=res&resno=13695&page=20&lognum=43&id=dixq&rln=13727

また、質問の際はもう少し具体的にされると良いでしょう。
横スクロールといっても、左なのか右なのか、そのステージ(背景)の大きさは?
キャラクタ(自機)の移動範囲は?(何コマ進むとスクロールさせたい?それとも中央固定で常に背景スクロール?)

など、想定されている設定、状況などを具体的にされるとベターな回答がされやすいかと思います。


180ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(526,029ポイント)   Date: 2008/03/03(月) 18:04   No:14680     
Title: Re:教えていただきたいです;;    
ご自分の想像していらっしゃるものと同じ既存のゲームをよく見てみるといいですよ。
マリオ、魔界村、ロックマンなどあると思います。
どんなゲームを想像していらっしゃいますか?


75ポイント を手に入れた。



Name: san  ..ぴよぴよ(16ポイント)   Date: 2008/03/03(月) 14:44   No:14661       
Title: visual c++ express 2008でのAA動画の作り方を教えてください。    
visual c++ express 2008でのAA動画の作り方を教えてください。


16ポイント を手に入れた。


Name: やそ  ..上級者(24,257ポイント)   Date: 2008/03/03(月) 15:08   No:14662     
Title: Re:visual c++ express 2008でのAA動画の作り方を教えてください。    
ttp://dixq.net/rakisuta.html

TOPページにAAの作り方へのリンクがありますよ。
管理人さんの力作?(本人否定^^;)ですから是非ごらんになって盗めるだけ盗むといいんじゃないかな(笑)


91ポイント を落としてしまった。

Name: 管理人 [URL]  ..伝説のハッカー(525,639ポイント)   Date: 2008/03/03(月) 15:18   No:14663     
Title: Re:visual c++ express 2008でのAA動画の作り方を教えてください。    
まぁ作成数時間ですしね^^;

sanさんは、AA動画をお作りになりたいと思われたきっかけは何でしょうか?
私の作った動画か何かをご覧になったのでしょうか。
やそさんが紹介されている通り、

http://dixq.net/rakisuta.html

こちらで詳しく紹介しておりますので、ご参考下さい。


89ポイント を手に入れた。



Name: Nikol  ..ぴよぴよ(47ポイント)   Date: 2008/03/02(日) 22:13   No:14634       
Title: クラスのデータ共有    
こちらでは以前もお世話になったことがあります。
が、HNを忘れてしまいましたのでNikolと名乗らせていただきます。

質問なのですが、例えば以下のような配置

[メインプログラム]-->--[キャラクター管理クラス]
-->--[戦闘管理クラス]
-->--[マップ管理クラス]

そして以下の構造体データ(例)
char name;
char job;
int hp, mp;

この構造体データをキャラクター管理クラスが保持しているとして、
そのデータをメインプログラムで保持、
そしてそのほかのクラスで使用したいとおもっているのですが、
int型はreturnを駆使することでどうにかなるのですが、
char型はどのようにしたらよいのでしょうか?

また、もっと手軽に構造体を共有できる方法はないのでしょうか?
ご回答おねがいします。


47ポイント を手に入れた。


Name: 組木紙織  ..熟練のプログラマー(43,101ポイント)   Date: 2008/03/02(日) 23:27   No:14639     
Title: Re:クラスのデータ共有    
クラスという言葉を使っているのでC++で作っていると判断しました。
詳細がわからないので適当に組んでみました。

意識したのは以下の部分です。
>この構造体データをキャラクター管理クラスが保持しているとして、
>そのデータをメインプログラムで保持、
>そしてそのほかのクラスで使用したいとおもっているのですが、


#include <iostream>
struct Data
{
char name;
char job;
int hp, mp;
};

class Charactor
{
public:
Data data;
void setData(){
data.name = 'A';
data.job = 'b';
data.hp = 3;
data.mp =1;
}
};

class War
{
public:
Data *p_data;
War(Data *data)
{
this->p_data = data;
}
void showData()
{
std::cout << "data.name: " << this->p_data->name << std::endl;
std::cout << "data.job: " << this->p_data->job << std::endl;
std::cout << "data.hp: " << this->p_data->hp << std::endl;
std::cout << "data.mp: " << this->p_data->mp << std::endl;
}
};

int main()
{
Charactor chara;
War war(&chara.data);

chara.setData();
war.showData();
};


413ポイント を手に入れた。

Name: Nikol  ..ぴよぴよ(53ポイント)   Date: 2008/03/03(月) 06:56   No:14650     
Title: Re:クラスのデータ共有    
ご回答ありがとうございます。

なるほど、そういう手がありましたか。
参考にさせていただきます。

もうひとついいでしょうか?

その構造体が配列されているばあい
(ex) Data data[10];
どのようにしたらよいのでしょうか?


6ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,052ポイント)   Date: 2008/03/03(月) 08:40   No:14651     
Title: Re:クラスのデータ共有    
ポインタで渡している訳ですから、添え字の分だけアドレスをインクリメントすればいいと思います。

46ポイント を手に入れた。



Name: tny  ..ぴよぴよ(802ポイント)   Date: 2008/03/03(月) 01:47   No:14647       
Title: VisualC++ 入力候補表示を自動で表示するには    
visual c++ express 2008 を導入したのですが、入力候補表示(IntelliSenseと言うのでしょうか)を自動でやってくれる設定にしたいのです。
今のところは、Ctrl + Spaceをしてますが……
是非教えて下さい。


64ポイント を落としてしまった。




Name: 超初心者  ..入門者(4,193ポイント)   Date: 2008/03/02(日) 23:25   No:14638       
Title: 無題    
当HPを読ませていただいていたら、
なにかゲームが作りたくなってしまったので質問させてください。

http://www.youtube.com/watch?v=v1Vz8URRdw4&feature=related

ここにあるようなゲームをつくろうとしたんですが、
図柄の変動(左右の数字付の絵が上下にスクロール)の処理のところで
詰まってしまいました。
なにかうまい動かし方がありましたらご教授お願いします。


160ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(525,084ポイント)   Date: 2008/03/03(月) 00:13   No:14644     
Title: Re:無題    
つまりスロットを作りたいわけですね??
う〜ん、動かし方はきっと100人いたら100通りの案が浮かぶでしょうし、私もどれがうまい方法なのかはわかりませんが、
普通にカウンタを特定の数字に対応させたらいいんじゃないでしょうか。
仮に0〜9の数字のスロットだとします。

カウンタを0〜99の間でループさせます。
(cnt = (++cnt)%100; みたいな)

カウンタが0~9の時にボタンを押したら一週まわって0に決定。
カウンタが10~19の時にボタンを押したら一週まわって1に決定。
そんな感じで対応させたら割りと簡単だと思いますが、どうでしょうか。

具体的な現在書いているコードとか全くなしに、「いい方法は無いか」と言われると回答に困るのですが、
単純なスロットなら単純にカウンタに数字を対応させればいいと思います。


237ポイント を落としてしまった。



Name: 組木紙織  ..プログラマー(32,523ポイント)   Date: 2008/01/28(月) 22:29   No:13859       
Title: マルチスレッドクラス    
おかげさまで大分完成してきました。
質問に答えてくださった方々ありがとうございます。

基本的な骨格が完成したので、今回は質問というより批評をお願いしたいと思います。

スレッド作成クラス、ミューテックスを作ったので基本的なスレッド操作は
出来るようになったと思います。
残りはイベントクラス、セマフォクラスを作ったら完成予定です。

基本的なコンセプトは、エラーが起きてもデットロックに陥りにくいように
する。プログラムが途中で停止しない。という2点です。

クラスは全てTKネームスペースの中に入れています。
サンプルコードも入れてあるので使い方は分かると思います。
使用してみて気になったことがあったらコメントを下さい。

#前回の後にコメントしようと思ったらもう過去ログになってた。。。


349ポイント を手に入れた。


Name: たかぎ [URL]  ..プログラマー(26,167ポイント)   Date: 2008/01/28(月) 23:19   No:13860     
Title: Re:マルチスレッドクラス    
突っ込みどころ満載なので、とりあえず上から順番にいきます。
まずは ThreadException クラスから。
ThreadException(std::exception e):exception("Thread"),name(e.what()){}

ThreadException():exception("Thread"){}
ThreadException(const char * e) :exception("Thread"),name(e){}


コンストラクタですが、std::exception からの変換コンストラクタの存在意義がよくわかりません。
なぜ exlicit を付けないのか、なぜ値渡しなのかも読み取れませんでした。
const char*からの変換コンストラクタも explicit なしでは危険ではないですか?
コピーコンストラクタを定義していないのは意図通りでしょうか?(なくても問題はなさそうです)
データメンバ name の初期化時に std::bad_alloc 例外が送出される可能性があることは想定済みでしょうか?
ThreadException operator=(ThreadException &e){return e;}



代入演算子の形式が変です。これを書くなら、
ThreadException& operator=(const ThreadException &e)

{
std::string t(e.name);
name.swap(t);
return *this;
}


とすべきです。ここでも std::bad_alloc 例外が送出される可能性がありますが、これは避けられません。
const char * getName(){return this->name.c_str();}



なぜ const がないのでしょうか? これだとコンパイルできないと思います。

そもそも Thread::throwErrorCode にかなり無理があるように思います。


385ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(26,226ポイント)   Date: 2008/01/28(月) 23:37   No:13861     
Title: Re:マルチスレッドクラス    
Thread クラスですが、コピーコンストラクタやコピー代入演算子でコピーされると、コピーの数だけ CloseHandle が呼ばれますが、大丈夫でしょうか?

Thread::Pack のデータメンバである errorException と errorFlag ですが、参照先の寿命管理は本当に大丈夫ですか?

Thread::run の中で例外を catch しているのはよいのですが、ThreadException のコンストラクタが失敗するとさらに例外が送出され、その場合は破綻してしまいます。


59ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(26,311ポイント)   Date: 2008/01/29(火) 00:24   No:13862     
Title: Re:マルチスレッドクラス    
Mutex::create は変です。もう一度見直してください。
また、Mutex クラスもコピーされた場合に破綻します。

Critical クラスもコピー代入演算子で破綻しますが、それ以前に何か違和感があります。


85ポイント を手に入れた。

Name: 組木紙織  ..プログラマー(33,357ポイント)   Date: 2008/01/31(木) 20:49   No:13936     
Title: Re:マルチスレッドクラス    
返信遅くなってすみません。

うえから順番に返答します。

まず変換コンストラクタについてですが、現時点ではまだ何も考えていません。
というより完全に忘れてました。

>コピーコンストラクタを定義していないのは意図通りでしょうか?(なくても問題はなさそうです)

意図的です。

>データメンバ name の初期化時に std::bad_alloc 例外が送出される可能性があることは想定済みでしょうか?
一応std::bad_alloc例外については想定済みです。
何とかしてThreadExceptionに子スレッドでどんな例外が投げられたのかを格納したかったので
メンバにnameを作りました。
例外禁止に出来なければ、nameを削除する予定です。
その場合は親スレッドでどんな例外が投げられたのかが知りようがないのが問題ですが。


>そもそも Thread::throwErrorCode にかなり無理があるように思います。

この無理というのは、Thread::throwErrorCodeが例外を投げること自体が無理なのでしょうか?
「無理」という意味が判断できませんでした。
解説をお願いしたいと思います。

Threadクラスについては欲しい機能を追加しただけで他はまだ触っていないです。
コピーコンストラクタなども考える必要があることは分かっています。



>Critical クラスもコピー代入演算子で破綻しますが、それ以前に何か違和感があります。
コピー代入演算子はprivateにいれて定義してなかったように思いますが。

違和感の理由は多分デストラクタで処理を振り分けているからだろうと思います。
このようにした目的は子スレッドでCritical::unlock()を忘れた場合の時のための
安全策のつもりです。
スマートポインタを介したほうがいいのかなと、思ったのですが
どっちの実装にしたほうが良いのか理由が見つからないので、
ここに関してアドバイスが欲しいと思います。



#来週卒業論文提出なのでこんなことをしている場合ではないような。。。





731ポイント を手に入れた。

Name: Justy  ..ハッカー(171,902ポイント)   Date: 2008/01/31(木) 22:59   No:13943     
Title: Re:マルチスレッドクラス    
 面白そうなので、ちょっとだけ参加します。


・ Criticalクラスのデストラクタで objectCounterが0なら objectを
破棄するようになっていますが、(参照カウンターではないので)
他に共有している objectがいない保証になっていませんが、大丈夫ですか?

・ Criticalクラスの使い方で C++なのに lock() / unlock()を対にして
使わせるのはちょっと・・・。
 デストラクタで unlock()忘れ対策をとっているのは判りますが、
対にするならコンストラクタとデストラクタを使った方が確実かと。

・ 連続して lock()を2回以上コールできてしまいますが、意図したとおりでしょうか?
(その場合、デストラクタによる unlock()忘れが正しく機能しない可能性が)。

・ Threadクラスの run()のローカル変数 resultは pf->t()内で例外が発生した時は
何の値を返しているのでしょうか?


315ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(28,704ポイント)   Date: 2008/02/01(金) 10:22   No:13950     
Title: Re:マルチスレッドクラス    
> >データメンバ name の初期化時に std::bad_alloc 例外が送出される可能性があることは想定済みでしょうか?
> 一応std::bad_alloc例外については想定済みです。

thread.hpp の46行目〜55行目の2つの catch 節の中で、ThreadException の自動オブジェクトを生成しています。
このコンストラクタが std::bad_alloc 例外を送出した場合、pf->t も pf も delete の機会を失い、run から例外がリークして破綻すると思うのですが...

> 何とかしてThreadExceptionに子スレッドでどんな例外が投げられたのかを格納したかったので
> メンバにnameを作りました。
> 例外禁止に出来なければ、nameを削除する予定です。
> その場合は親スレッドでどんな例外が投げられたのかが知りようがないのが問題ですが。

格納する内容が文字列だけなら、run の引数として与えるオブジェクトの中に char 配列のメンバを入れておき、strncpy 等でコピーするほうが安全です。

> >そもそも Thread::throwErrorCode にかなり無理があるように思います。
> この無理というのは、Thread::throwErrorCodeが例外を投げること自体が無理なのでしょうか?
> 「無理」という意味が判断できませんでした。
> 解説をお願いしたいと思います。

一番無理がありそうなのは、クライアントコードが errorFlag を知る方法がなく、とりあえず Thread::throwErrorCode を呼んでみて、例外が送出されるかどうかを調べるしかない点です(見落としがあるかもしれませんが...)。
それに、Thread::throwErrorCode は、その仕組み上、元の例外が発生したスレッドの状態に関わらず、非同期に呼び出せてしまいます。しかも、errorFlag は volatile 修飾されていないので、どんな振る舞いをするか予想し切れません。

> >Critical クラスもコピー代入演算子で破綻しますが、それ以前に何か違和感があります。
> コピー代入演算子はprivateにいれて定義してなかったように思いますが。

すみません、これは見落としていました。


156ポイント を手に入れた。

Name: 組木紙織  ..プログラマー(34,135ポイント)   Date: 2008/02/04(月) 21:09   No:14034     
Title: Re:マルチスレッドクラス    
お二人のコメントをいただいて改良版を作ってみました。
コメントいただいた事は大部分は修正できたと思います。

穴があると自分で認識しているのは、
Justy様の
>連続して lock()を2回以上コールできてしまいますが、意図したとおりでしょうか?

連続してlock()を呼ぶことが出来ないようにすることを実装するのを忘れていたぐらいです。

今回も批評をお願いしたいとおもいます。

個人でしか使うつもりはありませんが、
実用に耐えるようにしたいと思っています。

#出来ればお二方だけでなくていろんな人からの突込みがほしいかな。
#突っ込まれた分だけ勉強になったので。


242ポイント を手に入れた。

Name: Justy  ..ハッカー(172,907ポイント)   Date: 2008/02/05(火) 00:33   No:14037     
Title: Re:マルチスレッドクラス    
 おっと、新しくなってますね。
 まだまだいろいろ問題がありそうですが、実用レベルには
大分近づいてきているような気がします。


・ Threadクラスを生成して、即座に破棄するとメモリーリークします。

    {

Thread thread1(std::bind2nd(std::ptr_fun(&bar2), critical));
} //ここでリーク


 必ず join()しなければならないという仕様であるなら、
デストラクタで必要性を調べ、必要なら join()した方がいいと思います。


・ STRING_SIZE
 C++でこういう定数マクロはちょっと・・・。

 ThreadExceptionクラス内に static const(使えないコンパイラなら enum)で
入れた方が定数がクラスに従属しますし、不用意な(プリプロセッサによる)
置き換えが発生しなくなります。

 あ、あと 19という直値があります。多分、STRING_SIZE-1を狙ったものだとは
思いますが。


・ Criticalクラスのコピーコンストラクタって必要なのでしょうか?
 Criticalクラスの役割を考えると operator=()は無効にしておきながら、
コピーコンストラクタを実装する意味があまりよくわかりませんでした。
(ひょっとして、bar2の引数に実体を渡す為だけ??)

 いっそのこと、コピーコンストラクタもなしにすれば、miniCriticalも不要になって、
Critical/Critical::LockObjectの実装がより簡単になります。
(実体をそのまま持てばいいので、LockObjectへのポインタを保持する必要もなくなるかも・・・)


・ Lockクラスがコピー可能なのは危険なのでは?


・ 前にも書きましたが、Threadクラスの run()のローカル変数 resultは
pf->t()内で例外が発生した時は何の値を返しているのでしょうか?
(不定を返す仕様ならば無視して下さい)



329ポイント を手に入れた。

Name: 組木紙織  ..プログラマー(34,814ポイント)   Date: 2008/02/10(日) 20:54   No:14167     
Title: Re:マルチスレッドクラス    
改良版をさらに改良しました。
今回は結構悩みました。

私にはlock()を2回呼ばないようにできなかったので、
その部分を除いては、今までの指摘されたことすべて改良しました。
(2回呼んでも大丈夫みたいですが)


>・ Threadクラスを生成して、即座に破棄するとメモリーリークします。
今回の実装で一番大変だったのがこの部分です。メモリを管理するスレッドを用意して考えました。



>コピーコンストラクタを実装する意味があまりよくわかりませんでした。
>(ひょっとして、bar2の引数に実体を渡す為だけ??)

ここはご指摘の通り実体を渡すためだけです。


>前にも書きましたが、Threadクラスの run()のローカル変数 resultは
>pf->t()内で例外が発生した時は何の値を返しているのでしょうか?

このresultは他の部分に影響を与えてないように思われるので不定を返しても問題ないような
気がしていたのでそのままにしていました。


今回よくわからなくて実装が途中やめになっている部分があります。
beginthreadex()がエラーを返した時の、errno変数の使い方です。
今考えているのはマルチスレッドなのでエラーを返したことをする確認してerrnoを取得
したとしても、間に別のスレッドで別のエラーをが入っているかも知れないので、
どのようにしてbeginthreadex()のエラーを取得すればよいのかということろです。



#なんとか卒論も提出できてこれで卒業がほぼ確定しました。


211ポイント を手に入れた。

Name: Justy  ..ハッカー(173,640ポイント)   Date: 2008/02/11(月) 03:01   No:14173     
Title: Re:マルチスレッドクラス    
 うーん、イベントを持ってきましたか。
 なんだかちょっと大げさなクラスになってきましたね(^^;


■ デッドロックするかもしれません
 Threadオブジェクトを作ったとき、下記の2つがかち合ってしまい、デッドロックを起こす可能性はありませんか?

  ・ Threadクラスコンストラクタの WaitForSingleObject(this->first,INFINITE);
  ・ Threadクラス template関数 setPack()の WaitForSingleObject(*p_t->second,INFINITE);

(自動リセットオブジェクトにすれば、大丈夫そうですが)


■ ハンドルの解放忘れ
 Threadクラスは正常に動作すると4つのハンドルを作成しますが、うち1つしか解放していません。
 つまり、このクラスを使うたびに3つのハンドルが溜まっていくことになります。


□ const オブジェクト
 ThreadExceptionクラスのコンストラクタや、catch節のオブジェクトなど constを
付けておいた方がいいかと。


□ Critical::LockObjectの miniCritical オブジェクト
 何に使ってます?



>私にはlock()を2回呼ばないようにできなかったので
 とりあえず Criticalクラスの lock()/unlock()を privateに配置して、
Lockクラスを friend指定にすれば、(Lockクラスでしか使われていないので)
現状2回呼ばれる・・・というか lock()/unlock()の呼ばれる回数がおかしくなる
ことは防げますね。

 2回コールを防ぐには lock()が呼ばれたらフラグを trueに、unlock()が呼ばれたら falseに
するようにして、フラグが trueなのに lock()がよばれたら・・・でチェックできるのでは
ないでしょうか。


>今回の実装で一番大変だったのがこの部分です。メモリを管理するスレッドを用意して考えました
 うーん、この為だけにイベント2つにスレッド1つですか。
 ちょっともったいない気もしますね。

 どうせ Threadクラスのデストラクタでスレッドの終了待ちをしなければならないのであれば、
Threadクラスに Pack<F>オブジェクトへのポインタを持つちょっと特殊なスマートポインタ(?)を
持たせて、そのデストラクタを利用してメモリを破棄してもいいような。
(ちょっと特殊なスマートポインタになるのは、Threadクラスのコンストラクタの template引数に
よって中身の Pack<F>の Fが変化するからです)


>このresultは他の部分に影響を与えてないように思われるので
 直接的に影響はないのですが、コンパイラによっては警告が出たりしますので・・・。


>beginthreadex()がエラーを返した時の、errno変数の使い方です。
 たしか、Visual Studioで MTでビルドしているなら、スレッド毎に異なる変数を見に行くはずなので
別のスレッドの値が入ることはなかったかと。
 それ以外だとわかりませんが・・・。


609ポイント を手に入れた。

Name: 組木紙織  ..プログラマー(35,293ポイント)   Date: 2008/02/11(月) 19:48   No:14190     
Title: Re:マルチスレッドクラス    
修正したつもりでしたが、修正できてなかったところをすべて突っ込まれてました。
きちんとコードは確認しておかないと。


>Threadクラスに Pack<F>オブジェクトへのポインタを持つちょっと特殊なスマートポインタ(?)を
>持たせて、そのデストラクタを利用してメモリを破棄してもいいような。

その方法も考えたのですが、実装方法がわからなかったので、上記のようにスレッドで管理しました。
簡単なサンプルコードを提示していただければ助かります。


126ポイント を手に入れた。

Name: Justy  ..ハッカー(174,123ポイント)   Date: 2008/02/11(月) 21:13   No:14199     
Title: Re:マルチスレッドクラス    
 こんなかんじですかね。

 Threadクラスが持つ PackHolderクラスがそれです。


41ポイント を手に入れた。

Name: 組木紙織  ..プログラマー(35,387ポイント)   Date: 2008/02/11(月) 22:13   No:14202     
Title: Re:マルチスレッドクラス    
ありがとうございます。
ざっと見てみました、継承を使うことは思いつかなかったです。
他にも色々と手が入っていたようなので、変更点を確認して、さらに完成を目指していきたいと思います。


55ポイント を手に入れた。

Name: Justy  ..ハッカー(174,763ポイント)   Date: 2008/02/13(水) 00:28   No:14241     
Title: Re:マルチスレッドクラス    
>他にも色々と手が入っていたようなので
 つい気になったところをついでに直してしまいましたが、
ちょっと個人的な意見を。

 Threadのデストラクタでスレッドの終了待ちをしていますが、
これは先の私のコードにしても組木紙織さんのコードにしても
リソース(発生した例外情報)の解放がスレッドが終了しないと出来ない、という観点から
必要な処理だとはおもいますが、現実的にはこれはあまりよろしくないように思えます。

 たとえば

    {

Thread thread1(std::bind2nd(std::ptr_fun(&bar1), &critical));
}


 のようなコードの場合。
 デストラクタでスレッドの終了待ちをしてしまうと、bar1スレッドの内容によっては(無限ループとか)
そのまま処理が止まってしまうのでうまくありません。


 根本的な事を言ってしまいますと、Threadクラスからスレッド内で発生した例外の状況を知る、
ということは本当に必要なことなのでしょうか。

 一見その機能は便利に思えるのですが、ずっと過去にスレッド内で発生した例外が
あるかどうかを取得する程度の意味合いでしかないですし、
(私的には)スレッド内で発生した例外はスレッド内で処理しないとまずいことが多いので、
使いどころが難しい機能となります。

 勿論、そのスレッド内で例外の補足を怠った、或いは失敗したのなら、run()内で
それを補足する必要はありますが、その場合は警告を出して即座に
プログラムを止めてしまってもいいたぐいのエラーではないでしょうか。

 とまぁ、Threadクラスから例外の状況取得という機能がなくなれば、
TThreadのデストラクタでスレッドの終了待ちが必要なくなって、
先のコードでも Threadオブジェクトは即座に消滅しハンドルも破棄するけど、
bar1は走り続ける、というコードになります。

 いかかでしょうか?



 それでもやっぱり後から例外の状況を取得したい、ということであれば
アプローチを変えればできるかと思います。

 一例を挙げるなら例えば、今はユーザースレッドの指定を関数オブジェクトで行っていますが、
純粋仮想関数 run()や、仮想関数 exception()とかを持ったユーザースレッド専用の
基底クラス ThreadRunを作って、それを継承してユーザが独自のクラスを作り、
そのオブジェクトを Threadクラスに与えることで ThreadRunの run()をスレッドで実行するようにする。
 内部で例外を補足したら 仮想関数 exception()を呼び、例外の情報をセットする。

 で、外部からの例外の発生状況の取得はその継承したクラスから取得する、
という流れで一応要望は満たせます。

 或いはまぁ単純にスレッドに指定した関数の引数に例外情報を格納する構造体への参照とかポインタとか
入れてしまうとか。


784ポイント を手に入れた。

Name: 組木紙織  ..プログラマー(38,990ポイント)   Date: 2008/02/14(木) 10:13   No:14291     
Title: Re:マルチスレッドクラス    
>Threadのデストラクタでスレッドの終了待ちをしていますが、...

そういえば子のスレッドを途中で破棄すると、子スレッド中でautoで生成したオブジェクトの
デストラクタが呼ばれることはないんですよね。
ということはThreadのデストラクタで子スレッドの終了待ちをしたほうが安全なのかな。
無限ループだけは気をつけないといけなくなりますが。

ただThreadのデストラクタが子スレッドの終了を待つ時間がもったいないなと思ったので
子スレッドを途中で破棄したかったということがあります。


>勿論、そのスレッド内で例外の補足を怠った、或いは失敗したのなら、run()内で
>それを補足する必要はありますが、その場合は警告を出して即座に
>プログラムを止めてしまってもいいたぐいのエラーではないでしょうか。

そのような考え方もありますか。

一番最初にあげたコンセプトからは少し外れるような気もしますが、プログラム作成者にとっては
その方がエラーがわかりやすくなりますね。
ユーザーに選択権を与えるといった方法で考えていきます。


#大幅な組み直しになりそうな予感。






2倍のポイントを手に入れた! 864ポイント を手に入れた。

Name: Justy  ..ハッカー(175,286ポイント)   Date: 2008/02/14(木) 23:34   No:14304     
Title: Re:マルチスレッドクラス    
>ということはThreadのデストラクタで子スレッドの終了待ちをしたほうが安全なのかな。
>無限ループだけは気をつけないといけなくなりますが。
 うーん、大抵の場合終了待ちした方が安全ですね。
 ただ、明示的に join()すればいいだけの話なので、
デストラクタでした方がいいか、と言われると先の例のようなケースもあるので
そうでもないような。

 まぁ結局は Threadのインスタンスの生存期間 >= スレッドの生存期間で
いいのかどうか、でしょう。


>そういえば子のスレッドを途中で破棄すると、子スレッド中でautoで生成したオブジェクトの
>デストラクタが呼ばれることはないんですよね。
 あー、強制的に破棄すると、環境依存ですが呼ばれないこともありますね。
 明示的にそうするメソッドがあってもいいとは思いますが、デストラクタで
キャンセルしてしまうのはまずそうです。

 スレッド内に(ユーザーフラグによる)キャンセルポイントを作って
キャンセル指示を出した後、join()で待つ、が無難でしょうか。


>>その場合は警告を出して即座に
>>プログラムを止めてしまってもいいたぐいのエラーではないでしょうか。
>そのような考え方もありますか。

 次の C++0xにもスレッドクラスが標準ライブラリに入ることになるらしいのですが、
こちらはスレッド内で例外の補足に失敗すると std::terminate()をコールするみたいです。
(30.2.1.2 thread constructors 5)

ttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2521.pdf



>#大幅な組み直しになりそうな予感。
 がんばってくださ〜い。


523ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(40,556ポイント)   Date: 2008/02/23(土) 01:00   No:14502     
Title: Re:マルチスレッドクラス    
色々とがんばって組み直してみました。
継承を使ったりテンプレート使ったりで難しい。。

まだ全部完成していませんが、全体的な構成の仕方についてコメントが欲しいと思います。


72ポイント を手に入れた。

Name: Justy  ..ハッカー(174,936ポイント)   Date: 2008/02/23(土) 03:56   No:14504     
Title: Re:マルチスレッドクラス    
 なるほど、こうなりましたか。


>全体的な構成の仕方についてコメント

 スレッドを使うのに、実行クラスを作って継承して、くらいまではいいのですが、
ThreadRunHolderにそのクラスの型とデストラクタのポリシーを指定して、
更にそれを Threadのテンプレート引数に、って複雑すぎやしませんか?

 前のようなお手軽感がなくてなってしまったような気がします。


・ デストラクタのポリシークラス
 ThreadNotBreak/ThreadCanBreakはコンストラクタで処理をしていますが、
これならそれぞれのクラスに同じ関数名を持つ静的関数を用意した方が、
いいと思います。
 実質的には変わらないのですが、Threadのデストラクタでオブジェクトを生成して
コールするより、普通に関数コールした方がわかりやすいかな、と。


・ Thread::join()
 キャンセル指示はイベントとかOSの仕組みを利用した方が安全だと思います。


・ ThreadRun/My2
 Threadクラスでの使われ方で、My2のコンストラクタで volatile int*という引数を
強制されてしまっています。
 多少制限があるのは仕方がないのですが、さすがに My2クラスの自由度が
固定されてしまうというのはどうでしょう。


・ このサンプル
 main()の threadオブジェクトは作られて即座に破棄されます。
 その為デストラクタで this->endFlagが trueになり、そのままスレッドの終了待ちを
行うのですが、この段階では Threadクラスの静的関数 run()が実行されていない
可能性があり、その場合 run()が後からよばれ this->endFlagを falseに初期化して
してから、My2の run()が実行されます。

 その場合、スレッドがいつまで経っても終了しなくなります。
 Threadのコンストラクタでは、ちゃんと静的関数 run()が実行されたことを
確認した方がいいと思います。


507ポイント を落としてしまった。

Name: 組木紙織  ..熟練のプログラマー(40,782ポイント)   Date: 2008/02/23(土) 12:15   No:14510     
Title: Re:マルチスレッドクラス    
>前のようなお手軽感がなくてなってしまったような気がします。
やっぱり複雑でしたか。
今回は前回より簡単に使えるようにしてみました。

>Threadクラスでの使われ方で、My2のコンストラクタで volatile int*という引数を 強制されてしまっています。

これは子スレッドで無限ループを作ってデットロックに陥らないようにするために必要な
ことなのでどうしようもないと考えています。

>Thread::join()
>キャンセル指示はイベントとかOSの仕組みを利用した方が安全だと思います。

wait関数はOSの仕組みではないのですか?
どのような意図かよく理解できないので解説が欲しいと思います。


スレッドを途中で破棄するときにCloseHandle()を使わないようにとMSDNにあったので
どの関数を使って破棄をすればよいのかわからないのが今の気になっているところです。
ほかはすべて実装したつもりです。




226ポイント を手に入れた。

Name: Justy  ..ハッカー(175,818ポイント)   Date: 2008/02/23(土) 19:13   No:14511     
Title: Re:マルチスレッドクラス    
>>>Threadクラスでの使われ方で、My2のコンストラクタで
>>>volatile int*という引数を 強制されてしまっています。
これは子スレッドで無限ループを作ってデットロックに陥らないようにするために必要
なことなのでどうしようもないと考えています。
 それはキャンセル指示の為のフラグを Threadクラスと実行しているスレッドと
共有するためだと思いますが、回避する方法はあります(後述)。


>>Thread::join()
>>キャンセル指示はイベントとかOSの仕組みを利用した方が安全だと思います。
wait関数はOSの仕組みではないのですか?
 wait関数というのは WaitForSingleObjectのことですか?
 たしかに OSの仕組みですが、これは同期待ちの方です。

 キャンセル指示自体は endFlagで行っているので、volatileが付いているとはいえ
これをイベント(CreateEvent/SetEvent)で通知した方が同期もとれていいかなぁ、
と思っただけです。
 今回のケースでは実際どっちでもいいのかもしれませんが。

 で、先の回避の方法ですが。
 単純に一方通行の信号(Threadクラスから実行スレッドへのキャンセル)なので、
TLS(Thread Loacl Storage)を使ってイベントハンドルなどを保持し、
参照カウンタでデータの破棄を行うようにすれば一応できます。
 サンプルを添付したので、それを見て頂ければ判るかと思います。


スレッドを途中で破棄するときにCloseHandle()を使わないようにとMSDNに
 それは _beginthreadの話では?
 _beginthreadexなら普通に CloseHandle()でいいと思います。



※添付のサンプルは全く完全ではなくおかしなところも多々あるので、あくまで参考程度に(^~
# 追記(19:59) 露骨にダメなところを修正
# 追記(23:06) やっぱりまだおかしかったので、再修正。
 ついでに例外補足失敗時の挙動を選べるよう修正。


882ポイント を手に入れた。

Name: Justy  ..ハッカー(176,389ポイント)   Date: 2008/02/24(日) 01:06   No:14512     
Title: Re:マルチスレッドクラス    
 さて、新しい方の Threadクラスですが。

・ Threadの特殊化
 Threadクラスが特殊化されたものがデフォになっていますが、
結構妙な使い方です。
    template<typename Run>

class Thread<ThreadRunHolder<Run> >
{
...
};


 1パターンしか特殊化しないのであれば、普通に Threadテンプレートに
してみてはどうでしょうか。


・ 静的関数 run
 これも NullTypeで特殊化されていますが、内容が1カ所くらいしか違わないのであれば
    struct caller_run_void

{
template <typename T>
static void run(ValueType &r, T) { r.run(); }
};
struct caller_run_other
{
template <typename T>
static void run(ValueType &r, T v) { r.run(v); }
};


 のようなクラスを用意して、run<F>の Fが NullTypeだったら、caller_run_voidを、
それ以外なら caller_run_otherの runを使ってコールするようにして
まとめてしまった方がメンテが楽です。

    template <typename T, typename U>

struct IsSameType { enum { Result = false }; };
template <typename T>
struct IsSameType<T, T> { enum { Result = true }; };

template <bool flag, typename T, typename U>
struct SelectType { typedef T Type; };
template <typename T, typename U>
struct SelectType<false, T, U> { typedef U Type; };

typedef SelectType<IsSameType<F, NullType>::Result, caller_run_void, caller_run_other>::Type Caller;
Caller::run(run, *pf.t);



・ 破棄
 破棄の時の挙動を My2などの継承先にもってきていますが、
どうせならポリシークラスにしてしまい、テンプレート引数でしていさせた方が
間違いがない、かと思います。


・ 関数
 以前は普通の関数もスレッドに指定できたと記憶していますが、
以後は関数タイプのものはなし、ということでしょうか?




571ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(41,096ポイント)   Date: 2008/02/24(日) 17:08   No:14519     
Title: Re:マルチスレッドクラス    
サンプル見てみました。色々と複雑なことをしているようで、理解するのに時間がかかりそうです。
実装するのにはさらに時間がかかりそう。


> 以前は普通の関数もスレッドに指定できたと記憶していますが、
>以後は関数タイプのものはなし、ということでしょうか?


関数タイプのものは、継承を使ったクラスタイプよりユーザーが簡単に作れると思いますが、
関数タイプを実装していなかったのは、実装する頭の余裕がなかったというだけです。
クラスタイプのめどがついたら関数タイプを実装しようとかんがえてはいます。


時々ポリシークラスという言葉を使っていますが、この構造って一種のStrategyパターンですよね。
実行時の変更ができなくて、コンパイル時にすべてが決まってしまう。
とちょっと気になりました。


#最初はこんなに複雑になると予想はしてなかったです。


314ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(34,057ポイント)   Date: 2008/02/24(日) 18:11   No:14521     
Title: Re:マルチスレッドクラス    
しばらく見ないうちに、追いきれなくなりましたが...

> 時々ポリシークラスという言葉を使っていますが、この構造って一種のStrategyパターンですよね。

その認識であっていると思いますよ。
「Modern C++ Design」にも、ポリシーが一種の Strategy パターンであることが記されていました。

> 実行時の変更ができなくて、コンパイル時にすべてが決まってしまう。

この例からも分かるように、テンプレートは静的なポリモーフィズムを実現するためのツールとして使えます。
実は、これが Java や C# には真似ができない、C++ の最も強力な機能だったりします。


96ポイント を手に入れた。

Name: Justy  ..ハッカー(177,124ポイント)   Date: 2008/02/25(月) 01:32   No:14524     
Title: Re:マルチスレッドクラス    
>クラスタイプのめどがついたら関数タイプを実装しようとかんがえてはいます。
 なるほど。


>実行時の変更ができなくて、コンパイル時にすべてが決まってしまう。
 たしかにそうですね。
 しかしそれがメリットでもありますので、上手に使えばその方がいいこともあります。


>#最初はこんなに複雑になると予想はしてなかったです。
 いろいろな機能を付けようとすると、多少はそうなりますよね。
 スレッドは意外なところに落とし穴がありますし。

 世の中にはいろんなところに C++で実装したスレッドライブラリがあるので、
いろいろ見てみるといいかもしれません。


CodeProject: A C++ Cross-Platform Thread Class. Free source code and programming help
ttp://www.codeproject.com/KB/threads/thread_class.aspx

CodeProject: Encapsulating Win32 threads in C++. Free source code and programming help
ttp://www.codeproject.com/KB/threads/thread_win32.aspx

CodeProject: A C++ Thread Class. Free source code and programming help
ttp://www.codeproject.com/KB/threads/ThreadClass.aspx

CodeProject: Creating a C++ Thread Class. Free source code and programming help
ttp://www.codeproject.com/KB/threads/threadobject.aspx

 これの翻訳が↓
CodeZine:C++でのスレッドクラスの作成(オブジェクト指向)
ttp://codezine.jp/a/article/aid/1977.aspx?p=1

CodeGuru: Template Thread Library
ttp://www.codeguru.com/cpp/w-p/system/threading/article.php/c5687/

CodeGuru: A Generic C++ Thread Class
ttp://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c3793/

Chapter 15. Boost.Thread
ttp://www.boost.org
  ttp://www.boost.org/doc/html/thread.html

Class Poco::Thread
ttp://pocoproject.org/
  ttp://pocoproject.org/poco/docs/Poco.Thread.html



735ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(42,581ポイント)   Date: 2008/03/02(日) 18:54   No:14632     
Title: Re:マルチスレッドクラス    
Justy様のDate: 2008/02/23(土) 19:13に添付されたコードで一部不明な部分があるので、
質問させてください。
zthread.cppの中にある以下のコードです。

void ThreadDetail::BaseParam::Wait()関数が複数回呼ばれる可能性がないようにも思えるのにかかわらず、
if(started)return;
と、複数回呼ばれる可能性を考慮しているようなので、なぜ複数回呼ばれる可能性を考慮する必要が
あるのか?
ということです。

この関数は親スレッドで使用され、子スレッドの準備が終わるまで、親スレッドを待機させるという目的
で使われています。

void ThreadDetail::BaseParam::Wait()
{
if(started) return;

DWORD result = WaitForSingleObject(start_handle, INFINITE);
if(result == WAIT_OBJECT_0)
{
CloseHandle(start_handle);
start_handle = 0;
started = true;
}
else
throw ThreadLogicException();
}


269ポイント を手に入れた。

Name: Justy  ..ハッカー(178,324ポイント)   Date: 2008/03/02(日) 21:18   No:14633     
Title: Re:マルチスレッドクラス    
>と、複数回呼ばれる可能性を考慮しているようなので、
>なぜ複数回呼ばれる可能性を考慮する必要があるのか?

 特にないですね。
 使われ方からすれば、複数回呼ばれる可能性はありません。

 ただ、BaseParamクラス"単体"で見た時に、一度でも trueを返した後、
呼ばれるとまずいから、そうしたのだと思います(うろ覚え)。


99ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(42,688ポイント)   Date: 2008/03/02(日) 23:23   No:14637     
Title: Re:マルチスレッドクラス    
回答ありがとうございます。

>複数回呼ばれる可能性はない。
ということで私のコードはそれを前提に構築していこうと思います。

ただ、Justy様のサンプルコードは何重にも安全策を施しているようにみえる部分があるので、
安全策を一つだけにせず、何重にも重ねて作っていく必要があるのかなと感じています。



107ポイント を手に入れた。

Name: Justy  ..ハッカー(178,401ポイント)   Date: 2008/03/02(日) 23:48   No:14641     
Title: Re:マルチスレッドクラス    
>安全策を一つだけにせず、何重にも重ねて作っていく必要があるのかなと感じています

 そうですね。
 
 作ってるときは必要ないと思っても他人が使う場合や設計が変更になったりした時に、
そのクラスや関数の設計コンセプトに反した使われ方をする可能性があったりします。
 
 それにあり得ないと思っていても起きてしまうのがプログラムですしね。


77ポイント を手に入れた。



Name: しょう  ..かけだし(1,445ポイント)   Date: 2008/03/02(日) 13:12   No:14621       
Title: 二つの配列の合併について    
問題は

2つの集合配列set0[],set1[]を入力とし、共通および合併の集合演算を施施した結果でset0[]を更新する関数を作成する。
入出力も整備したプログラムをC言語で作成せよ。

というものなんです。共通のほうはできたのですが、合併のほうがひとつしか要素が追加されません。

合併というのはもしset0[1,3,5]、set1[2,3,6]であったときset0[1,3,5,2,6]を出力するものとします。


下のプログラムを作成しましたがどこか間違っていますか?教えてください!!

//====================================================================
// ヘッダ情報
//====================================================================

#include <stdio.h>

//====================================================================
// 定数定義マクロ
//====================================================================

#define LEN 100 // 配列最大長
#define EOA -99999999 // 配列終端の番兵(End of Array)

#define TRUE 1 // 真値
#define FALSE 0 // 偽値

//====================================================================
// データ型定義
//====================================================================

typedef int Data; // 文字列
typedef int Bool; // 真偽値

//====================================================================
// 関数宣言
//====================================================================

void set_input(Data set[], int num);
void set_output(const Data set[]);
void set_normal(Data set[]);
Bool set_elem(const Data set[], Data elem);
//---- 共通演算
void set_common(Data set0[], const Data set1[]);

//---- 合併演算
void set_union(Data set0[], const Data set1[]);

//====================================================================
// メイン関数
//====================================================================

int main(void) {
//---- 宣言
Data set1[LEN], set0[LEN];
int n1, n0;
int s;

//---- 集合set0の要素数と各要素の入力
printf("n0 = ? "); scanf("%d", &n0);
set_input(set0, n0);
set_normal(set0);

//---- 集合set1の要素数と各要素の入力
printf("n1 = ? "); scanf("%d", &n1);
set_input(set1, n1);
set_normal(set1);

//---- 集合演算と出力

printf("1:共通 2:合併\n");
scanf("%d", &s);

switch( s ){
case 1: set_common(set0, set1); // 共通演算
printf("共通 = "); set_output(set0);
break;
case 2: set_union(set0, set1); // 合併演算
printf("合併 = "); set_output(set0);
break;
default: puts("入力エラー"); break;
}

return 0;
}


//====================================================================
// 集合データの入出力
//====================================================================

//--------------------------------------------------------------------
// 配列への入力
//--------------------------------------------------------------------

void set_input(Data set[], int num) {
int k;
for ( k = 0; k < num; k++ ) { scanf("%d", &set[k]); }
set[num] = EOA;
}

//--------------------------------------------------------------------
// 配列からの出力
//--------------------------------------------------------------------

void set_output(const Data set[]) {
int k;
for ( k = 0; set[k] != EOA; k++ ) { printf("%d ", set[k]); }
puts("");
}



//--------------------------------------------------------------------
// 共通演算
//--------------------------------------------------------------------

void set_common(Data set0[], const Data set1[]) {
int k1, k0 = 0;
for ( k1 = 0; set1[k1] != EOA; k1++ ) {
if ( set_elem(set0, set1[k1]) ) { set0[k0++] = set1[k1]; }
}
set0[k0] = EOA;
}

//--------------------------------------------------------------------
// 合併演算
//--------------------------------------------------------------------

void set_union(Data set0[], const Data set1[] ) {
int k1, k2;
int k0 = 0;
for ( k1 = 0; set0[k1] != EOA; k1++ ) { k0++; }
//---- s1の要素を走査し、s0に属さない要素のみを新たに追加する
for ( k1 = 0; set1[k1] != EOA; k1++ ) {
if ( ! set_elem(set0, set1[k1]) ) { set0[k0++] = set1[k1]; }
}
set0[k0] = EOA;
}

//--------------------------------------------------------------------
// 集合の正規化
//--------------------------------------------------------------------

void set_normal(Data set[]) {
int k1, k2, k0 = 0;
Bool check;
// sの要素に対し、正規化した部分と照合し、重複していない要素のみを追加
for ( k1 = 0; set[k1] != EOA; k1++ ) {
check = TRUE;
for ( k2 = 0; k2 < k0; k2++ ) {
if ( set[k1] == set[k2] ) { check = FALSE; break; }
}
if ( check == TRUE ) { set[k0++] = set[k1]; }
}
set[k0] = EOA;
}

//--------------------------------------------------------------------
// 所属性
//--------------------------------------------------------------------

Bool set_elem(const Data set[], Data elem) {
int k;
for ( k = 0; set[k] != EOA; k++ ) {
if ( set[k] == elem ) { return TRUE; }
}
return FALSE;
}


1,416ポイント を手に入れた。


Name: box  ..ハッカー(107,920ポイント)   Date: 2008/03/02(日) 13:45   No:14622     
Title: Re:二つの配列の合併について    

適宜printfを入れるなどして、配列の内容がどうなっているかを
確認すれば、わかると思います。

set_union関数の

> if (!set_elem(set0, set1[k1])) {
> set0[k0++] = set1[k1];
> }

ここで、set0[]のEOAを上書きしている点に問題がありそうです。


136ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(42,145ポイント)   Date: 2008/03/02(日) 15:37   No:14624     
Title: Re:二つの配列の合併について    
以前も同じような質問がありました。

ttp://www.play21.jp/board/formz.cgi?action=res&resno=13993&page=&lognum=45&id=dixq&rln=14310


43ポイント を手に入れた。

Name: しょう  ..かけだし(1,546ポイント)   Date: 2008/03/02(日) 16:07   No:14625     
Title: Re:二つの配列の合併について    
boxさん

set0[k0]=EOAを消してみましたが、ごちゃごちゃしたものが出てきて変になってしまいます…
そこじゃなくて
> if (!set_elem(set0, set1[k1])) {
> set0[k0++] = set1[k1];
> }
をどーにかしないといけないんですか?


組木紙織さん

そのページを見ましたが、解決策が載っていなかったので……


101ポイント を手に入れた。

Name: box  ..ハッカー(107,977ポイント)   Date: 2008/03/02(日) 16:31   No:14626     
Title: Re:二つの配列の合併について    
>set0[k0]=EOAを消してみました

配列set0[]に終わりの印を付けることは必要です。
付けるタイミングが正しくないのではないか、ということです。


57ポイント を手に入れた。

Name: しょう  ..かけだし(1,566ポイント)   Date: 2008/03/02(日) 16:35   No:14627 解決!     
Title: Re:二つの配列の合併について    
なるほど!!
できました!!
ありがとうございます♪


20ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(42,312ポイント)   Date: 2008/03/02(日) 16:50   No:14628     
Title: Re:二つの配列の合併について    
boxさんのに一言付け加えるとすると、
set0[]はどのような変化をしているのか?
というところです。


私が過去ログを提示した理由は今問題にしている部分が解決できたとしても、
set0[1,3,5]、set1[2,3,6]であったときに合併演算をすると、set0[1,3,5,2,6]
と出力されるようになっており、正規化していない部分が問題かなと思ったので
過去ログにあげたソースを利用すると、出力されるのがset0[1,2,3,5,6]
となり正規化した結果で、出て来るので後が使いやすいと思ったからです。

仕様に正規化してない結果を返すようにしているようなので余計な御世話だったようです。
混乱させてしまったようですみません。


167ポイント を手に入れた。

Name: しょ  ..ぴよぴよ(0ポイント)   Date: 2008/03/02(日) 17:11   No:14629 解決!     
Title: Re:二つの配列の合併について    
組木紙織さん

いや、そこまで深く考えてませんでしたので、わざわざありがとうございます!




Name: ナメ  ..ぴよぴよ(664ポイント)   Date: 2008/02/24(日) 18:05   No:14520       
Title: Rainboard    
ぺありんさんの作ったRainbow Channel(CGI配布掲示板)をTOK2のPROでアップして使いたいんですが、何度やっても失敗ばかりで、もうわけがわかりません。
掲示板CGIを設置できる方、ぜひ助けてください。

Rainbow ChannelというCGIで無料配布されている掲示板があります。
それを、TOK2のPROでアップロードして使いたいんですが、とってもむずかしくてわかりません・・・。
どなたか、ぜひとも教えてください。

できればFFFTPを使ってアップロードする方法をお願いいたします・・・・。
まず、TOK2のhttp://tok2.com/cgi.htmlでパーミッション情報が載ってるんですが
乗ってないのもあって、止まってしまいます。・・・

FFFTPでサーバに接続したあとからじっくり教えていただける方、お願いいたします。
掲示板のテーマとかがあるらしいですが、とりあえずは標準のもので掲示板が出来上がったら詳しく説明をいただき
編集したいと思っております。

HPの開設日が3月1日なので、急いでいます。だれか様、おねがいいたします

Perlは#!/usr/bin/perlであってると思います。ただ、無料版の方なのでPROはどうなのかわかりませんが・・・・。

本当にクソバカなので、詳しく、詳しく解説をお願いします・・・。

まず、ディレクトリ、ファイルのパーミッション情報を記載していただいて
CGIファイル、PLファイルなどのパーミッションとPMなども・・・。
かなり、いろいろあります。
そして、GIFやJSなどもおねがいします。(というか、すべてお願いします。)


Rainbow Channelはダウンロードされた方が早いとおもいますのでダウンロード先を載せておきます
http://rainboard.net/download.uhtml

皆様の知恵をお貸しください・・・・。よろしくお願いします。
本当に、おねがいします。


664ポイント を手に入れた。


Name: ナメ  ..ぴよぴよ(669ポイント)   Date: 2008/03/02(日) 11:01   No:14620 解決!     
Title: Re:Rainboard    
自己解決しました。

5ポイント を手に入れた。



Name: taku.net  ..入門者(2,898ポイント)   Date: 2008/03/01(土) 01:14   No:14596       
Title: ポインタについて質問    
書籍「シューティングゲームプログラミング」のタスクシステムについてのコードなのですが
判読できないコードがあったので意味を教えていただきたいのですが・・・

// タスクの構造体
struct TASK {

// 処理関数へのポインタ
void (*Func)(TASK* task);

// 前後のタスクへのポインタ
TASK* Prev;
TASK* Next;

// ワークエリア
char Work[WORK_SIZE];
};

ポインタについて、基本的なことは理解しているのですが、
自分なりに調べても「TASK* XXX;」の部分が何をしているのか分からなかったので質問させていただきました。
よろしくお願いしますm(__)m


287ポイント を落としてしまった。


Name: 組木紙織  ..熟練のプログラマー(42,102ポイント)   Date: 2008/03/01(土) 07:15   No:14597     
Title: Re:ポインタについて質問    
"リンクリスト"って知っていますか?
構造体同士ををポインタでつないだものです。
その部分は、前のTASK構造体へのポインタと後ろのTASK構造体へのポインタを指しています。


87ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(524,462ポイント)   Date: 2008/03/02(日) 06:07   No:14619     
Title: Re:ポインタについて質問    
http://www.google.co.jp/search?hl=ja&q=%E5%8F%8C%E6%96%B9%E5%90%91%E3%83%AA%E3%82%B9%E3%83%88&lr=

この辺でぐぐってはどうでしょうか。


59ポイント を手に入れた。



Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,971ポイント)   Date: 2008/03/01(土) 17:44   No:14614       
Title: iostreamとwchar_t    
iostreamを使ってワイド文字を出力しようとしたのですが、なぜかその文字の文字コードが出力されてしまいます。
ロケールの設定はしていますが、アルファベットですら文字コードになってしまいます。しかし、typeidによって確認した結果、wchar_t型で間違いはないようです。
環境はWinXP+VC2005アカデミック版です。お願いします。

#include<iostream>
#include<locale>
#include<typeinfo>
using namespace std;

int main()
{
setlocale(LC_ALL,"");
cout<<L"あ,"<<L'あ'<<endl;//あ,あと表示されるはず
cout<<typeid(L'あ').name()<<endl;//とりあえず型を確認しておく
return 0;
}



207ポイント を手に入れた。


Name: tkmakwins15 [URL]  ..熟練のプログラマー(59,020ポイント)   Date: 2008/03/01(土) 17:49   No:14615     
Title: Re:iostreamとwchar_t    
追加です。

wchar_t型の文字列を渡すと文字コードどころか文字列へのアドレスが出力されるようです。

その他、wstringに代入してからcoutに渡すと、<<演算子がwstringクラスに対して定義されていないというエラーがでます。
どういうことでしょうか?


49ポイント を手に入れた。

Name: Blue  ..初心者(5,980ポイント)   Date: 2008/03/01(土) 18:46   No:14616     
Title: Re:iostreamとwchar_t    
wcoutを使ってください。

std::wcout.imbue(std::locale("japanese"));

の記述も忘れずに。


38ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(35,177ポイント)   Date: 2008/03/01(土) 19:27   No:14617     
Title: Re:iostreamとwchar_t    
std::basic_string クラステンプレートの出力は、
template <class charT, class traits, class Allocator>

basic_ostream<chaT, traits>& operator<<(basic_ostream<charT, traits>&, const basic_string<chaT, traits, Allocator>&);


のようになっています。
そのため、charT が異なる文字列とストリームの組み合わせでは使うことができません。
これを解決するには、std::wcout を使うのが筋ですが、std::cout に対して出力したいこともありますよね。
そんな場合は、手前味噌ですが、下記のページに記述しているコードを使うとよいでしょう。

http://www.kijineko.co.jp/tech/cpptempls/original/io#103.3

↑は、const wchar_t*の出力に関するサンプルですが、const std::wsring& に応用するのも簡単にできるはずです。



310ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(59,040ポイント)   Date: 2008/03/01(土) 23:13   No:14618     
Title: Re:iostreamとwchar_t    
Blueさん、たかぎさん、ありがとうございます。

ありがとうございます。wcoutにすればいいのですね。


20ポイント を手に入れた。



Name: ステル  ..ぴよぴよ(101ポイント)   Date: 2008/03/01(土) 16:20   No:14609       
Title: 超初歩的な質問なのですが    
Visual C++ 2005 Express Editionを使用しているのですが
下記のプログラムをコマンドラインから
プログラム名 xxx yyy
と実行した所、xxxと表示して欲しかったのですが
xとしか表示されませんでした
初歩的過ぎるのが調べても分かりませんでした
どなたか教えて頂けないでしょうか
お願いします。

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
printf("%s", argv[1]);
return 0;
}


101ポイント を手に入れた。


Name: たかぎ [URL]  ..プログラマー(34,867ポイント)   Date: 2008/03/01(土) 17:22   No:14610     
Title: Re:超初歩的な質問なのですが    
Unicode版になっていませんか?
その場合、
printf("%s", argv[1]); 



ではなく、
printf("%ls", argv[1]);



とする必要があるかと思います。


102ポイント を手に入れた。

Name: Justy  ..ハッカー(178,225ポイント)   Date: 2008/03/01(土) 17:28   No:14611     
Title: Re:超初歩的な質問なのですが    
 アプリケーションの起動引数は間にスペースがあると、別の文字列と見なされ
別の arg[n]に格納されます。

 従って xxx yyyとしたときの yyyは argv[2]に格納されていますので
printfの "%s"を "%s%s"として、引数にargv[2]も加えると
出力されます。


 或いは引数を xxx yyyではなく、"xxx yyy"のようにダブルクォーテーションで
囲うと1つの文字列と見なしますので、argv[1]に全て格納されます。



 それと文字列に _TCHAR*型を使っているのであれば
printfより _tprintf()の方がいいのではないでしょうか。

_tprintf(_TEXT("%s"), argv[1]); 



210ポイント を手に入れた。

Name: ステル  ..ぴよぴよ(183ポイント)   Date: 2008/03/01(土) 17:34   No:14612 解決!     
Title: Re:超初歩的な質問なのですが    
回答ありがとうございます。

%lsとした所、意図した通りに表示する事が出来ました。

Unicodeの問題に出会ったことが無かったので
さっぱり分からなかった初心者なのですが

本当にありがとうございました。


82ポイント を手に入れた。

Name: ステル  ..ぴよぴよ(224ポイント)   Date: 2008/03/01(土) 17:36   No:14613     
Title: Re:超初歩的な質問なのですが    
神さんもありがとうございました。

型をより意識して今後は取り組みたいと思います。


41ポイント を手に入れた。



Name: 特に  ..ぴよぴよ(171ポイント)   Date: 2008/03/01(土) 11:51   No:14600       
Title: BCCを使っているのですが・・・    
このプログラムが正常に動作しません。
メイクはしっかりできているのですが・・・。
#include "DxLib.h"

// プログラムは WinMain から始まります
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1 ; // エラーが起きたら直ちに終了
}

DrawPixel( 320 , 240 , 0xffff ) ; // 点を打つ

WaitKey() ; // キー入力待ち

DxLib_End() ; // DXライブラリ使用の終了処理

return 0 ; // ソフトの終了
}

点が表示されません。どうしたら良いのでしょうか?


171ポイント を手に入れた。


Name: box  ..ハッカー(107,784ポイント)   Date: 2008/03/01(土) 14:30   No:14602     
Title: Re:BCCを使っているのですが・・・    
1ドットだけなので視認しづらい状況である、
ということはないですか?

座標を変えて、もっとたくさんの点を表示してみたら、
どうなるでしょうか?


50ポイント を手に入れた。

Name: 特に  ..ぴよぴよ(130ポイント)   Date: 2008/03/01(土) 15:15   No:14603     
Title: Re:BCCを使っているのですが・・・    
二つ表示したら1つ出て、3つ表示したら2つと、入力した点の数−1の数だけ表示されるようです。

何が原因でしょうか


41ポイント を落としてしまった。

Name: Justy  ..ハッカー(177,773ポイント)   Date: 2008/03/01(土) 15:19   No:14604     
Title: Re:BCCを使っているのですが・・・    
 試しに、ScreenFlip()を WaitKey()の前に入れてみて下さい。


17ポイント を手に入れた。

Name: 特に  ..ぴよぴよ(156ポイント)   Date: 2008/03/01(土) 15:27   No:14605     
Title: Re:BCCを使っているのですが・・・    
ScreenFlip()入れてみましたが駄目でした。

画像でも同じく2つ入れると表示されます


26ポイント を手に入れた。

Name: Justy  ..ハッカー(177,874ポイント)   Date: 2008/03/01(土) 15:38   No:14606     
Title: Re:BCCを使っているのですが・・・    
 となると、使っているライブラリのバージョン、PCの環境一通り、
出力されたログなど、判る限りの環境情報などがわからないとなんともいえませんが。

 ダメもとで、SetUseDirectDrawFlag(FALSE);を DxLib_Init()の前に入れたらどうなりますか?


101ポイント を手に入れた。

Name: 特に  ..ぴよぴよ(156ポイント)   Date: 2008/03/01(土) 15:47   No:14607     
Title: Re:BCCを使っているのですが・・・    
おおっ!
映りました!ありがとうございます!

で、これからもこの命令を入れないとまずいですかね?


Name: Justy  ..ハッカー(178,015ポイント)   Date: 2008/03/01(土) 16:01   No:14608     
Title: Re:BCCを使っているのですが・・・    
>で、これからもこの命令を入れないとまずいですかね?
 そのPCで動かす場合は、そういうことになりますね。


 ただ、この命令はハードウェア的な力を借りずにソフトウェアで描画しようとするので
描画パフォーマンスが落ちます。

 今後も本格的に何か作ろうと思ってらっしゃるのでしたら、環境的なんとか
した方がいいのかもしれません。


141ポイント を手に入れた。



Name: シュバ  ..かけだし(2,438ポイント)   Date: 2008/02/29(金) 02:22   No:14577       
Title: 回転処理と削除アニメーションについて    
以前、連鎖処理について質問させて頂いた者です。

たびたび申し訳ありませんが2点質問をさせて頂きたいと思います。

今回は回転処理と削除アニメーションについてです。

回転処理の方がflagで管理しており、時計回りに回転すると言う形にしてみたのですが回転した後、フィールドに固定する際の処理に問題が発生している状況です。ブロックの固定はメイン関数の方で処理しているのですが移動用の関数内でブロックの固定処理をした方が良いのでしょうか?

削除アニメーションに関しまして、αブレンドを使って4つ以上並んだ画像を薄くして実際に削除処理に移るという形をとりたいと考えているのですが、この際別関数を作り制御した方が良いのでしょうか?

ソースコードなのですが、何分長くなってしまい掲示板の文字数をオーバーしてしまうので添付ファイルという形をとらせて頂きました。

どうか、宜しくお願い致します。


278ポイント を手に入れた。


Name: シュバ  ..入門者(2,502ポイント)   Date: 2008/02/29(金) 06:08   No:14580     
Title: Re:回転処理と削除アニメーションについて    
環境を書くのを忘れてしまいました。

コンパイラ:VC++2008

ライブラリがDxLibの方を使わせて頂いております。


64ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(77,853ポイント)   Date: 2008/02/29(金) 19:06   No:14587     
Title: Re:回転処理と削除アニメーションについて    
私だったら…ですが、落ちてくるブロック用の構造体かクラスを用意します。


struct PIECE
{
int color[3][3];
int x;
int y;
};



例えばこんな感じですね。
で、ブロックが消える前に一旦その『これから消えるブロックです』という情報を保持しておきたいならば…



struct FIELD
{
int color[FIELD_MAX_Y][FIELD_MAX_X]; // ブロックの色
int vanish[FIELD_MAX_Y][FIELD_MAX_X]; // 消去判定フラグ(普段は0で、1の時に消える)
};


こんな風にフィールド上の1マス1マスに消去フラグを持たせると処理が楽ではないでしょう?
消える箇所を検索して、4つ以上繋がっている箇所の消去フラグを1にして、次に消去フラグが1の箇所だけ表示を薄くして、実際に消去する…みたいな流れですね。


277ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(77,949ポイント)   Date: 2008/02/29(金) 22:23   No:14591     
Title: Re:回転処理と削除アニメーションについて    
ためしにメイン関数以外の部分の実装をしてみました。メイン関数の実装はお任せします(他力本願)
当然ながら動作は未確認ですが、多分大丈夫じゃないかな?(^_^;)

これらの関数を並べていけば、とりあえずはぷよぷよの動きになるんじゃないかと思います。

※クラスを使わずに書くのは久しぶりだったので、妙に気をつかってしまいました(苦笑)


96ポイント を手に入れた。

Name: シュバ  ..入門者(2,570ポイント)   Date: 2008/03/01(土) 00:38   No:14595     
Title: Re:回転処理と削除アニメーションについて    
バグさん、ありがとうございます!

頂いたサンプルソースのmain関数を作り、参考にさせて頂きながら自分なりのソースコードを作っていこうと思います。

何から何まで本当にありがとうございました!


68ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(78,006ポイント)   Date: 2008/03/01(土) 08:50   No:14599     
Title: Re:回転処理と削除アニメーションについて    
あ、1つ実装を忘れている関数がありました(^_^;)
下記の関数を追加しておいてください。PIECE構造体の情報をFIELD構造体へセットする関数です。


/* PIECE情報をFIELDにセットする */
int PieceToField(PIECE* pPiece, FIELD* pField)
{
int i, j;

/* PIECEとFIELDの重なり判定を行う */
if (PieceCollision(pPiece, pField) == 0)
{
/* 重なっている箇所が有る場合は0を返す */
return 0;
}

for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
/* 空白の箇所は何もしない */
if (pPiece->Color[i][j] == 0)
{
continue;
}

/* FIELDへPIECE情報をコピーする */
pField->Color[pPiece->X + i][pPiece->Y + j] = pPiece->Color[i][j];
}
}

/* セットに成功したので1を返す */
return 1;
}


57ポイント を手に入れた。

Name: シュバ  ..入門者(2,598ポイント)   Date: 2008/03/01(土) 12:32   No:14601 解決!     
Title: Re:回転処理と削除アニメーションについて    
関数の方、追加いたしました。

何から何までありがとうございました!


28ポイント を手に入れた。



Name: まきんこ☆  ..ぴよぴよ(358ポイント)   Date: 2008/02/29(金) 13:35   No:14582       
Title: ゲームの終了のさせかたについて。    
すいませんDXライブラリで作成されたウインドウについての質問です。ウィンドウモードで起動させたときに、右上にXのアイコンが出てきますよね?
そのXによって終了させたときに、深刻なエラーとなります。(プログラムが内部的に終了していない)
Xを押して終了する方法などはあるんでしょうか?
もし、Xが押されたら、などの処理の方法がありましたら教えてください、お願いします。


173ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(524,403ポイント)   Date: 2008/02/29(金) 13:38   No:14583     
Title: Re:ゲームの終了のさせかたについて。    
http://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=view&no=658

この辺でしょうか?


11ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,764ポイント)   Date: 2008/03/01(土) 08:25   No:14598     
Title: Re:ゲームの終了のさせかたについて。    
Dxライブラリを使っているということは、While(ProcessMessage()!=-1)というループをしていると思います。
×が押されると、このループを抜ける事になりますから、そこでDxLib_End()関数を呼び出して、WinMainをreturn 0で終了する。
もしくは、先にstdlib.hをインクルードしておいて、exit(0);を呼び出して終了するかのどちらかでいいと思います。


98ポイント を手に入れた。



Name: kz  ..ぴよぴよ(80ポイント)   Date: 2008/02/29(金) 18:24   No:14585       
Title: ヘッダでのマクロの定義の書き換えって関数内でできますか?    
前に一度配布の方法でお世話になりましたkzです。前件は本当にありがとうございました^^
今回はヘッダで宣言しているマクロを関数で書き換えたいのですが、どうもうまくいきません。
ヘッダの定義はこんな感じです。

#define UP KEY_INPUT_E
#define DOWN KEY_INPUT_D
#define LEFT KEY_INPUT_S
#define RIGHT KEY_INPUT_F
#define ENTER KEY_INPUT_L
#define BACK KEY_INPUT_K

これをcommand_fload関数で書き換えます。
command_fload()
int FP;
char botan_read[256],temp[256];
FP=FileRead_open("./txt/ボタン構成.ini");
FileRead_gets(botan_read,256,FP);
FileRead_gets(botan_read,256,FP);

sscanf(botan_read,"%s",temp);
#define UP botan_read

こんな感じです。
一応関数内では定義が変わってるんですが、この関数を抜けると元のマクロの定義に戻ってしまいます。
これをほかの関数でも変わるようにしたいのですがどうすればいいでしょうか??


80ポイント を手に入れた。


Name: GPGA  ..熟練のプログラマー(44,243ポイント)   Date: 2008/02/29(金) 18:43   No:14586     
Title: Re:ヘッダでのマクロの定義の書き換えって関数内でできますか?    
キー配置を設定してあるテキストファイルを読み込み
その設定でキー配置を変えるようにしているみたいですが
このような可変的なものですよね?

マクロは基本的に定数を扱うものですから、可変的なことはできません。
変数を使いましょう。

>この関数を抜けると元のマクロの定義に戻ってしまいます。
これは、正確にはマクロ定義の位置から翻訳単位の終端もしくは
#undefが定義されるまでに効力があるので、別の翻訳単位や
マクロ定義より上にあるものが置き換えられることはありません。


126ポイント を手に入れた。

Name: kz  ..ぴよぴよ(136ポイント)   Date: 2008/02/29(金) 20:02   No:14588 解決!     
Title: Re:ヘッダでのマクロの定義の書き換えって関数内でできますか?    
わかりました、変数で設定するようにします。
ご返答ありがとうございました^^


35ポイント を手に入れた。



Name: てむてむ  ..ぴよぴよ(246ポイント)   Date: 2008/02/29(金) 04:34   No:14579       
Title: ご教授下さい><    
自分はC言語 初心者でこれから本格的に始めたいと思っています。

質問なんですが、

char c[2]= {'a','b'};

printf( "%c\n", c[0] );

というプログラムなら、配列に格納された一つ目の文字"a"が画面に表示されると思います。

同様に、

char c[2]= {'あ','い'};

printf( "%c\n", c[0] );

とした場合は、日本語文字がchar型には収まりきらず、一つ目の要素が画面に表示できないと思うんですけど


一つ目の要素のみを取り出す方法はどのような方法があるのでしょうか?


超初心者の質問ですみません。どなたかご教授下さい><


246ポイント を手に入れた。


Name: てむてむ  ..ぴよぴよ(341ポイント)   Date: 2008/02/29(金) 06:20   No:14581     
Title: Re:ご教授下さい><    
すみません 自己解決しました;;

wchar_tなる型を使えばよかったんですね☆


wchar_t ct[2] = L"あい";

setlocale(LC_ALL, "japanese");

wprintf( L"[%c]\n ", ct[0] );

上の様に変更した所うまくいきました♪



95ポイント を手に入れた。



Name: 管理人 [URL]  ..伝説のハッカー(523,876ポイント)   Date: 2008/02/22(金) 02:27   No:14465       
Title: 雑談版    
2月下旬に公開予定と言っていた四聖龍神録について、
毎日用事をしていない時は四六時中作っているのですが、2月中微妙な状態ではあります(_ _|||)
世間の大学生は春休みだというのに、就活と学会が重なってテンテコマイな忙しさです;
期限は頑張って守ろうと思いますが、
これだけ時間かけて作ったゲームも初めてで、バグチェックにも時間がかかりそうでひやひやしてます;

そして就職活動の為に全国あちこちいったりしています。
もし新幹線の中で、ノーパソで龍神録作ってる人がいたら私なので、気軽に声をおかけ下さい(w

完成したら徐々にゲームプログラミングの館と、本末転倒コードでいっぱいなシューティングゲームの館を作り変えていこうと思います。

・・・まずい、SPI試験の勉強よりこっちを優先してしまいそうだ〜・・・。


49ポイント を手に入れた。


Name: クロカモ  ..入門者(4,755ポイント)   Date: 2008/02/22(金) 09:51   No:14471     
Title: Re:雑談版    
 世間の大学生は春休みみたいですねぇ…残念ながらクロカモはまだ学校にのんびりと通ってます。
 一応クロカモは、卒業も就職も決定してますけど…色々不安は大量にあります。

 新幹線滅多に乗りませんが…もし乗ったときに見かけたら声かけさせていただきますw
 SPI試験よりプログラミング優先ですかwが…頑張ってください!


137ポイント を手に入れた。

Name:  ..プログラマー(29,162ポイント)   Date: 2008/02/22(金) 10:51   No:14474     
Title: Re:雑談版    
>・・・まずい、SPI試験の勉強よりこっちを優先してしまいそうだ〜・・・。
・・・え?
SPIの方をやらないとじゃないですか!?
もし、落ちたりなんかしたら(ないと思いますが)、とても気まずい状況になってしまいそうです・・・。

新幹線は、余程じゃないと乗れませんが…もし乗ったら、ノーパソ広げている人に注意してみますw

色々と頑張って、体調管理を忘れないで頑張ってくださいね!!!!!!!!!!!!!!!!


164ポイント を手に入れた。

Name: 管理人  ..伝説のハッカー(524,233ポイント)   Date: 2008/02/23(土) 04:17   No:14506     
Title: Re:雑談版    
う〜ネットに繋がらないってホント不便だなぁ‥。
携帯でプログラムコードかくほどだるいものはないと感じている今日このごろです。

お返事はまた日を改めて‥。

今月のパケ代が大変な事になってましたorz


81ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,054ポイント)   Date: 2008/02/23(土) 11:09   No:14509     
Title: Re:雑談版    
今公立入試に向けて再度勉強中です。高校に入るまではゆっくりとHPの更新もできないですね。

龍神録楽しみです。(うーん、管理人さん作のゲーム、弟もやっていますね。)
体験版のクリアーさっさとしてしたいなぁ。


77ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(524,439ポイント)   Date: 2008/02/24(日) 14:53   No:14518     
Title: Re:雑談版    
明後日辺り、身内でテストバージョンリリースし、完成版バージョンを今月中にリリースする予定でいます。
バグがでず、予定通りにいけばいいですが・・。
約束の予定日守れるようにがんばります。

>クロカモさん
私も来年から社会人の仲間入りします。早く就職して色々仕事してみたい気がしますが、確かに色々と不安もありますね^^;
で、新幹線の中で話しかけられました。
ぜんっっぜん関係ないおっさんにですがw
私の指定席に「まぁいいじゃないか」とかいいながら座る大柄なおっさんでしたw

>雷さん
やらないといけないことは後にするタイプなので(ォィ
がんばりますっ!!

>tkさん
いや〜大変ですね〜。国立の方がずいぶん早くあるんですね。
体験版はやらないほうがいいですw
ネットにつながるものならさっさとあのページ削除したい気持ちでいっぱいです^^;
完成版の完成にむけてがんばりますっ!


206ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(41,149ポイント)   Date: 2008/02/24(日) 20:10   No:14522     
Title: Re:雑談版    
雑談はここでいいんですよね。

ふと気になったのですが、
タイトルのところのコード、字が小さくて読めないのですが、
Cで"maigo"と表示させるコードですか?
画像だから拡大してもぼやけてよくわからない。


53ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,448ポイント)   Date: 2008/02/24(日) 21:44   No:14523     
Title: Re:雑談版    
>いや〜大変ですね〜。国立の方がずいぶん早くあるんですね。

うーん、私立と同じ日でして、結局併願ができずという状況ですね。


62ポイント を落としてしまった。

Name: 管理人 [URL]  ..伝説のハッカー(524,465ポイント)   Date: 2008/02/25(月) 12:23   No:14525     
Title: Re:雑談版    
>組木紙織さん
あはは、其の通りです。
C言語がよくわからなくて途方に暮れた迷子の人が来る掲示板と言う意味ですw
画像は更新するたびにかわりますし、別に深い意味無いんですけどねw

>tkさん
併願出来ないのは痛いですね。
第一希望と第二希望の企業の面接と重なったらなきそう・・。


26ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,551ポイント)   Date: 2008/02/25(月) 20:39   No:14526     
Title: Re:雑談版    
という訳で4月から大学入試を念頭に入れて勉強するようにします。

体験版、やらないほうがいいってどういう意味でしょうか?
やってみたところ別にそんな問題点が見当たるようなことはないようですけど…

高校入試終わったら.NETのプログラミングをやろうかな…。なんて考えていますが、いいのでしょうか?


103ポイント を手に入れた。

Name:  ..プログラマー(28,900ポイント)   Date: 2008/02/26(火) 00:37   No:14527     
Title: Re:雑談版    
>という訳で4月から大学入試を念頭に入れて勉強するようにします。
すご!?
僕はわかっていても、行動できませんでした!!

>高校入試終わったら.NETのプログラミングをやろうかな…。なんて考えていますが、いいのでしょうか?
WindowsAPIの事なのかな・・・(無知ですいませんorz
だったら、大丈夫なんじゃないかな?(超無責任
楽しめればそれで良いと思ってるので・・・www


140ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,649ポイント)   Date: 2008/02/27(水) 04:47   No:14536     
Title: Re:雑談版    
>WindowsAPIの事なのかな

ちょっと違うような…
ってだいぶ違うか…。でも楽しめればいいのかな…。将来プログラマになる予定は今のところないですから…

将来的に.NETをやっておいてもたぶん損はないと思うので、少し本格的にやっていこうかと。


98ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(524,630ポイント)   Date: 2008/02/27(水) 10:29   No:14537     
Title: Re:雑談版    
大学入試の勉強なんて高校3年になるまでやってませんでしたよw
と言ってもまぁ高校は普段の勉強が大学の受験勉強みたいなもんですしねぇ。
私は毎日テニス三昧だったので普段の勉強もおろそかでしたけど^^;

昨日四聖龍神録のベータ版を身内で公開しました。
バグ報告などを受けて色々バグを直し、正式版を近々公開しようと思いますm(_ _)m


165ポイント を手に入れた。

Name: クロカモ  ..入門者(4,798ポイント)   Date: 2008/02/27(水) 16:05   No:14545     
Title: Re:雑談版    
 おぉ〜ついにデバグの段階に入りましたかぁ。
 プレイできるのを楽しみに待ってますよぉ。


43ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,666ポイント)   Date: 2008/02/28(木) 19:28   No:14575     
Title: Re:雑談版    
正式版がもうそろそろ公開されるのですね。それは楽しみです。

17ポイント を手に入れた。

Name: kura  ..ぴよぴよ(20ポイント)   Date: 2008/02/29(金) 02:51   No:14578     
Title: Re:雑談版    
沢山期待してます。
とっても楽しみです。


20ポイント を手に入れた。



Name: 赤羽  ..ぴよぴよ(387ポイント)   Date: 2008/02/27(水) 22:15   No:14557       
Title: オリジナルのパズルゲーム    
学校で配布してもらったC++のライブラリで
自分のゲームを作っていてわからないところがあるので
質問させていただきました。
C++は独学ですので直したほうがいい点が大量にあると思います。
そこも教えていただけますと助かります。

添付したソースはゲーム画面のものです。
現在の段階では選択したマスと上下左右のみの反転となっています。

ゲームの内容は

周囲の音符を成長させ消していくパズルゲームです。

プレイヤーは音符を選択していきます。   
すると、音の波紋が広がり、選択した所とその周囲の 音符が成長します。      ただし、成長している音符は壊れてしまいます。

連続して縦横3マスずつ(計9マス)成長している状態になると、 その9マスの音符が消えていきます。

・わからないのは頭上から降ってくる音符をどう扱えばいいのか?(配列でとるのかどうか)
・9マスそろったときどうすれば消えるのか?

という点などです・・・
お忙しいと思いますがどうか教えていただけないでしょうか?

自分は情報セキュリティを専攻しているのでプログラム関係はさっぱりわかりません。

わかりにくい質問ですいません。


387ポイント を手に入れた。


Name: 組木紙織  ..熟練のプログラマー(41,602ポイント)   Date: 2008/02/28(木) 00:06   No:14563     
Title: Re:オリジナルのパズルゲーム    
ざっと目を通しただけで処理は確認していませんが、
オブジェクト指向の概念を使っていないので、C++選択した理由がよくわかりません。
C++を使ったと言わないと、Cで書いたように見えます。
(変数の初期化位置を除いてCみたいです。)

MapData_00配列をなぜ使っているのか?というところが一番気になりました。
画面全体を一つの配列で扱うのではなく、自分の領域と、相手の領域を分けて考えれば、
同じ落下関数を使うことができるので落下処理の扱い方が楽になります。

それよりも配列を全てgrobalで扱っているようにみえます。
できるだけlocalに収めた方が安全にできると思います。

srand()を不必要に使っているかな。
srand()は最初だけ使えばよいです。
(2,3回使っているように見えたので)

>・わからないのは頭上から降ってくる音符をどう扱えばいいのか?(配列でとるのかどうか)
この問題は一般的な落ちものゲームの落下処理と考えればテトリスの作り方が参考になると思います。

>・9マスそろったときどうすれば消えるのか?
画面を配列で扱っているので、ある点を中心にして周りのマスが全部そろった時に、
消す処理をすればできます。


453ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(77,576ポイント)   Date: 2008/02/28(木) 00:46   No:14564     
Title: Re:オリジナルのパズルゲーム    
直接の答えではありませんし、参考になるかも分かりませんが、私が趣味で作っている落ち物パズルゲーム用のクラスを載せてみます。デバッグもしてませんので、動作の保障はありません(苦笑)

pieceクラスとfieldクラスの絡み辺りは落ち物パズルならば、ほとんど共通の似たような動きになるはずなので、何かヒント位にはなるかもしれません。


143ポイント を手に入れた。

Name: 赤羽  ..ぴよぴよ(210ポイント)   Date: 2008/02/28(木) 22:11   No:14576     
Title: Re:オリジナルのパズルゲーム    
みなさんありがとうございます。

>>組木紙織s
え〜とですね・・・C言語のほうがどんなプログラムでも作りやすいと聞いたので
選択しました。
本当に初心者ですので、オブジェクト指向などという言葉は聞いたことありますが
意味などはわかりません・・・
if文やfor文が使えるレベルです・・・。

>>バグs
参考にさせていただいたのですが難しいですねw

ご回答ありがとうございました。


177ポイント を落としてしまった。



Name: tny  ..ぴよぴよ(462ポイント)   Date: 2008/02/27(水) 15:28   No:14543       
Title: グローバル変数を巧いこと複数のファイルで扱う    
また質問させて頂きたいと思います、よろしくお願いします。


グローバル変数を複数ファイルで扱うとき、私の場合は、

グローバル変数宣言用の"GlobalVariable.h"と、GlobalVariable.hで宣言されたグローバル変数をexternするための"ExternGlobalVariable.h"なるヘッダファイルを用意する。
そして、WinMain関数を記述したcppファイルに"GlobalVariable.h"をインクルードし、他の各cpp全てに"ExternGlobalVariable.h"をインクルードする。

と言う手順で実装しています。
しかし、これですと、グローバル変数の内容を変更したいとなったときに、2ファイル分(GlobalVariable.hとExternGlobalVariable.h)変更しなければならず、スマートではなく思われます。
更に、デバッグするとき、ExternGlobalVariable.hを多くのファイルでインクルードしてしまうと、実行までの時間がものすごいかかってしまいます。


これに関して、解決法や改善策がありましたら、ご教授願います。


328ポイント を手に入れた。


Name: バグ  ..比類無きプログラマー(77,365ポイント)   Date: 2008/02/27(水) 15:48   No:14544     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
グローバル変数を使わなければいいのではないでしょうか?

2倍のポイントを手に入れた! 50ポイント を手に入れた。

Name: tny  ..ぴよぴよ(588ポイント)   Date: 2008/02/27(水) 16:28   No:14546     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
一度そうやってゲームを作ってみてるのですが、どうにも都合が悪く感じられてしまって。
シューティングなのですけど、関数の引数が膨大になってしまったり、ちょっとした改造をするにも他の部分へ影響が伝播していってしまうような状況が多発してしまったので。


126ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(43,087ポイント)   Date: 2008/02/27(水) 16:56   No:14549     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
古典的な方法ですが
ExternGlobalVariable.h内部を以下のように記述します。


#ifndef GLOBAL_VARIABLE
#define EXTERN extern
#else
#define EXTERN
#endif

// 以下グローバル変数
EXTERN int hoge1;
EXTERN char hoge2;
・・・
 

次に、WinMainを記述したcpp内部では


#define GLOBAL_VARIABLE
#include "ExternGlobalVariable.h"
 

のように呼び出し、他のcpp内部では


#include "ExternGlobalVariable.h"
 

のように呼び出すことで、グローバル変数の記述を一回で済ませることができます。


ただ、私もバグさんが書かれているように、グローバル変数を使わないことをお勧めします。
クラスをうまく使用することで、グローバル変数をひとつも使わずにプログラムを組むことができます。
(クラスを使わなくてもできますが、クラスを使う場合に比べていろいろと面倒です)


398ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(34,280ポイント)   Date: 2008/02/27(水) 17:48   No:14550     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
次のような方法もあります。
/* GlobalVariable.h */


struct global_t
{
int a;
char b[10];
double c;

};

extern struct global_t global_variable;

/* GlobalVariable.c */
struct global_t global_variable;


のように、グローバル変数をひとつの構造体に入れてしまう方法です。
この方法の利点は、メンテナンスが楽になるほか、グローバル変数の再初期化を簡単に行うことができるようになることです。


223ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(77,433ポイント)   Date: 2008/02/27(水) 18:29   No:14551     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
あら?たかぎさんに先を越されてしまいましたが…(^_^;)

やはり、私も同意見ですね。クラスや構造体をうまく活用すれば、グローバル変数を使用せずにスッキリとしたソースを書く事ができると思います。


68ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(34,372ポイント)   Date: 2008/02/27(水) 19:01   No:14552     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
私が実際に使っている方法は以下のようなものです。
boost::any& global(const std::string& name)

{
static std::map<std::string, boost::any> vars;
return vars[name];
}

void initialize()
{
global("foo") = 1234;
global("bar") = "abc";
global("hoge") = 3.14;
}


こうしておけば、翻訳単位間の初期化順序の問題もクリアできます。
any_cast が面倒なのが難点ですが...


92ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(43,107ポイント)   Date: 2008/02/27(水) 19:14   No:14553     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
>any_cast が面倒なのが難点ですが...
C++にはvar型がないですからねぇ


20ポイント を手に入れた。

Name: tny  ..ぴよぴよ(631ポイント)   Date: 2008/02/27(水) 19:22   No:14554     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
皆様、ご回答ありがとうございます。

GPGAさんのやり方は確かに納得行くのですが、たかぎさんの方法は理解出来ません・・・。
実際に自分でやってみないと把握出来なさそうですので、色々と試してみますね。


しかしあれですね、やはりプロの方はあまりグローバル変数を多用しないのですね。
どういうやり方をすればスッキリいくのかが疑問ですがTT
よろしければ、勉強になりそうなサイト・本etcなどがありましたら、お教えいただけませんでしょうか。


43ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(34,389ポイント)   Date: 2008/02/27(水) 22:13   No:14556     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
> たかぎさんの方法は理解出来ません・・・。

構造体を使う方は分かりますか?


17ポイント を手に入れた。

Name: tny  ..ぴよぴよ(774ポイント)   Date: 2008/02/27(水) 22:27   No:14558     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
あぁすいません、返事を書くのにものすごい文体悩むもので、タイムラグで下二つ分の返事(たかぎさんとGPGAさんのモノ)が見えてませんでした・・・。

構造体の方、色々と猫でも分かるプログラミングやらGoogle経由やらで調べまわっているのですが、それらしいところは見つからずですTT
下の方は、もっと謎ですね・・・まるで初めてソース見たときのような状態です(TT;


143ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(524,659ポイント)   Date: 2008/02/27(水) 23:00   No:14559     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
え?構造体について書いてあるサイトは沢山ありますよね?
http://www.google.co.jp/search?hl=ja&q=%E6%A7%8B%E9%80%A0%E4%BD%93&lr=

構造体はmemsetを使えば簡単に初期化出来ます。


29ポイント を手に入れた。

Name: tny  ..ぴよぴよ(654ポイント)   Date: 2008/02/27(水) 23:06   No:14561     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
構造体に関しては、すいません、何か勘違いしてましたo(_ _o
今は分かりました、お手数かけました。


>構造体はmemsetを使えば簡単に初期化出来ます。
これをしてしまうと、とある社長様に怒られそうな予感がしましたもので・・・。


120ポイント を落としてしまった。

Name: たかぎ [URL]  ..プログラマー(34,474ポイント)   Date: 2008/02/28(木) 10:51   No:14572     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
> >構造体はmemsetを使えば簡単に初期化出来ます。
> これをしてしまうと、とある社長様に怒られそうな予感がしましたもので・・・。

C++ですので、memset で初期化するのはお勧めしません。
# Cでもお勧めしませんが...

構造体の各メンバをデフォルトコンストラクタでクリアしたいのであれば、
struct A

{

};

A a;

int main()
{
a = A(); // クリア
}


とすべきです。


85ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(34,765ポイント)   Date: 2008/02/28(木) 10:58   No:14573     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
一応、global 関数の方も説明しておきます。
boost::any& global(const std::string& name)

{
static std::map<std::string, boost::any> vars;
return vars[name];
}


では、Boost C++ Libraries の中の boost::any クラスを使っています。
global 関数の中で定義している vars は、static 指定子が付いていますので、最初に global 関数が呼び出された時点で構築されます。これは、std::string 型の文字列をキーとして、boost::any 型のオブジェクトを引き当てるための連想配列になっています。
すなわち、global 関数は、渡した文字列に対応した変数(オブジェクト)への参照を返しますので、これをあたかもグローバル変数であるかのように使用できるのです。

難があると書いたのは、boost::any から本来の型に明示的なキャストが必要なためです。
例えば、
global("abc") = 123;

int value = any_cast<int>(global("abc"));


のようにです。



291ポイント を手に入れた。

Name: tny  ..ぴよぴよ(866ポイント)   Date: 2008/02/28(木) 16:27   No:14574     
Title: Re:グローバル変数を巧いこと複数のファイルで扱う    
うーん・・・何よりもまず、Boostと言うのを知りませんでしたので、その勉強から始めた方が良さそう・・・ですかね。
何となくは分かるのですが、そこかしこに理解できない部分があると不安になってしまいますわ・・・。
これ以上突っ込むとスレ違いになりそうですしねTT;


2倍のポイントを手に入れた! 212ポイント を手に入れた。



Name: パソピ  ..初心者(6,554ポイント)   Date: 2008/02/27(水) 12:34   No:14538       
Title: 音楽関数について    
おはようございます。この掲示板で、DXライブラリを用いたシューティングゲームプログラミングについて何度か質問させていただいている者です。
質問の内容ですが、少し謎の現象が起こってしまいました。

シューティングゲームのタイトル画面で音楽を流そうと考えています。
LoadSoundMemで音楽をメモリに読み込んだ後、PlaySoundMemで音楽を流そうとしたのですが、実行してもうまく流れませんでした。しかし、ウィンドウを非アクティブにすると何故か音楽が流れます。ウィンドウをアクティブにすると音楽が停止してしまいます。
音楽が流れるということは、読み込み出来ているはずなのですが、原因がよく分かりません…

お忙しいとは思いますが、このような現象の対処法を知っている方、回答お願いします。



254ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(524,679ポイント)   Date: 2008/02/27(水) 23:02   No:14560     
Title: Re:音楽関数について    
VGAのドライバの問題か何かじゃないでしょうか。
恐らく間違ったコードを書いたとしても通常そのような状態にはならないのではないかと思います。
内部的な問題はよくわからないので、本家の掲示板で聞いてみて下さい。

http://homepage2.nifty.com/natupaji/DxLib/

一度、投稿する前に、VGAのドライバが正しく入っているか確認して下さい。


20ポイント を手に入れた。

Name: 木霊  ..初心者(5,771ポイント)   Date: 2008/02/28(木) 02:24   No:14566     
Title: Re:音楽関数について    
#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode ( TRUE ); // ウインドウモードで起動
if ( DxLib_Init () == -1 ) { return -1; }
SetDrawScreen ( DX_SCREEN_BACK );
ClearDrawScreen ();
SetCreateSoundDataType( DX_SOUNDDATATYPE_MEMPRESS );// ストリーム再生の引数
int S_Handle = LoadSoundMem ( "Test_Music.ogg" );
while ( ProcessMessage () == 0 ) // ------------------ ループ開始
{
PlaySoundMem ( S_Handle, DX_PLAYTYPE_LOOP );// これだけだと問題
/*
PlaySoundMem ( S_Handle, DX_PLAYTYPE_NORMAL );// 解決策その1
// 音楽が鳴り終わるまでここでストップ
*/
/*
if ( CheckSoundMem ( S_Handle ) == 0 ) {
PlaySoundMem ( S_Handle, DX_PLAYTYPE_LOOP );// 解決策その2
}
// 音楽が鳴っていれば何もしないが、鳴っていなければ音楽を鳴らす
*/
ScreenFlip ();
ClearDrawScreen ();
if ( CheckHitKey ( KEY_INPUT_ESCAPE ) == 1 ) break;
}
DxLib_End();
return 0;
}

 パソピさん、上のソースのようにループ内で「PlaySoundMem」関数だけを呼んでませんか?
 この関数は呼ばれる度に、音楽が最初から演奏されます。
 なので音楽が鳴っていないように見えます。(聞こえます)

 解決策は2つありますが、ゲームに使うなら「その2」の方でしょう。/*と*/を外して、
実行してみてください。(例によって、音楽ファイルは御自分で用意して下さい)


445ポイント を手に入れた。

Name: 木霊  ..初心者(5,821ポイント)   Date: 2008/02/28(木) 02:30   No:14567     
Title: Re:音楽関数について    
 ちなみに非アクティブになることでプログラムの進行が停止してるので、
ループが回らずに「PlaySoundMem」関数が呼ばれなくなることで、
音楽が聞こえ始めるのだと思います。


50ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(524,392ポイント)   Date: 2008/02/28(木) 06:43   No:14570     
Title: Re:音楽関数について    
なるほど、再生しまくってるというわけですか^^;
確かにそうなりますね。思いつきませんでしたm(_ _)m


48ポイント を手に入れた。

Name: パソピ  ..初心者(6,635ポイント)   Date: 2008/02/28(木) 09:01   No:14571     
Title: Re:音楽関数について    
管理人さん、木霊さん、おはようございます。

なるほど。音楽が流れないのではなく、連続で再生しようとしていることで聞こえなかったということなんですね…
皆さんのアドバイスで直すことができました。
ありがとうございましたm(_ _)m


81ポイント を手に入れた。



Name: ф魔理沙ф  ..入門者(3,597ポイント)   Date: 2008/02/28(木) 02:20   No:14565       
Title: 敵?    
たびたびすいません。またも壁にぶつかってしまったので質問します。

今シューティングの館のサンプルを元に作っているのですが、
あのサンプルは敵が一種類しかでません。ってことで敵を増やしたいのですが、
プログラムの方を見回してもよく分かりません。
どんな感じにしたら沢山の種類の敵を出すことが出来るのでしょうか?

どなたかご教授よろしくお願いします。(ノ_<。)


178ポイント を手に入れた。


Name: 管理人 [URL]  ..伝説のハッカー(524,344ポイント)   Date: 2008/02/28(木) 06:31   No:14569     
Title: Re:敵?    
敵が保持する情報に種類であるkindを付け加えればいいと思います。
kind==0なら今までどおりの敵、==1なら新しい敵、と判別すればいいでしょう。

//敵

typedef struct{
double x,y,size;
int flag,counter,hp,pattern,kind;
} BODY_enemy_t;


ショットの計算や登録などとは完全に分離しているので、特にここを変えたからといって、ショットの計算方法を変更したりする必要は無いと思います。敵が変わるとどのように性質が変わるような想定をされていらっしゃるのかはわかりませんが、
各敵特有の性質を持たせたりしない場合は単純にkindによって絵の表示とsizeによる当たり判定の範囲を変えてやればいいだけでしょう。


335ポイント を落としてしまった。



Name: はね  ..初心者(6,552ポイント)   Date: 2008/02/26(火) 20:49   No:14531       
Title: テンプレート関数について    
現在、DirectXにて画像を読み込む関数を汎用的にしようと思い、テンプレート関数を作ったのですが、

main.obj : error LNK2019: 未解決の外部シンボル "long __cdecl Init2D<struct PLAYER>(struct PLAYER *,char *,struct D3DXVECTOR2 *)" (??$Init2D@UPLAYER@@@@YAJPAUPLAYER@@PADPAUD3DXVECTOR2@@@Z) が関数 "long __cdecl InitD3d(struct HWND__ *)" (?InitD3d@@YAJPAUHWND__@@@Z) で参照されました。

のエラーの解決法が分からずに困っております。
大変恐縮ですが、どなたかご教授お願いします。


一応参考までにエラーに関係ありそうな部分を抜粋し、下に載せさせていただきました。

==================================Gloval.h内======================================================

//プロトタイプ宣言
template<class T>
HRESULT Init2D(T *,LPSTR Filename,D3DXVECTOR2 *vec2);

================================================================================================

==================================LoadBMP.cpp内===================================================

template<class T>
HRESULT Init2D(T* pg2d,LPSTR Filename,D3DXVECTOR2 *vec2){
if(FAILED(D3DXCreateTextureFromFileEx(pDevice,Filename,vec2->x,vec2->y,0,0,D3DFMT_UNKNOWN,D3DPOOL_DEFAULT,
D3DX_FILTER_NONE,D3DX_DEFAULT,0xffff00ff,NULL,NULL,&pg2d->pTexture))){
MessageBox(0,"テクスチャ失敗","",MB_OK);
return E_FAIL;
}
if(FAILED(D3DXCreateSprite(pDevice,&pg2d->pSprite))){
MessageBox(0,"スプライト失敗","",MB_OK);
return E_FAIL;
}
return S_OK;
}

==================================================================================================

===========================================main.cpp内=============================================

Init2D(&Player[0],"sh/char1.bmp",&D3DXVECTOR2(240,48));
//Init2D(構造体アドレス,画像名,読み込む画像の縦横幅);

==================================================================================================

全てのcppファイルでGloval.hをインクルードしています。
よろしくお願いいたします。


785ポイント を手に入れた。


Name: Justy  ..ハッカー(177,185ポイント)   Date: 2008/02/26(火) 21:06   No:14532     
Title: Re:テンプレート関数について    
 テンプレートの定義はヘッダで、が基本なので、
とりあえず、LoadBMP.cppの Init2D()を Gloval.hへ持っていけばいいはずです。


61ポイント を手に入れた。

Name: はね  ..初心者(6,667ポイント)   Date: 2008/02/27(水) 00:04   No:14533     
Title: Re:テンプレート関数について    
回答ありがとうございます。
Justy様のおっしゃるようにヘッダーに書いたらうまくいきました。

1つ質問なのですが、ヘッダーでは宣言のみで定義はcppファイルでやりましょう。
のような事を見たのですが、テンプレートは例外なのでしょうか?


115ポイント を手に入れた。

Name: Justy  ..ハッカー(177,551ポイント)   Date: 2008/02/27(水) 00:29   No:14534     
Title: Re:テンプレート関数について    
>1つ質問なのですが、ヘッダーでは宣言のみで定義はcppファイルでやりましょう。
>のような事を見たのですが、テンプレートは例外なのでしょうか?

 そうなります。

C++編(言語解説) 第27章 テンプレートクラス
http://www.geocities.jp/ky_webid/cpp/language/027.html
 の中段参照。


 ただ、言語的には exportというキーワードがあり、これを使えば
cppの方に書くこともできるはずです。
(問題はコンパイラがこの機能をサポートしているかどうか、ですが)

テンプレートをヘッダファイル外で定義する - YAMAGUCHI::weblog
http://d.hatena.ne.jp/ymotongpoo/20080115/1200373530



#ところで、このテンプレート関数 Init2D()ですが、
T型の pSpriteのメンバをスプライトと見なして初期化をするようですが、
1つのクラス(T)の中で2つ以上スプライトが必要になったら、
どうするんでしょう?? Init2D2()とか作るのでしょうか。



366ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(42,340ポイント)   Date: 2008/02/27(水) 03:15   No:14535     
Title: Re:テンプレート関数について    
pSpriteは、描画元のイメージではなく
スプライトを描画するための関数のインターフェイスになります。

このpSpriteはグローバルな領域に一つだけ作成して、スプライト描画関数を呼ぶときに
使いまわすのが一般的だと思います。


2倍のポイントを手に入れた! 216ポイント を手に入れた。

Name: はね  ..初心者(6,672ポイント)   Date: 2008/02/27(水) 15:11   No:14541 解決!     
Title: Re:テンプレート関数について    
>>Justy様
>#ところで、このテンプレート関数 Init2D()ですが、
>T型の pSpriteのメンバをスプライトと見なして初期化をするようですが、
>1つのクラス(T)の中で2つ以上スプライトが必要になったら、
>どうするんでしょう?? Init2D2()とか作るのでしょうか。
現在は1つのオブジェクトにつき、1枚の画像しか使用しないのでpSpriteは1つで何の問題もありませんが、
もし、2枚以上の画像が必要なった場合には・・・どうなんでしょ?^^;
考えたこともなかったので憶測ですがpSpriteを配列にしてみたり、でしょうか。
すみません勉強不足です。

>>GPGA
現在は、プレイヤー等の画像を表示させる必要がある構造体にはメンバとして構造体にはそれぞれpSpriteを持たせております。
と言うのも、画像を回転させる等の処理ではPlayer[i].pSprite->SetTransform(&mat);のような関数を使わないとできないのでこのような形しか思いつきませんでした。


5ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(42,689ポイント)   Date: 2008/02/27(水) 16:29   No:14547     
Title: Re:テンプレート関数について    
SetTransformに入れるマトリクスの値をあらかじめプレイヤーのメンバで持っておき
処理の部分で、このマトリクスに回転行列をいれ、描画のときにそのメンバを使用すれば
よいと思います。


LPD3DXSPRITE g_pSprite; // グローバルで宣言

// 描画
void Draw(){
{
g_pSprite->Begin(0);
for (int i = 0; i < MAX_PLAYER; ++i) {
g_pSprite->SetTransform(Player[i].mat);
g_pSprite->Draw(Player[i].pTexture, NULL, NULL, NULL, 0xFFFFFFFF);
}
g_pSprite->End();
}
 

DirectX9.0cからID3DXSprite::Beginの仕様が変更されました。
現在のデバイス状態を保存して内容を書き換え
ID3DXSprite::Endを呼び出したときに元に戻します。
このデバイスの設定の書き換えというのは、処理が軽いものではないので
グローバル領域にひとつだけ作ることで、この負荷を抑えることができます。
もっとも、これに関してはID3DXSprite::BeginのD3DXSPRITE_DONOTSAVESTATEを
渡すことで、保存および復元を行わないようにすることができますが・・・。

ほかにも、デバイスロストやデバイスリセットが起こった場合に
すべてのスプライトに対して、ID3DXSprite::OnLostDeviceや
ID3DXSprite::OnResetDeviceを呼び出す手間も、一度で済みます。


349ポイント を手に入れた。

Name: Justy  ..ハッカー(177,756ポイント)   Date: 2008/02/27(水) 20:13   No:14555     
Title: Re:テンプレート関数について    
 あー、GPGAさんの仰るとおり、ID3DXSpriteが幾つも出てくることはそう無いですね。
 むしろ、テクスチャ(pTexture)の方ですね、問題があるとすれば。


>もし、2枚以上の画像が必要なった場合には・・・どうなんでしょ?^^;
>考えたこともなかったので憶測ですがpSpriteを配列にしてみたり、でしょうか。

 配列にしてもこのInit2D()では処理できないですね。

 pTextureの型が 生の IDirect3DTexture9*なのか、IDirect3DTexture8*なのか、
或いは CComPtrなそれなのかはわかりませんが、ちゃんとテクスチャクラスを
作って、そのメンバ関数でロードとかさせた方がいいかと思います。

 そうしておけば、プレイヤーが何枚もテクスチャを持つ必要があっても
テクスチャクラスをメンバに持たせるだけで、環境が許す限り幾つでも
持てますから。


205ポイント を手に入れた。

Name: はね  ..初心者(6,867ポイント)   Date: 2008/02/27(水) 23:18   No:14562 解決!     
Title: Re:テンプレート関数について    
>>GPGA様
なるほど!確かに個々のオブジェクトに行列を持たせればスプライト一個で済みますね。
貴重な回答ありがとうございます。
早速実装してみます。

>>Justy様
>配列にしてもこのInit2D()では処理できないですね。
はい、おっしゃるようにD3DXCreateSprite()の時点でおかしな事になっていました。
テクスチャの型はLPDIRECT3DTEXTURE9です。
テクスチャクラスですか。今はパッと思いつきませんが今後実装してみようと思います。
ありがとうございました。


195ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(44,117ポイント)   Date: 2008/02/28(木) 04:05   No:14568     
Title: Re:テンプレート関数について    
今から書くことは私の考え方ですので、参考にしてもらってもかまいませんし無視してもらってもかまいません。
私は昔PSの実習機を使っていたことがあり、その作りをベースにしています。

DirectXで描画を行う際に必要な項目を三つのクラスに分けています。
・テクスチャークラス
・スプライトクラス
・描画クラス

大雑把に、各クラスのインターフェイスを記述します。


// テクスチャークラス
class CTexture {
public :
// 読み込み関数
bool CreatFromFile(const char* szFileName); // ファイルから読み込み
bool CreatFromMemory(const char* pcBuffer, DWORD size); // メモリから読み込み

// サイズ関数
DWORD GetWidth() const; // 幅を取得
DWORD GetHeight() const; // 高さを取得

privaete :
// テクスチャーに必要な変数
・・・
};


// スプライトクラス
class CSprite {
public :
int dstx; // 描画先のX座標
int dsty; // 描画先のY座標
int srcx; // テクスチャーのX座標
int srcy; // テクスチャーのY座標
int width; // 幅
int height; // 高さ
int rotate; // 回転角度
int alpha; // アルファ値
float scalex; // X拡縮値
float scaley; // Y拡縮値
CTexture* texture; // 描画するテクスチャー
};


// 描画クラス
class CDraw {
public :
// 通常描画
static void DrawSprite(CSprite& sprite); // スプライトを裏画面に描画する

// 画面反映
static void Present(); // 裏画面に描かれた画像を表画面に描画する
};
 
まずテクスチャークラスはその名のとおり、テクスチャーのみを扱います。
テクスチャークラス一つにつき画像一枚と考えてもらって問題ありません。

スプライトクラスは画面に描画する画像の設定を扱います。
メンバのtextureに、テクスチャークラスのポインタを指定することで、描画する画像を選択します。
また、表示するX座標やY座標、回転角度、拡縮、半透明などの値を設定することができます。


描画クラスはスプライトクラスを受け取り、設定にそって描画を行います。

以上の分け方をすることにより、必要最低限の情報で描画を行うことができます。




これらを実際のゲームで使用する場合、テクスチャークラスはグローバル配列で持ちます。
スプライトクラスはプレイヤークラスのメンバ変数として持ちます。
以下に例を示します。


プレイヤークラス
class Player {
public :
CSprite sprite;
};


// グローバル領域にテクスチャー配列とプレイヤー配列を定義
CTexture g_Texture[5];
Player g_Player[2];

// テクスチャー読み込み関数
void LoadTexture() {
// 0.png〜4.pngという画像を読み込む
for (int i = 0; i < 5; ++i) {
char fname[20];
sprintf(fname, "%d.png", i);
g_Texture[i].CreateFromFile(fname);
}
}

// プレイヤーの初期化を行う
void InitPlayer() {
for (int i = 0; i < 2; ++i) {
g_Player[i].sprite.texture = &g_Texture[i]; // テクスチャーを登録する
g_Player[i].sprite.dstx = 10; // 描画座標を設定する
・・・
}
}


// プレイヤーの描画を行う
void DrawPlayer() {
for (int i = 0; i < 2; ++i) {
CDraw::DrawSprite(g_Player[i].sprite); // スプライトの描画を行う
}

// 表画面に反映する
CDraw::Present();
}
 


使用例が非常に大雑把かつ、C風になってしまいましたが、使い方がわかりましたでしょうか?
(C++風に書くと記述が長くなるのでC風で書かせていただきました)
このやり方ですと、プレイヤーが2つの画像を描画したい場合、プレイヤークラスの
メンバに、スプライトクラスをもう一つ追加して設定することで、描画できます。
長文、失礼しました。


2倍のポイントを手に入れた! 1,010ポイント を手に入れた。



Name: Gantetsu  ..ぴよぴよ(475ポイント)   Date: 2008/02/27(水) 14:53   No:14539       
Title: 教えてください    
初心者です。

double x,y,z;
char str1[10],str2[40]

として

NODE 1 0.0000 -120.0000 0.0000 000
NODE 5658 25.0000 120.0000 35.0000 000
(空白はタブではなく全てスペース)

というファイルをファイルオープン後、

fscanf(fp1,"%s%6d%10f%10f%10f%s\n", str1, &node, &x, &y, &z, str2);

を用いて読み込みを行っていますがうまくいきません。

問題は空白を埋めるスペースのところのようで、1行目を読み終えた時点で各変数を見てみたところ、
str1=NODE
node=1
x=8.45603e-307
y=1.33511e-306
z=1.44638e-307
str2=000
とx,y,zにこちらの意図しない値が入っているようです。
文字幅一定(この場合(NODE)(6文字整数)(10文字実数)(10文字実数)(10文字実数)(20文字空白)(3文字文字列))で読み込みを行う実行ファイルに対する入力ファイルのため、空白をタブに置き換えるなどの処理が出来ず、どうしたものか困っています。
ネットを色々見てみましたがうまい解決方法にたどりつかず、こちらで質問をさせていただきます。
お助けください。


475ポイント を手に入れた。


Name: やそ  ..上級者(24,348ポイント)   Date: 2008/02/27(水) 15:07   No:14540     
Title: Re:教えてください    
%10fのところを%10lfにしてもだめでしょうか?
double型の場合はlfだったと思いますが。

もしかして、またscanfのバッファリングの問題なのかな?
なら、fscanfじゃなくてfgetsとか使えばいいのかな?


char str[256];
FILE *fp;
double x,y,z;
char str1[10],str2[40]


fgets(str,255,fp);

sscanf(str,"%s %6d %10lf %10lf %10lf %s", str1, &node, &x, &y, &z, str2);

とか?


39ポイント を落としてしまった。

Name: バグ  ..比類無きプログラマー(77,315ポイント)   Date: 2008/02/27(水) 15:24   No:14542     
Title: Re:教えてください    
やそさんの言われる変更でいけると思います。
fscanfで読み込むならば…

fscanf(fp, "%s %d %lf %lf %lf %s", str1, &node, &x, &y, &z, str2);

これでだけでいいと思うのですが…何か理由があるのかな?


2倍のポイントを手に入れた! 176ポイント を手に入れた。

Name: Gantetsu  ..ぴよぴよ(609ポイント)   Date: 2008/02/27(水) 16:38   No:14548 解決!     
Title: ありがとうございました    
やそさん、バグさんのおっしゃる方法を試してみたところ、きれいにデータが入ってきました。
結局%lfとすべきところを、%fにしていたのがまずかったようです。
お二人から2通りのパターンも提示していただけて勉強になりました。
ここ数日これで悶々と悩んでいたので感動です。
本当にありがとうございました。


134ポイント を手に入れた。



Name: nullぽ  ..ぴよぴよ(5ポイント)   Date: 2008/02/26(火) 15:22   No:14528       
Title: プロセスの優先度とfpsの関係    
いつもこのサイトで勉強させていただいてます。
少し疑問に思ったことがあったので、質問させて頂きたいと思います。

シューティングゲームの館の方で60fpsの設定をした後、プログラムを動かすとfpsが大体45〜54をうろうろしていたので、タスクマネージャーで優先度を高にしたら解決しました。

こういったプロセスの優先度をプログラム側で制御することは出来るんでしょうか?


5ポイント を手に入れた。


Name: へろり  ..入門者(3,267ポイント)   Date: 2008/02/26(火) 15:49   No:14529     
Title: Re:プロセスの優先度とfpsの関係    
SetPriorityClass()で可能です。

14ポイント を手に入れた。

Name: nullぽ  ..ぴよぴよ(6ポイント)   Date: 2008/02/26(火) 16:47   No:14530 解決!     
Title: Re:プロセスの優先度とfpsの関係    
出来ました、すぐ回答が来て助かりました。ありがとうございます。

1ポイント を手に入れた。



Name: 黒猫  ..入門者(2,537ポイント)   Date: 2008/02/24(日) 11:21   No:14513       
Title: mallocなどを使わずにすませる方法    
こんにちは、初めて質問致します黒猫です。
課題を解いているのですが、途中でつまづいてしまいました。
プログラムは完成しているのですが、教科書の見本などを繋ぎ合わせて作ったので、まだ理解出来ないまま使っているものがあります。「malloc」や「free」などです。
どうにかこれらを使わずに書き換えられないものでしょうか。
すみませんが、アドバイスをお願いいたします><
以下、設問と作成したプログラムです。

・名前(char)、身長(double)、体重(double)、視力(視力構造体)これらのデータをメンバとする構造体を定義して、入力された表示を行うプログラムを作成。
入力件数は最大5件で、名前は19文字までの入力。
範囲外だったならばエラーメッセージ(Sorry. Input less than 20 characters.)を表示し再入力。
名前に"END"が入力されたときは入力を終了して表の表示に移るが、もし最初に"END"が入力された場合は、その旨のメッセージ(Input data is nothing!)を出力。
表示は身長で昇順にソートして出力。
身長、体重は、小数第一位までの表示とし、視力は、小数第三位までの表示。
出力の幅は、名前が19文字、その他は5文字で指定。
視力は右(double)、左(double)をメンバとする構造体で扱うこと。
1件分の入力はinput_data()、表示はdisplay_data()、ソートはsort_data()と処理を関数に分けて行う。

名前の入力の所でつまずいています。
使用環境は、Visual C++2005、Win Vistaです。


#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define BUF 256
#define NAME_MAX 19
#define DATA_MAX 5

typedef struct eye
{
double l_eye; /*左視力*/
double r_eye; /*右視力*/
}Eye;

typedef struct
{
char name[NAME_MAX + 1]; /*名前*/
double height; /*身長*/
double weight; /*体重*/
Eye eye; /*視力*/
}Person;


int input_data(Person *mem);
void sort_data(Person *pmem,int max_cnt);
void display_data(const Person *pmem,int max_cnt);


int main(void)
{
int cnt;
Person data[DATA_MAX];
cnt = input_data(data);
sort_data(data,cnt);
display_data(data,cnt);

return 0;

}

int input_data(Person *mem)
{
int i = 0,cnt = 0;
char *buf;

while( i < DATA_MAX )
{
buf = (char *)malloc( BUF * sizeof( char ) );
if( buf )
{
printf("\n");
printf("Name : ");
scanf("%255s", buf);
}

if( !strcmp(buf,"END") && cnt == 0 )
{
printf("\n Input data is nothing! \n");
exit(0);
}

if( !strcmp(buf,"END") )
{
return cnt;
}

if ( strlen(buf) > NAME_MAX )
{
printf("\n Sorry. Input less than %d characters. \n",NAME_MAX + 1);
continue;
}
else
{
strcpy( (mem+i)->name , buf );
free(buf);
}

printf("Height : ");
scanf("%lf", &((mem+i)->height));

printf("Weight : ");
scanf("%lf", &((mem+i)->weight));

printf("Eye(L) : ");
scanf("%lf", &((mem+i)->eye.l_eye));

printf(" (R) : ");
scanf("%lf", &((mem+i)->eye.r_eye));

i++;
cnt++;
}

return cnt;
}

void sort_data(Person *pmem,int max_cnt)
{
int cnt1;
int cnt2;
Person temp; /* 一時格納領域 */

for(cnt1 = 0 ; cnt1 < max_cnt-1 ; cnt1++) /* ソート処理 */
{

for(cnt2 = cnt1+1 ; cnt2 < max_cnt ; cnt2++)
{
if( (pmem+cnt1)->height > (pmem+cnt2)->height)
{
temp = *(pmem+cnt1);
*(pmem+cnt1) = *(pmem+cnt2);
*(pmem+cnt2) = temp;
}
}
}
}


void display_data(const Person *pmem,int max_cnt)
{
int cnt; /* 個人情報件数カウンタ */

printf("\n********Name***********Hi*****We***(L) Eye (R)**\n");
for(cnt = 0 ; cnt < max_cnt ; cnt++)
{
printf("%-*s %6.1f %6.1f %6.3f %6.3f\n", NAME_MAX, /* データ表示 */
&(pmem+cnt)->name[0],(pmem+cnt)->height,(pmem+cnt)->weight,
(pmem+cnt)->eye.l_eye, (pmem+cnt)->eye.r_eye);
}
return;

}



以上です。
宜しくお願いします。



1,362ポイント を手に入れた。


Name: box  ..ハッカー(107,248ポイント)   Date: 2008/02/24(日) 11:33   No:14514     
Title: Re:mallocなどを使わずにすませる方法    
input_data関数の中の変数bufを
動的に確保するのではなく、
char型の配列で確保すればよいと思います。


28ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(58,510ポイント)   Date: 2008/02/24(日) 11:33   No:14515     
Title: Re:mallocなどを使わずにすませる方法    
これならばfreeを全て消して、mallocで用意しているバッファを全て配列にしてしまえばいいと思います。

int input_data(Person *mem)
{
int i = 0,cnt = 0;
char buf[BUF];

while( i < DATA_MAX )
{
/*以下元ソース*/
/*
buf = (char *)malloc( BUF * sizeof( char ) );
if( buf )
{
printf("\n");
printf("Name : ");
scanf("%255s", buf);
}
*/
/*新ソース*/
printf("\n");
printf("Name : ");
scanf("%255s", buf);

if( !strcmp(buf,"END") && cnt == 0 )
{
printf("\n Input data is nothing! \n");
exit(0);
}

if( !strcmp(buf,"END") )
{
return cnt;
}

if ( strlen(buf) > NAME_MAX )
{
printf("\n Sorry. Input less than %d characters. \n",NAME_MAX + 1);
continue;
}
else
{
strcpy( (mem+i)->name , buf );
/*free(buf);*//*このfree()も取っ払う(コメント化)*/
}

printf("Height : ");
scanf("%lf", &((mem+i)->height));

printf("Weight : ");
scanf("%lf", &((mem+i)->weight));

printf("Eye(L) : ");
scanf("%lf", &((mem+i)->eye.l_eye));

printf(" (R) : ");
scanf("%lf", &((mem+i)->eye.r_eye));

i++;
cnt++;
}

return cnt;
}

こんな感じです。元のソースはコメントとして残してあります。


456ポイント を手に入れた。

Name: box  ..ハッカー(107,298ポイント)   Date: 2008/02/24(日) 11:46   No:14516     
Title: Re:mallocなどを使わずにすませる方法    
input_data関数の中の変数iとcntの違いはどこにありますか?
もし、違いがないのであれば、一つにまとめる方がよいと思います。


50ポイント を手に入れた。

Name: 黒猫  ..入門者(2,784ポイント)   Date: 2008/02/24(日) 12:24   No:14517 解決!     
Title: ありがとうございました    
boxさん、tkmakwins15さん、ありがとうございました。
こんなに早くアドバイスを頂けるとは思っていなかったのでちょっと感動しています。
大袈裟ですみません。

mallocというのが、一時領域を確保してくれるというのはなんとなく分かったのですが、書き換え方が分からず・・・
大変勉強になりました。
配列での確保についてまだ勉強不足ということですよね。
もっと勉強します。


boxさんへ

> input_data関数の中の変数iとcntの違いはどこにありますか?
> もし、違いがないのであれば、一つにまとめる方がよいと思います。

ご指摘ありがとうございました。
おっしゃる通りです・・・同じ働きなので、一つにまとめる事にします。
他にも関数ごとに*pmemと*memとしているので、統一したほうが良いですよね。
もっと、どこが何をしているのかちゃんと考えながら作れるようにしようと思います。

お二人の方、本当にありがとうございました。



247ポイント を手に入れた。



Name: ф魔理沙ф  ..かけだし(2,325ポイント)   Date: 2008/01/31(木) 12:06   No:13912       
Title: なぜか重い壁┃oT)    
いつもこのサイトを拝見させてもらって参考にしている魔理沙です♪

えっとこないだここで質問をしてシューティングゲームのタイトルを表示することができたのですが、

ビルドをして始めると、なぜかものすごい重たいのです。そしてなかなかタイトル画面が表示されません。

最小化して再び最大化すると表示されるのですが何ででしょうか?

一応タイトル画面に関するコードを乗せてみます。

===========title.cpp==============
void title(){
int i,position_y,position_x;
DrawGraph(0,0,img_background[2],FALSE);//タイトル画面表示

DrawGraph(420,220,img_menu[0],TRUE);
DrawGraph(430,260,img_menu[1],TRUE);
DrawGraph(440,300,img_menu[2],TRUE);
DrawGraph(450,340,img_menu[3],TRUE);
position_y=230;
position_x=400;
for(i=1;State==TITLE;){
DrawGraph(position_x,position_y,img_menu[4],TRUE);
if(CheckHitKey(KEY_INPUT_DOWN)==1){
i+=1;
position_x+=10;
position_y+=40;
}
if(CheckHitKey(KEY_INPUT_UP)==1){
i-=1;
position_x-=10;
position_y-=40;
}
if(CheckHitKey(KEY_INPUT_RETURN)==1){
State=RUN;
break;
}

if(CheckHitKey(KEY_INPUT_RETURN)==1){
switch(i){
case 1:
State=RUN;
break;
case 2:
State=RUN;
break;
case 3:
State=RUN;
break;
case 4:
State=RUN;
break;
}
}
}


}


==========main.cpp===============
         メインループ{
switch(State){
case TITLE:
title();
break;
if(Key[KEY_INPUT_ESCAPE]==1)



case RUN:
RefreshTime = GetNowCount(); //今の時間を取得
ClearDrawScreen(); //裏画面のデータを全て削除

Background();

PlayerShotCalc();

PlayerShotDisp();

PlayerControl();

EnemyControl();

EnemyCalcDisp();

EnemyShotControl();

EnemyShotCalcDisp();

CollisionDetection();

Background2();

FpsTimeFanction();

ScreenFlip() ; //裏画面データを表画面へ反映

counter++;
break;

if(Key[KEY_INPUT_ESCAPE]==1)
break; //Escapeが押されたら終了
while(GetNowCount() - RefreshTime < 17);//1周の処理が17ミリ秒になるまで待つ

case GAMEOVER:
break;
case CLEAR:
break;
}
}


と言う感じになっています。すいませんが。ご教授お願いします。


759ポイント を手に入れた。


Name: やそ  ..上級者(18,375ポイント)   Date: 2008/01/31(木) 13:32   No:13918     
Title: Re:なぜか重い壁┃oT)    
タイトル画面の表示が遅い(重い)というのならば・・・
プログラム開始からState==TITLEになってtitle()が呼ばれるまでのプログラムも必要じゃないでしょうか?
これだと、いつ、Stateの状態が変わるのか分からないです。初期値でTITLEが設定されてるの?

それとも、title()に移ってから重くなっているというのははっきり分かっているのでしょうか?

その前の段階と言うことは考えられませんか?
他には、メインループ{からtitleが呼ばれたとき、LoadGraphなしにDrawGraphしてるようですが、その辺は問題なし?



174ポイント を手に入れた。

Name: ф魔理沙ф  ..かけだし(2,423ポイント)   Date: 2008/01/31(木) 14:15   No:13920     
Title: Re:なぜか重い壁┃oT)    
あ、すいません。言葉がいろいろ足りませんでした|_T)

列挙型で定義してそのなかでState=TITLEとなっています。
enum{
TITLE,
RUN,
GAMEOVER,
CLEAR,
};
int State=TITLE;

こんな感じになっています。それでさらに、LoadGraphhはしっかりやってあります。


98ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(508,550ポイント)   Date: 2008/01/31(木) 17:39   No:13928     
Title: Re:なぜか重い壁┃oT)    
こんにちは。ф魔理沙фさん。

プログラムを書いていると、何気なく書いた普通のことが、悪さをしてしまって大変ですよね。

今回重くしている原因はこれじゃないかと思います。

while(GetNowCount() - RefreshTime < 17);//1

改善策を先に言うと、こう書き換えるといいでしょう。

WaitTimer(17-(GetNowCount() - RefreshTime));//2

というのも1は見えないだけで、待機しているだけで何百万回も処理が行われているはずです。
一方で、WaitTimerは一度しか呼ばれません。
WaitTimerは普通のsleep関数のDxLib版です。
http://homepage2.nifty.com/natupaji/DxLib/dxfunc.html#R6N1

またさらによいことに、処理を休ませてくれるのに、
プロセスのメッセージ処理ProcessMessageをしてくれるという便利な関数です。

しかし、スペックの高いPCだと、while文でも、特に処理は重くならない場合が多いです。
もしPCのスペックがそこまで高くないのならこういう処理が行われる「回数」に注意してみるといいかもしれません。

もう一つ重くなる原因はメモリがあふれてしまうこと。
Windowsタスクマネージャーの「パフォーマンス」で確認できる現在のメモリ使用量が、オーバーしていないでしょうか。

例えば、512MB積んでるとします。DxLibを起動する前は450位だったとします。
DxLibを起動した瞬間100MB食って、550MBとかになると、急に重くなります。

多分この2つをチェックすればよくなるのではないでしょうか。


286ポイント を手に入れた。

Name: やそ  ..上級者(19,149ポイント)   Date: 2008/01/31(木) 18:13   No:13931     
Title: Re:なぜか重い壁┃oT)    
>while(GetNowCount() - RefreshTime < 17);

が原因でしたか・・・。

単純に17ミリ秒waitしてくれるだけだと思ってました^^;
まあ、while文なのでその間処理は固まっていると思いますが(笑)
(17ミリ秒の間に何回繰り返されるかは分かりませんが)

PC環境でそれほど変わる部分だったとは^^;



134ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(509,079ポイント)   Date: 2008/01/31(木) 19:01   No:13932     
Title: Re:なぜか重い壁┃oT)    
実はこれはプログラムの世界では泣く子も黙るJustyさんの受け売りです。
私も待機はwhile文で書いていたのですが、お渡しすると、重いといわれ、原因はここだろうと指摘して頂きました。
当時、処理が重いのはこれで解決して、単にその体験談を申しているだけで・・これが原因かどうかはわかりません。

その記事見つけました。
http://www.play21.jp/board/formz.cgi?action=res&resno=1488&page=&lognum=6&id=dixq&rln=1554
いや〜懐かしい記事・・。


ただ、ProcessMessageは結構重要なので、なるべく、処理はとめずに、とめるときは、WaitTimerで止めた方がいいかなと思いました。


241ポイント を手に入れた。

Name: ф魔理沙ф  ..入門者(2,654ポイント)   Date: 2008/02/01(金) 02:14   No:13947     
Title: Re:なぜか重い壁┃oT)    
お返事遅れてすいません。(ノ_<。)

えっと早速試して見たのですが、なぜか重さが解消されません。
原因を考えてみてよくわかりませんが、なんとなく重いのとは違うのかという気がします。

プログラムを立ち上げしばらく待つと窓がでます。しかし画面は真っ黒のままなのです壁┃oT)
そして最小化をしてすぐに最大化すると画面が出ます。
自分が思うには画面の表示関係だと思うのですがよくわかりません・・・^^;

ちなみにこの現象は↑に乗せたプログラムを書いた後から出るので原因はその中にあると思うのですが・・・
なぜでしょうか・・・?


231ポイント を手に入れた。

Name: 管理人  ..伝説のハッカー(509,297ポイント)   Date: 2008/02/01(金) 08:42   No:13949     
Title: Re:なぜか重い壁┃oT)    
私もビスタでコンパイルしたコードはなぜか数秒表示までに時間がかかりました。同じコードでXPとビスタで挙動が変わるのはよくわかりませんから、制作者にお聞きになった方がいいと思います。
もしビスタではないならちょっとこちらで試してみないとそのコードだけではよくわかりません。
DXライブラリの制作者の方は忙しい方なので返事がなかなかもらえない可能性もありますし、よかったら先に一度見せて頂けないでしょうか。
もし人に見せてもいいものならアップローダなどを利用してあげてもらえますか?
あまり人に見せたくなければ私宛にメール添付で送っていただけたらと思います。
コンパイルしてすぐ結果が見れるようプロジェクトファイルなど、必要なファイルは同梱してzipかなにかにしていただけると助かります。


218ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(55,963ポイント)   Date: 2008/02/01(金) 17:48   No:13958     
Title: Re:なぜか重い壁┃oT)    
ビスタのAPIは変化している可能性があるのでは?
その他、Dxライブラリ自体がVista環境では違う挙動をするように設計されています。(というのはDxライブラリの機能自体に違いがあるのではなく、その機能を一定にするための設計みたいです。)


59ポイント を手に入れた。

Name: ф魔理沙ф  ..入門者(2,785ポイント)   Date: 2008/02/03(日) 22:40   No:14018     
Title: Re:なぜか重い壁┃oT)    
返信遅れてすいません(ノ_<。)
ちょっと家のネットが金を払ってなかったので使えませんでした(;>_<;)

それでできれば余り見せたくはないので、メールで送りたいと思うのですが、
メルアドを教えてもらえませんか?トップのメールはなぜか開かないので;w;

ほかに方法があるならほかでもいいのですが・・・w


131ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(510,258ポイント)   Date: 2008/02/04(月) 01:52   No:14026     
Title: Re:なぜか重い壁┃oT)    
メールアドレスは
dixqhp@gmail.com
です。
アップローダなどを利用してもらってもかまいません。
拝見して解決するかどうかはわかりませんが・・。

私もネット料金未払いで今つながらないので、時間かかるかもしれません^^;


108ポイント を手に入れた。

Name: クロカモ  ..ぴよぴよ(14ポイント)   Date: 2008/02/06(水) 22:21   No:14086     
Title: Re:なぜか重い壁┃oT)    
どうも、お初にお目にかかります。
まだまだプログラミングは初めて時間はたってないのですがこのサイトで勉強してじっくりと実力を付けようと思います。
今後ともよろしくお願いします。

発投稿をこの雑談に書き込みさせていただいたのは他でもありません。
自分もなぜこのプログラムが重くて大変なのかを是非とも教えていただきたく書き込ませていただきました。
自分勝手で申し訳ありませんがよかったらMAILの方に理由を送ってください。

よろしくお願いします。


14ポイント を手に入れた。

Name: 管理人 [URL]  ..伝説のハッカー(510,546ポイント)   Date: 2008/02/07(木) 15:25   No:14106     
Title: Re:なぜか重い壁┃oT)    
プロジェクト一式送っていただきましたので、よくわかりました。
掲示板で公開されていないので、公言すべきでない内容も含まれていてはいけませんので、
ф魔理沙фさんの投稿があるまで、だいたいな事だけ申し上げます。

原因は重いわけではありませんでした。
何か入力があるまで画面初期化や画面反映関数の無いただのループを延々と回るプログラムであった為、キー入力をするまで
シューティング画面に進まなかったというものでした。
また、データのロードが二重にされていたので、メモリの少ないパソコンだと、動きが遅くなったということもあるかもしれません。

なかなかトラブルがあると困りますよね・・。


292ポイント を手に入れた。

Name: ф魔理沙ф  ..入門者(2,967ポイント)   Date: 2008/02/16(土) 22:03   No:14328     
Title: Re:なぜか重い壁┃oT)    
大変返事が遅れてすいません(ノ_<。)
PCがちょっと逝っちゃいましたヘ(-_-ヘ
とりあえず直りましたので、返信しておきます(⌒▽⌒)

送っていただいたプログラムの方見させてもらいました。
ちょっといろいろ解らないこともありましたが、大体理解できたと思いますw
原因としてはやっぱりループを抜けていなかったのですね;
いろいろやってもらってありがとうございました(≧∇≦)/

ほかにもステージの作り方など聞きたいことがありますが、レスが立っているようなので
そちらで質問させてもらいます。
本当にありがとうございました。


182ポイント を手に入れた。

Name: ギョピ  ..ぴよぴよ(61ポイント)   Date: 2008/02/22(金) 20:44   No:14501     
Title: Re:なぜか重い壁┃oT)    
こんばんは。
解決したトピックに書き込むのも変ですが、どうしても気になることがあります。

魔理沙さんのプログラムの問題点である「処理が重くなる」ことについてなのですが、私もその壁にぶち当たってしまいました。
横から急にこのような質問をして申し訳ありませんが、どなたかこの問題点についてご教授願えないでしょうか?
お願いします。


61ポイント を手に入れた。

Name: 管理人  ..伝説のハッカー(524,152ポイント)   Date: 2008/02/23(土) 04:12   No:14505     
Title: Re:なぜか重い壁┃oT)    
重くなる原因は山のようにあるのでそれだけではよくわかりません。
まずは実行時にメモリーオーバーしてないか、タスクマネージャなどで調べ、続いて描画しすぎてないか、全画面アルファブレンドなど他用していないか、セットフォントなど他用してはいけない関数を他用していないかなどを調べる感じでしょうか。


128ポイント を落としてしまった。

Name: ギョピ  ..ぴよぴよ(90ポイント)   Date: 2008/02/23(土) 09:00   No:14507     
Title: Re:なぜか重い壁┃oT)    
管理人さん回答ありがとうございます。

自分のソースコードを見て、無駄に多用されてないか考えてみようと思います。


29ポイント を手に入れた。

Name: tkmakwins15 [URL]  ..熟練のプログラマー(57,977ポイント)   Date: 2008/02/23(土) 10:58   No:14508     
Title: Re:なぜか重い壁┃oT)    
三角関数の多用も遅くなる原因になります。
というよりも数学関数は下手すると遅くなります。一回ぐらいなら大丈夫だと思うけど。
という訳でこの自作sinと標準でどちらが速くなるかやってみました。
#include<stdio.h>

#include<stdlib.h>
#include<time.h>

#define REDIAN(X)((X)*(3.14159/180))

double mysin(double);
double y1[1000],y2[1000];

int main(void)
{
double begin=0,total1=0,total2=0;
int i,j,k,l;
FILE *file;
file=fopen("speedsin.csv","w");
if(!file)return 0;
for(i=0;i<10;i++){
begin=clock();
for(j=0;j<1000;j++){/*自作sin関数*/
y1[j]=mysin(REDIAN(j));
}
total1+=clock()-begin;
begin=clock();
for(k=0;k<1000;k++){/*標準関数*/
y2[k]=sin(REDIAN(k));
}
total2+=clock()-begin;

puts("自作関数\t標準関数\t誤差");
for(l=0;l<1000;l++){
if(fabs(y2[l]-y1[l])<0.01){/*近い範囲だけはコンソールにも結果を出す*/
printf("%f\t%f\t%f\n",y1[l],y2[l],fabs(y2[l]-y1[l]));
}
}
}
puts("平均タイム(単位:秒)");
printf("%f\t,%f\t,%f\n",total1/10,total2/10,fabs(total1-total2)/10);
fputs("自作関数\t,標準関数\t,誤差\n",file);
fprintf(file,"%f\t,%f\t,%f\n",y1[l],y2[l],fabs(y2[l]-y1[l]));
fputs("平均タイム(単位:秒)\n",file);
fprintf(file,"%f\t,%f\t,%f\n",total1/10,total2/10,fabs(total1-total2)/10);
fclose(file);
return 0;
}

double mysin(double red)
{
return red-(red*red*red)/6+(red*red*red*red*red)/120;
}

ただし、自作関数はその特性上、引数の値が大きくなるにつれて誤差が大きくなります。90度くらいまでなら何とか…という感じです。


678ポイント を手に入れた。



Name: ちょこ  ..ぴよぴよ(34ポイント)   Date: 2008/02/22(金) 03:46   No:14467       
Title: 無題    
はじめまして、いつもこちらのHPを参考にさせてもらってます。
今、シューティングゲームを作ってるんですが画面をスクロールさせるプログラムが思いつきません。
どのようにコードを書けばよいか、教えていただけますでしょうか


34ポイント を手に入れた。


Name: 管理人  ..伝説のハッカー(524,280ポイント)   Date: 2008/02/22(金) 08:04   No:14469     
Title: Re:無題    
携帯で書いているのでサンプルとか書けませんが、

まず連続で表示させて継ぎ目の出来ない画像を用意します。
どんな画像かわかりませんが、とりあえずVGAサイズの画面に対して画像もVGAだとします。

座標(0,n)に1枚表示し、(0,480-n)にもう1枚表示し、nの値を0〜-480の範囲をマイナスしてループさせます。

すると出来上がりです。
奥行きや立体感を出したいなら、手前の画像ほど大きく、スクロールを早く表示すれば立体的に表現できますよ。


2倍のポイントを手に入れた! 404ポイント を手に入れた。

Name: ちょこ  ..ぴよぴよ(0ポイント)   Date: 2008/02/22(金) 10:20   No:14472     
Title: Re:無題    
管理人さん返信ありがとうございます。
これをもっとループさせるためにはこのnの値の範囲を大きくし、それに合った大きめの画像を用意すればよいでしょうか?


53ポイント を落としてしまった。

Name:  ..プログラマー(28,855ポイント)   Date: 2008/02/22(金) 11:09   No:14475     
Title: Re:無題    
スクロールのシューティングなら、
画面の背景がそこまで変化しなくて良いなら
■:←を画像とすると
 ■
 ■
 
同じ画像を繋げてしまえばいいのでは?と思います。(管理人さんと同じかな?
僕は、座標をx,yで管理して、一定速度で進んでいくとしたとき(y方向に)
画像(??? * 480 のサイズ)としたとき、
画像の表示の始点をどんどん減らして行きます。(y方向に)
一枚目の始点をx,yとすると
二枚目の始点がx,y+480となるということです。
(yはどんどん減っていくとします。

その後、yは-480を超えると思います。
そうしたら、y=0として元に戻します

それ以外に、gX,gYを作って、こちらはどんどん増やしていくと考えます(gYを
そうすれば、gX,gY = 100, 500 の地点に障害物や微妙に背景を変更したように見せる表示を!!
(建物を加えたりwwww
とか出来そうだな〜と考えますが、出来るかどうか走りません。

どうでしょうか?


307ポイント を落としてしまった。

Name: 木霊  ..初心者(5,326ポイント)   Date: 2008/02/23(土) 03:50   No:14503     
Title: Re:無題    
#include "DxLib.h"


void Speed_Change ( int &Temp_Speed );// スクロールスピードの変更
void Speed_Scope_Check ( int &Temp_Speed );// スクロールスピードの範囲チェック
void Graphic_Scroll ( int &Start_Pos, int &End_Pos, int Temp_Handle, int Roll_Spd = 1 );
// 背景の下方向スクロール(のみ)を行う関数

// *****************************************************************************
// メイン
// *****************************************************************************
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
if ( DxLib_Init () == -1 ) { // ---- DXライブラリ初期化処理
return -1;
}
SetDrawScreen ( DX_SCREEN_BACK );
ClearDrawScreen ();

int Gr_Handle = LoadGraph ( "Test_Graphic.bmp" ); // グラフィックの読み込み
int Start_Y_Position = 0, End_Y_Position = 480; // スクロールに使う変数の宣言と初期化
int Scroll_Speed = 1; // スクロールスピードの宣言と初期化

while ( ProcessMessage () == 0 ) { // ------------------ ループ開始

Speed_Change ( Scroll_Speed ); // スクロールスピードの変更
Graphic_Scroll ( Start_Y_Position, End_Y_Position, Gr_Handle, Scroll_Speed );
// スクロールを行う関数呼び出し

ScreenFlip ();
ClearDrawScreen ();
if ( CheckHitKey ( KEY_INPUT_F12 ) != 0 ) { break; }
}
InitGraph ();
DxLib_End (); // -DXライブラリの使用終了処理
return 0; // ---------------- ソフトの終了
}
void Speed_Change ( int &Temp_Speed )
{
if ( CheckHitKey ( KEY_INPUT_A ) != 0 ) { Temp_Speed --; }
if ( CheckHitKey ( KEY_INPUT_Z ) != 0 ) { Temp_Speed ++; }
Speed_Scope_Check ( Temp_Speed );
return;
}
void Speed_Scope_Check ( int &Temp_Speed )
{
if ( Temp_Speed <= 1 ) { Temp_Speed = 1; }
if ( Temp_Speed >= 16 ) { Temp_Speed = 16; }
return;
}
void Graphic_Scroll ( int &Start_Pos, int &End_Pos, int Temp_Handle, int Roll_Spd )
{
/* if ( Start_Pos >= 480 ) {
Start_Pos = 0;
End_Pos = 480;
}
DrawRectGraph ( 0, 0, 0, Start_Pos, 640, End_Pos, Temp_Handle, TRUE, FALSE );
if ( End_Pos != 480 ) {
DrawRectGraph ( 0, End_Pos, 0, 0, 640, 480 +End_Pos, Temp_Handle, TRUE, FALSE );
}
Start_Pos += Roll_Spd;
if ( ( Start_Pos +End_Pos ) > 480 ) { End_Pos -= Roll_Spd; }
*/
if ( Start_Pos <= 0 ) {
Start_Pos = 480;
End_Pos = 0;
}
DrawRectGraph ( 0, 0, 0, Start_Pos, 640, 480, Temp_Handle, TRUE, FALSE );
DrawRectGraph ( 0, End_Pos, 0, 0, 640, Start_Pos, Temp_Handle, TRUE, FALSE );
Start_Pos -= Roll_Spd;
End_Pos += Roll_Spd;
return;
}


あまり上手なコードではないですが参考程度に・・・(640×480の画像は御自分で用意してください)
一応AキーとZキーでスクロールスピードを変更できます


2倍のポイントを手に入れた! 1,744ポイント を手に入れた。



Name: ゆも  ..ぴよぴよ(124ポイント)   Date: 2008/02/22(金) 16:24   No:14496       
Title: メンバ変数に配列を格納しようとしました。    
C++にてコンパイルした結果

■aa.h
private:
 AddressInfo *m_AddressInfo; // AddressInfoは自作のクラス
};

■aa.cc
aa::aa(AddressInfo *ad)
{
m_AddressInfo = ad;
}

■bb.cc
void main()
{
AddressInfo *ai = new AddressInfo("a", "b", "c");
AddressInfo *ad[6];
ad[0] = ai;
ad[1] = ai;
ad[2] = ai;

aa res = new aa(ad);
}

■エラー内容
error C2664: '__thiscall aa::aa(AddressInfo *)' : 1 番目の引数を 'class AddressInfo *[6]' から 'class AddressInfo *' に変換できません。
(新しい機能 ; ヘルプを参照)
指示された型は関連がありません; 変換には reinterpret_cast、 C スタイル キャストまたは関数スタイルのキャストが必要です。

とのエラーがでてしまっているのですが、
思いつくままにコードを修正してもエラーは増えるばかり、、、
どのような修正方法があるのでしょうか?
宜しくお願い致します。


124ポイント を手に入れた。


Name: GPGA  ..熟練のプログラマー(42,157ポイント)   Date: 2008/02/22(金) 16:33   No:14497     
Title: Re:メンバ変数に配列を格納しようとしました。    

■aa.h
private:
 AddressInfo **m_AddressInfo; // AddressInfoは自作のクラス
};


■aa.cc
aa::aa(AddressInfo **ad)
{
m_AddressInfo = ad;
}
 


95ポイント を手に入れた。

Name: ゆも  ..ぴよぴよ(16ポイント)   Date: 2008/02/22(金) 17:08   No:14498     
Title: Re:メンバ変数に配列を格納しようとしました。    
ポインタのポインタなんて存在するのですね。
勉強不足でした。。。
ありがとうございます。

ちなみに、配列からの取り出し方は以下でよろしいのでしょうか・・・?
AddressInfo *ai = *(m_AddressInfo);
AddressInfo res = ai[1];


108ポイント を落としてしまった。

Name: GPGA  ..熟練のプログラマー(42,124ポイント)   Date: 2008/02/22(金) 17:32   No:14499     
Title: Re:メンバ変数に配列を格納しようとしました。    
AddressInfo *ai = m_AddressInfo[1];
AddressInfo res = *ai;


33ポイント を落としてしまった。

Name: ゆも  ..ぴよぴよ(53ポイント)   Date: 2008/02/22(金) 17:57   No:14500 解決!     
Title: Re:メンバ変数に配列を格納しようとしました。    
おお!
なるほど。ありがとうございました!
解決しました。m(__)m


37ポイント を手に入れた。



Name: みらの  ..かけだし(1,273ポイント)   Date: 2008/02/22(金) 14:27   No:14483       
Title: c++のmap宣言にて。    
VC++ 6.0にて
下記のC++をビルドすると
やたら警告が出るのですが何故でしょうかね・・・

#include <map>
#include <string>

using namespace std;

void main()
{
map<string,string> a;
}


警告文
warning C4786: 'std::_Tree<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char>
> >,std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<st
d::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::_Kfn,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::it
erator' : デバッグ情報で識別子が 255 文字に切り捨てられました。
warning C4786: 'std::_Tree<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char>
> >,std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<st
d::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::_Kfn,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::_N
ode' : デバッグ情報で識別子が 255 文字に切り捨てられました。
warning C4786: 'std::_Tree<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::basic_string<char,std::char_traits<char>,std::allocator<char>
> >,std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<st
d::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::_Kfn,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::_R
edbl' : デバッグ情報で識別子が 255 文字に切り捨てられました。
warning C4786: 'std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::
allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >' : デバッグ情報で識別子が 255 文字に切り捨てられました。
warning C4786: 'std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::
allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::value_compare' : デバッグ情報で識別子が 255 文字に切り捨てられました。
warning C4786: 'std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::
allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >::_Kfn' : デバッグ情報で識別子が 255 文字に切り捨てられました。
リンク中...

test.exe - エラー 0、警告 76


1,273ポイント を手に入れた。


Name: たかぎ [URL]  ..プログラマー(33,933ポイント)   Date: 2008/02/22(金) 14:30   No:14484     
Title: Re:c++のmap宣言にて。    
> warning C4786

これは典型的な無視すべき警告です。
うるさいので、
#pragma warning(disable:4786)



をソースの最初に記述しておくとよいでしょう。
できれば、すべてのソースからインクルードされるヘッダに最初にでも入れておくと楽です。


111ポイント を手に入れた。

Name: みらの  ..かけだし(1,241ポイント)   Date: 2008/02/22(金) 14:34   No:14486 解決!     
Title: Re:c++のmap宣言にて。    
凄いすっきりしました!!!!!

ありがとうございますっ!
助かりましたっ


32ポイント を落としてしまった。

Name: バグ  ..比類無きプログラマー(76,844ポイント)   Date: 2008/02/22(金) 14:55   No:14487     
Title: Re:c++のmap宣言にて。    
std::mapに限らず、STL関連のクラスを使用しようとすると、かなりの高確率で警告が出ますよね…。
MicroSoftからすれば、MFCを使えという事なんでしょうね…きっと(あくまで推測です)


51ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(40,484ポイント)   Date: 2008/02/22(金) 15:26   No:14490     
Title: Re:c++のmap宣言にて。    
VS2005だとそのような警告は全くと言っていいほどでないです。

改良されたのかな。


35ポイント を手に入れた。

Name: GPGA  ..熟練のプログラマー(42,062ポイント)   Date: 2008/02/22(金) 15:57   No:14494     
Title: Re:c++のmap宣言にて。    
VC6.0では識別子が255文字で警告が出ましたが、VS2005では4096文字以上にならないと
警告は出ません。超えた場合はC4503警告が出ます。


35ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(33,961ポイント)   Date: 2008/02/22(金) 16:20   No:14495     
Title: Re:c++のmap宣言にて。    
> VS2005では4096文字以上にならないと警告は出ません。

かなりましにはなりましたが、名前空間が深くなると簡単に超えてしまいそうです。


25ポイント を手に入れた。



Name: たか  ..ぴよぴよ(910ポイント)   Date: 2008/02/22(金) 13:49   No:14480       
Title: 小数の桁数を指定した切捨ての仕方    
こんにちは、いかについて質問です。

double aaa = 123.456779874243753

上記のaaaを小数点第6位以下を切捨てる。

結果 123.45677

上記方法を教えてください。
環境はvisual studio 2005 .net です。

以下は試したところ誤差が出てしまったので、できれば誤差の出ない切捨て方法をお願いします。

long box = aaa * 100000;
aaa = box / 100000;


161ポイント を手に入れた。


Name: 組木紙織  ..熟練のプログラマー(40,138ポイント)   Date: 2008/02/22(金) 13:57   No:14481     
Title: Re:小数の桁数を指定した切捨ての仕方    
質問1:
 言語はcですか?c++ですか?
質問2:
 切り捨てした結果はどうするのですか?(変数に代入するとか、表示するとか)


65ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(33,822ポイント)   Date: 2008/02/22(金) 14:11   No:14482     
Title: Re:小数の桁数を指定した切捨ての仕方    
> 誤差が出てしまったので

この場合は「誤差」とはいわないような...
long box = aaa * 100000; 

aaa = box / 100000;


で多少はましになりますが、誤差が全くなくなるわけではありません。

10進法で表現して誤差がないようにするには、BCD演算でも行うとか、文字列で扱うとかしないとダメです。


100ポイント を手に入れた。

Name: たかぎ [URL]  ..プログラマー(33,936ポイント)   Date: 2008/02/22(金) 14:31   No:14485     
Title: Re:小数の桁数を指定した切捨ての仕方    
すみません。コピペのミスです。
long box = aaa * 100000; 

aaa = box / 100000.0;


でましになります。


3ポイント を手に入れた。

Name: たか  ..かけだし(1,305ポイント)   Date: 2008/02/22(金) 14:56   No:14488     
Title: Re:小数の桁数を指定した切捨ての仕方    
質問1:
 言語はcですか?c++ですか?

回答1:
 C++です。

質問2:
 切り捨てした結果はどうするのですか?(変数に代入するとか、表示するとか)

回答2:
 関数の戻り値として返します。(変数に代入)



前回の質問(標準関数atofについて:2008/02/17(日) 10:32)
の続きになってしまうのですが…以下が現在の状況です。

#######################################################

moji    :char型の配列で"123.45678901234567"が格納
ret  :double型
box :long型

/* char → double */
ret = atof(moji);

■ret = 123.45678901234567(ウォッチウインドウ表示)

box = ret * 100000;

■box = 12345678(ウォッチウインドウ表示)

ret = box;
ret /= 100000.0;

■ret = 123.45677999999999(ウォッチウインドウ表示)

####################################################

期待値 ret = 123.45678

うまく伝えられなくすいません。



395ポイント を手に入れた。

Name: 組木紙織  ..熟練のプログラマー(40,449ポイント)   Date: 2008/02/22(金) 15:24   No:14489     
Title: Re:小数の桁数を指定した切捨ての仕方    
つまり
double ret = 123.45678901234567;
定義した retの
小数点以下8桁までを表示したいということですか?

切り捨てる関数を double kiri(double)として

double ret2 = kiri(ret);

//ret2を演算に使う。
ret2 =0.5+ret2

という風にしたいわけではなく。

ならこちらでも。


#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

int main()
{
double ret = 123.45678901234567;
std::ostringstream stream ;
stream <<std::setprecision(10) << ret;

std::string out;
out.assign(stream.str(),0,9);
std::cout << out << std::endl;

return 0;
}




311ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(77,102ポイント)   Date: 2008/02/22(金) 15:30   No:14491     
Title: Re:小数の桁数を指定した切捨ての仕方    
あら?C++でしたか…
まぁ、せっかくCで組んでみたので、一応載せておきます(^_^;)
結構、力技なのであまり参考にはならないと思いますが…


int main(void)
{
double aaa = 123.456779874243753;
char str[512], *pchr;

// 一度文字列に変換
sprintf(str, "%.16f", aaa);

// 文字列内に小数点がある場合は小数点以下6桁目を'\0'に置き換える
if ((pchr = strchr(str, '.')) != NULL)
*(pchr + 6) = '\0';

// 文字列を数値に戻して画面に表示する
aaa = atof(str);
printf("%.5f\n", aaa);

return 0;


258ポイント を手に入れた。

Name: たか  ..かけだし(1,415ポイント)   Date: 2008/02/22(金) 15:43   No:14492 解決!     
Title: Re:小数の桁数を指定した切捨ての仕方    
サンプル回答ありがとうございます。

参考にした結果ですが
小数点位置を戻す前にあらかじめ
小さな数を足してから処理するようにしました。

ret += 0.0000005;
ret /= 100000.0;

■ret = 123.45678000000500(ウォッチウインドウ表示)

ご協力ありがとうございました。


110ポイント を手に入れた。

Name: バグ  ..比類無きプログラマー(77,139ポイント)   Date: 2008/02/22(金) 15:56   No:14493     
Title: Re:小数の桁数を指定した切捨ての仕方    
それだと『切捨て』ではなくて、『四捨五入』もしくは『繰上げ』になってしまいませんか?

37ポイント を手に入れた。




 
[ 1 , ... ]
 
 
管理者画面   RSS   + Powered By 21style +