公式アカウントからの投稿が始まります

いつもお世話になっております。 
 
 
いま、RPGを作っているのですが、
名前をボタンで入力して
wsprintf(HITOMOJI,TEXT(""),wParam);
~wsprintf(ROKUMOJI,TEXT(""),wParam);
wsprintf(Name,TEXT("%s%s%s%s%s%s"),HITOMOJI~ROKUJIMO);
とやっているのですが、
入力1文字は問題なしで、
6文字だと

その後の処理(戦闘)で、
StetasWnd
には基本ステータス(TextOut)しか表示されないはずなのに、
メインウィンドウの文字がStetasWndに描画されてしまいます。
 
さらに、所持金は10~13しか追加されないはずなのに、
800000000000000とか、ありえない桁数になるんです。
いわゆるバグですが、これの解消法はありますでしょうか?
 
※うまく説明できてませんがお願いします。

A 回答 (7件)

> Para=(rand() % (MDATE[monsNo].MonsLv+2))+MDATE[monsNo].PARA;



ここの計算部分が怪しいので、下記の各変数の値が思った通りになっているか確認しましょう。

monsNo
MDATE[monsNo].MonsLv
MDATE[monsNo].PARA

開発環境がわかりませんが、デバッグウィンドウが使用できるならそこに表示させれば確認できますし、なければ一時的に

> wsprintf(GetPARA,L"%sは%ldパラを得た。",NAME,Para);

のParaの部分を置き換えてやれば確認できますよね。

この回答への補足

Paraの部分を変えてみましたが、まったく改善されませんでした。

補足日時:2011/08/22 17:26
    • good
    • 0
この回答へのお礼

丁寧な説明、ありがとうございました。
解決しました。
 
すいませんが、この質問は削除します。(クソゲーですが、念のため

お礼日時:2011/08/22 17:40

>逆にメモリの確保しすぎでもなりますか?



文字列を扱う関数は、\0が来れば文字列が終わったと判定するので、それより後に何が入っていようと問題にならないはずです。無駄に大量に確保しようとしてメモリ不足とかにならなければ。

この回答への補足

ありがとうございました。
文字が別のウィンドウに描画される現象は改善されましたが、数字(所持金)が異常な数字になるのがわからないです。
static long Para=0,SYOJIPARA=0;
static TCHAR GetPARA[50],NAME[50],nowpara[50];
Para=0;
Para=(rand() % (MDATE[monsNo].MonsLv+2))+MDATE[monsNo].PARA;
wsprintf(GetPARA,L"%sは%ldパラを得た。",NAME,Para);
TextOut(hdcv,150,270,GetPARA,lstrlen(GetPARA));
SYOJIPARA+=Para;
EX+=MDATE[monsNo].MonsKeiken;
wsprintf(nowpara,L"所持金: %ldパラ",SYOJIPARA);

補足日時:2011/08/22 16:16
    • good
    • 0
この回答へのお礼

丁寧な説明、ありがとうございました。
解決しました。
 
すいませんが、この質問は今夜削除します。(クソゲーですが、念のため

お礼日時:2011/08/22 17:41

>描画する部分を消してもでてきました



ならば、文字列の変数の領域を超えていないか確認しましょう。

例えば、

wchar_t test1[5], test2[10];

lstrcpy(test1, L"あいうえお");

とすると、test1には5文字分しかメモリが確保されていないのに

あいうえお\0

の6文字が格納されます。6文字目は別の変数の領域などにはみ出している形になります。
ここで、test2がたまたまtest1の後ろに確保されているとして、

lstrcpy(test1, L"あいうえお");
lstrcpy(test2, L"かきくけこ");

というコードを実行すると、最初の命令ではみ出した部分はtest2[0]に入ってしまい、そのあとの命令で\0が上書きされるため、メモリ上では

あいうえおかきくけこ\0

という並びになります。ここで、test1をTextOutなどで表示させると、test1には入れていないはずの"かきくけこ"まで表示されてしまいます。

こういった部分を検証するために、変数の定義を何度も聞いているのですが。おそらく、関係ないと思ったのでしょうが、原因がわからないバグは、自分が関係ないと思っている部分が影響していることが多いです。「こうなるはず」とか「こうなっているはず」という考えを捨てて、1つ1つ考えた通りに動作しているか確認していくことが、結局は早道だと思いますよ。その経験が積み重なっていくと、最初に何を確認したらよいかという優先順位がわかってくると思います。

あと、wsprintfじゃなくlstrcpyを使う理由は、何をするための命令かがわかりやすいことと、wsprintfは書式文字列を解析して文字列を格納するので、単純に文字列をコピーするlstrcpyよりも内部で実行される命令が多くなる(=遅くなる)ことです。
他人がソースを見たとき(あるいは、自分が見たときでも、時間がたって内容をよく覚えていないようなとき)には、wsprintfが使われていて、wParamといった引数が無意味な状態になっていると、書式文字列を間違っている可能性を考えてしまいます。

この回答への補足

なるほど。
lstrcpyについてはやってみます
逆にメモリの確保しすぎでもなりますか?

補足日時:2011/08/22 10:17
    • good
    • 0
この回答へのお礼

消せない・・・
まあいいか。
 
ありがとうございました。

お礼日時:2011/08/22 19:57

> 「VisualWndの文字」がです



で、そのウィンドウの描画部分はまたまた内緒ですか。

>wsprintfはTEXTがないとエラーがでました

単にTEXTを外すとエラーになるでしょう。私は

L"あ"

とすればと書いています。
あと、lstrcpyじゃいけない理由は何なんでしょうか?

この回答への補足

wsprintfで格納した("%sは%ldパラを得た")がでてくるんです
描画する部分を消してもでてきました

あと、lstrcpyじゃないといけない理由は何でしょうか?(けしかけるようですいません

補足日時:2011/08/22 07:35
    • good
    • 0

>StetasWnd


>には基本ステータス(TextOut)しか表示されないはずなのに、
>メインウィンドウの文字がStetasWndに描画されてしまいます。

という現象なのに、メインウィンドウのウィンドウプロシージャを内緒にして解決すると思います?
それに、hWndの子ウィンドウと書かれてるけど、hWndはウィンドウプロシージャの引数として出てくるだけで、そこにはSatesWndかNameWndが入ってるはずなので、意味が不明です。(ちなみに、ステータスは「Status」と書きます)

所持金についても、Paraのことなんでしょうが変数の型は相変わらず不明だし、計算に使用している変数も同様に不明じゃ、原因なんかわかりません。

>wsprintf(MOJI,TEXT("あ"),wParam);

lstrcpy(MOJI,TEXT("あ"));

じゃだめなんですか? wParamなんて必要ないと思いますけど。
MOJIに1文字しか入らない仕様なら、もっと違うやり方があるし、wsprintfなんだからTEXTマクロ使わずにL"あ"でいいと思いますけど。

あと、ウィンドウプロシージャでウィンドウハンドルをhWndで受け取ったのなら、WM_PAINTの処理でもhWndを使ったほうがいいですよ。複数のウィンドウでウィンドウプロシージャを共有することになった場合に、書き直す部分が少なくなります。

この回答への補足

いろいろ焦ってて、間違えてます
「VisualWndの文字」がです

プロシージャの引数はNameWnd、StatesWndにしました(ご指摘をうけるまえに)
書き方は(つづりとか)それぞれだとおもいますが
wsprintfはTEXTがないとエラーがでました
変数は全てstaticな変数にしてあります

所持金、ステータスは static long です

補足日時:2011/08/21 22:55
    • good
    • 0

部分的にコードを提示されても、変数(と思われるもの)の型とかがまったくわかりませんし、ウィンドウをどのように描画しているのかも提示せずに「基本ステータス(TextOut)しか表示されないはずなのに」とかいわれても、検証のしようがありません。



> wsprintf(HITOMOJI,TEXT(""),wParam);

これでちゃんと文字が入るんですか?

何か全然コードの書き方を理解していないように思えますが。

この回答への補足

恥ずかしながらコードを掲載します。
これが、問題の描画部分。
 
LRESULT CALLBACK StatesProc (
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {

switch(uMsg) {
case WM_DESTROY:
DestroyWindow(StatesWnd);

return 0;
case WM_PAINT:
hdcs = BeginPaint(StatesWnd,&ps);
TextOut(hdcs,10,10,(LPCWSTR)States,lstrlen((LPCWSTR)States));
TextOut(hdcs,10,30,(LPCWSTR)lv,lstrlen((LPCWSTR)lv));
TextOut(hdcs,15,55,(LPCWSTR)nowhp,lstrlen((LPCWSTR)nowhp));
TextOut(hdcs,15,75,(LPCWSTR)nowmp,lstrlen((LPCWSTR)nowmp));
TextOut(hdcs,20,95,(LPCWSTR)str,lstrlen((LPCWSTR)str));
TextOut(hdcs,20,115,(LPCWSTR)bougyo,lstrlen((LPCWSTR)bougyo));
TextOut(hdcs,15,135,(LPCWSTR)nowex,lstrlen((LPCWSTR)nowex));
TextOut(hdcs,15,155,(LPCWSTR)nowpara,lstrlen((LPCWSTR)nowpara));
EndPaint(StatesWnd,&ps);


return 0;

}
return DefWindowProc(hWnd , uMsg , wParam , lParam);
}

StatesWndというウィンドウで親ウィンドウは、hWndです。
HDC hdcs;となっているのは、原因がわからなかったので、とりあえず
それぞれの処理で分けてみましたけど、うまくいかないです
これが、
switch(wParam){
case KOUGEKI_ID:
playerattack=0;
monsattack=0;
Para=0;
playerattack=(rand() % (Lv+1)+STR)- (MDATE[monsNo].MonsBOUGYO);
monsattack=(rand() % (MDATE[monsNo].MonsLv+1)+MDATE[monsNo].MonsSTR) - BOUGYO;
Para=(rand() % (MDATE[monsNo].MonsLv+2))+MDATE[monsNo].PARA;
if(playerattack<0){
playerattack=0;
}else if(monsattack<0){
monsattack=0;
}
wsprintf(MonsterName,MDATE[monsNo].MonsName,wParam);
wsprintf(PlayerAttack,TEXT("%sに%ldのダメージ!"),MDATE[monsNo].MonsName,playerattack);
wsprintf(MonsterAttack,TEXT("%sに%ldのダメージ!"),NAME,monsattack);
wsprintf(GetKeiken,TEXT("%sは%ldの経験値を得た。"),NAME,MDATE[monsNo].MonsKeiken);
wsprintf(GetPARA,TEXT("%sは%ldパラを得た。"),NAME,Para);
HP-=monsattack;
(MDATE[monsNo].MonsHP)-=playerattack;
wsprintf(nowhp,TEXT("HP: %ld/%ld"),HP,MAXHP);
battle=1;
InvalidateRect(StatesWnd,NULL,FALSE);
InvalidateRect(VisualWnd,NULL,FALSE);
break;
}

この処理の箇所でおかしくなります。
これはVisualWndというウィンドウで、hWndの子ウィンドウです。
 
それで、文字入力の部分。
 
 

LRESULT CALLBACK NameProc (
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {

switch(uMsg) {
case WM_DESTROY:
DestroyWindow(NameWnd);
case WM_PAINT:
hdcn = BeginPaint(NameWnd,&ps);
MoveToEx(hdcn,50,150,NULL);
LineTo(hdcn,70,150);
MoveToEx(hdcn,75,150,NULL);
LineTo(hdcn,95,150);
MoveToEx(hdcn,100,150,NULL);
LineTo(hdcn,120,150);
MoveToEx(hdcn,125,150,NULL);
LineTo(hdcn,145,150);
MoveToEx(hdcn,150,150,NULL);
LineTo(hdcn,170,150);
MoveToEx(hdcn,175,150,NULL);
LineTo(hdcn,195,150);

if(ni==1){
TextOut(hdcn,50,130,HITOMOJI,lstrlen(HITOMOJI));
}else if(san==1){
TextOut(hdcn,75,130,HUTAMOJI,lstrlen(HUTAMOJI));
}else if(yon==1){
TextOut(hdcn,100,130,SANMOJI,lstrlen(SANMOJI));
}else if(go==1){
TextOut(hdcn,125,130,YONMOJI,lstrlen(YONMOJI));
}else if(roku==1){
TextOut(hdcn,150,130,GOMOJI,lstrlen(GOMOJI));
}else if(nana==1){
TextOut(hdcn,175,130,ROKUMOJI,lstrlen(ROKUMOJI));
}

EndPaint(NameWnd,&ps);
return 0;
case WM_COMMAND:
if(iti==1){
InvalidateRect(NameWnd,NULL,FALSE);
}else if(ni==1){
InvalidateRect(NameWnd,NULL,FALSE);
}else if(san==1){
InvalidateRect(NameWnd,NULL,FALSE);
}else if(yon==1){
InvalidateRect(NameWnd,NULL,FALSE);
}else if(go==1){
InvalidateRect(NameWnd,NULL,FALSE);
}else if(roku==1){
InvalidateRect(NameWnd,NULL,FALSE);
}else if(nana==1){
InvalidateRect(NameWnd,NULL,FALSE);
}
switch(LOWORD(wParam)) {
case ADAN_ID:
if(agyou==1){
if(hiragana==1){
if(komoji==1){
wsprintf(MOJI,TEXT("ぁ"),wParam);
}else{
wsprintf(MOJI,TEXT("あ"),wParam);
}
}else{
if(komoji==1){
wsprintf(MOJI,TEXT("ァ"),wParam);
}else{
wsprintf(MOJI,TEXT("ア"),wParam);
}
}
}else if(yagyou==1){
if(hiragana==1){
if(komoji==1){
wsprintf(MOJI,TEXT("ゃ"),wParam);
}else{
wsprintf(MOJI,TEXT("や"),wParam);
}
}else{
if(komoji==1){
wsprintf(MOJI,TEXT("ャ"),wParam);
}else{
wsprintf(MOJI,TEXT("ヤ"),wParam);
}
}
}
 
・・・・・・・・・・・・・・

break;
 
長いのでここまでで。
わをん、濁点、半濁点はうまくいってないのでまだ途中です。
また、カタカナ、ひらがなの切り替え、小文字大文字の切り替えがあります。
ちゃんと、実行して思い通りの処理をしてくれています。
 
ヘタながら、書き方はわかっているつもりではあります。
 

補足日時:2011/08/21 08:37
    • good
    • 0

>※うまく説明できてませんがお願いします。


の通り、残念ながらいったい何が起こっているのか完全に不明です。
該当部分のソースコードを漏れなく掲載するなどした方がよい回答が得られるかと思います。

>wsprintf(HITOMOJI,TEXT(""),wParam);
少なくともwsprintfの第二引数が空文字列なのはおかしいと思います。
http://msdn.microsoft.com/ja-jp/library/cc364872 …

この回答への補足

TEXTのとこには
あ~んが入ります。
書き忘れてました、すいません

ソースコードをそのまま載せるのが恥ずかしかったので…

補足日時:2011/08/20 23:57
    • good
    • 0
この回答へのお礼

ありがとうございました。
解決しました。
 
すいませんが、この質問は削除します。(クソゲーですが、念のため

お礼日時:2011/08/22 17:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!