プログラムの書き方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あきら

プログラムの書き方

#1

投稿記事 by あきら » 17年前

いつも利用させていただき誠にありがとうございます。

プログラムの書き方に関して気になる事があったので質問させていただきます。

C言語~プログラミングの館~ 33節 選択画面の作り方では,下キーを押すことで白いカーソルが下に下がるようになっているかと思います。
せっかくこのような素晴らしいサイトがあるので,上キーを押して白いカーソルが上にあがるような仕組みにできないものかと思考錯誤した結果,上キーを押すことで白いカーソルが上にあがるようにプログラムを書く事が出来ました。
しかし,現状はコピーペーストでなんとなく理解している程度なので,プログラミングの書き方として間違ってないか。
また,もっとスマートなプログラムが書けないと気になったので質問させていただきました。
プログラムは次の投稿で記載したいと思います。

あきら

Re:プログラムの書き方

#2

投稿記事 by あきら » 17年前

#include "DxLib.h"

void char_disp(int White,int y){
DrawString( 150 , y , "■" , White );
DrawString( 170 , 100 , "NEW GAME" , White );
DrawString( 170 , 120 , "CONTINUE1" , White );
DrawString( 170 , 140 , "CONTINUE2" , White );
DrawString( 170 , 160 , "CONTINUE3" , White );
DrawString( 170 , 180 , "CONTINUE4" , White );
DrawString( 170 , 200 , "CONTINUE5" , White );
DrawString( 170 , 220 , "CONTINUE6" , White );
DrawString( 170 , 240 , "LOG OUT" , White );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
ChangeWindowMode( TRUE ) ; //ウィンドウモードに変更
if( DxLib_Init() == -1 ) return -1; // DXライブラリ初期化処理 エラーが起きたら終了

int White , y=100; //色とy座標の宣言
int DownOshita=0,NewDown=0,OldDown=0,DownPusingCounter=0;
int UpOshita=0,NewUp=0,OldUp=0,UpPusingCounter=0;//各種フラグの宣言
char KeyBuf[ 256 ] ; //キー入力状態を格納する変数

White = GetColor( 255 , 255 , 255 ) ; //色の取得

SetDrawScreen( DX_SCREEN_BACK ) ; // 描画先を裏画面に設定

while( 1 ){
ClearDrawScreen(); // 裏画面のデータを全て削除
GetHitKeyStateAll( KeyBuf ) ; // すべてのキーの状態を得る
if( KeyBuf[ KEY_INPUT_ESCAPE ] == 1 ) break ; // Escapeが押されたらブレイク

char_disp(White,y); // 文字を描画

if( KeyBuf[ KEY_INPUT_DOWN ] == 1 ) // 下キーが押されたら
NewDown=1; // 今押されている状態に
else // 押されていなかったら
NewDown=0; // 今押されていない状態に

if( KeyBuf[ KEY_INPUT_UP ] == 1 ) // 上キーが押されたら
NewUp=1; // 今押されている状態に
else // 押されていなかったら
NewUp=0; // 今押されていない状態に

if( OldDown==0 && NewDown==1 ) // 前回押されてなく、今回押されていたら
DownOshita=1; // たった今押された状態に
else // それ以外なら
DownOshita=0; // たったいま押されていない状態に

if( OldUp==0 && NewUp==1 ) // 前回押されてなく、今回押されていたら
UpOshita=1; // たった今押された状態に
else // それ以外なら
UpOshita=0; // たったいま押されていない状態に

if( OldDown==1 && NewDown==1 ) // 前回も押され、今回も押されていたら
DownPusingCounter++; // 押しっぱなしカウンターを増加
else
DownPusingCounter=0;

if( OldUp==1 && NewUp==1 ) // 前回も押され、今回も押されていたら
UpPusingCounter++; // 押しっぱなしカウンターを増加
else
UpPusingCounter=0;


if( DownOshita==1 || DownPusingCounter>30){ // たった今押したか、30カウンター以上押しっぱなしなら
if(DownPusingCounter>30) // 30カウンター以上押しっぱなしならカウンターを27へ
DownPusingCounter=27; // オートの場合4回に1回下に下がる。
y+=20;
if(y==260) // y座標が260なら(選択が一番下なら)
y=100; // 選択座標を一番上に
}
if( UpOshita==1 || UpPusingCounter>30){ // たった今押したか、30カウンター以上押しっぱなしなら
if(UpPusingCounter>30) // 30カウンター以上押しっぱなしならカウンターを27へ
UpPusingCounter=27; // オートの場合4回に1回上に上がる。
y-=20;
if(y==80) // y座標が80なら(選択が一番上なら)
y=240; // 選択座標を一番下に
}
OldDown=NewDown,OldUp=NewUp; // 新しい入力情報を古い入力情報へ

if( ProcessMessage() == -1 ) break ; //エラーが起きたら終了
ScreenFlip() ; // 裏画面データを表画面へ反映
}

DxLib_End() ;// DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}

やそ

Re:プログラムの書き方

#3

投稿記事 by やそ » 17年前

char_disp(White,y); // 文字を描画

の書く場所がおかしいです。

キー判定によってせっかく操作したY座標なのにchar_disp()が呼ばれずに
ScreenFlip()で画面反映しているようです。

while()に入る前に一度char_disp()を呼んで選択画面を表示しておいて、
while()の中でY座標を計算し、
char_dispを再度呼んで裏画面に表示して、
ScreenFlip()で画面反映するのが良いと思います。

また、選択画面の表示については選択肢は最初の一回だけでよいでしょう。
書き直す可能性のあるのは■マークだけなので、
char_disp()をうまく分割するといいんじゃないかな。

あきら

Re:プログラムの書き方

#4

投稿記事 by あきら » 17年前

やそ様

早速のご助言ありがとうございます。

まだこちらのサイトで勉強を始めたばかりでわからない点が多いのですが,よろしくお願い致します。

いくつかわからない点があるので質問したいと思います。

>char_disp(White,y); // 文字を描画
>の書く場所がおかしいです。

どの位置に書くのがふさわしいのでしょうか。

>キー判定によってせっかく操作したY座標なのにchar_disp()が呼ばれずに
>ScreenFlip()で画面反映しているようです。

呼ぶというのは,どういった操作をさし,どのように記述すればよいのでしょうか。

>while()に入る前に一度char_disp()を呼んで選択画面を表示しておいて、
>while()の中でY座標を計算し、
>char_dispを再度呼んで裏画面に表示して、
>ScreenFlip()で画面反映するのが良いと思います。

while()の中でY座標を計算というのは,どういう記述を指しているのでしょうか。

本当に初歩的な質問ばかりで申し訳ないのですが,よろしくお願い致します。

やそ

Re:プログラムの書き方

#5

投稿記事 by やそ » 17年前

んーと、本当に初歩的な質問でガッカリだよ!!(by桜塚やっくん)

と言うのはお約束の突っ込みとして、

あきらさんのその返しを見るに・・・
記述されたカーソル移動プログラムの内容を把握していないのかな?
”答え”をプログラムじゃなくて文章の形で書いただけなのですが・・・

「呼ぶ」と言うのは関数をコールすると言うことを指したつもりでしたが、
分かりにくかったでしょうか?
「char_disp()を呼んで~」とかいたので文意は分かっていただけると思いました。

はっきり言って答えを曝すのは質問者&回答者双方のためにならないので好きじゃないんですけどね^^;
#include "DxLib.h" 
/* 選択肢とカーソルを表示 */
void char_disp(int White,int y){ 
DrawString( 150 , y , "■" , White );
}
void char_disp2(){ 
DrawString( 170 , 100 , "NEW GAME" , White ); 
DrawString( 170 , 120 , "CONTINUE1" , White ); 
DrawString( 170 , 140 , "CONTINUE2" , White ); 
DrawString( 170 , 160 , "CONTINUE3" , White ); 
DrawString( 170 , 180 , "CONTINUE4" , White ); 
DrawString( 170 , 200 , "CONTINUE5" , White ); 
DrawString( 170 , 220 , "CONTINUE6" , White ); 
DrawString( 170 , 240 , "LOG OUT" , White ); 
} 

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ 
ChangeWindowMode( TRUE ) ; //ウィンドウモードに変更 
if( DxLib_Init() == -1 ) return -1; // DXライブラリ初期化処理 エラーが起きたら終了 

/* 宣言と初期設定 */
int White , y=100; //色とy座標の宣言 
int DownOshita=0,NewDown=0,OldDown=0,DownPusingCounter=0; 
int UpOshita=0,NewUp=0,OldUp=0,UpPusingCounter=0;//各種フラグの宣言 
char KeyBuf[ 256 ] ; //キー入力状態を格納する変数 

White = GetColor( 255 , 255 , 255 ) ; //色の取得 

SetDrawScreen( DX_SCREEN_BACK ) ; // 描画先を裏画面に設定 

char_disp(White,y); // カーソルを描画
char_disp2(); // 選択肢を描画

/* 選択肢ループ開始 */
while( 1 ){ 
	ClearDrawScreen(); // 裏画面のデータを全て削除 
	GetHitKeyStateAll( KeyBuf ) ; // すべてのキーの状態を得る 
	if( KeyBuf[ KEY_INPUT_ESCAPE ] == 1 ) break ; // Escapeが押されたらブレイク 

/* カーソル表示 (コメント化)*/
//	char_disp(White,y); // 文字を描画 

	if( KeyBuf[ KEY_INPUT_DOWN ] == 1 ) // 下キーが押されたら 
		NewDown=1; // 今押されている状態に 
	else // 押されていなかったら 
		NewDown=0; // 今押されていない状態に 

	if( KeyBuf[ KEY_INPUT_UP ] == 1 ) // 上キーが押されたら 
		NewUp=1; // 今押されている状態に 
	else // 押されていなかったら 
		NewUp=0; // 今押されていない状態に 

	if( OldDown==0 && NewDown==1 ) // 前回押されてなく、今回押されていたら 
		DownOshita=1; // たった今押された状態に 
	else // それ以外なら 
		DownOshita=0; // たったいま押されていない状態に 

	if( OldUp==0 && NewUp==1 ) // 前回押されてなく、今回押されていたら 
		UpOshita=1; // たった今押された状態に 
	else // それ以外なら 
		UpOshita=0; // たったいま押されていない状態に 

	if( OldDown==1 && NewDown==1 ) // 前回も押され、今回も押されていたら 
		DownPusingCounter++; // 押しっぱなしカウンターを増加 
	else 
		DownPusingCounter=0; 

	if( OldUp==1 && NewUp==1 ) // 前回も押され、今回も押されていたら 
		UpPusingCounter++; // 押しっぱなしカウンターを増加 
	else 
		UpPusingCounter=0; 

/* カーソルの上下移動&ループ処理 */
	if( DownOshita==1 || DownPusingCounter>30){ // たった今押したか、30カウンター以上押しっぱなしなら 
		if(DownPusingCounter>30) // 30カウンター以上押しっぱなしならカウンターを27へ 
			DownPusingCounter=27; // オートの場合4回に1回下に下がる。 
/* ひとつ下の選択肢にカーソルのY座標を移動 */
		y+=20; 
		if(y==260) // y座標が260なら(選択が一番下なら) 
			y=100; // 選択座標を一番上に 
	} 

	if( UpOshita==1 || UpPusingCounter>30){ // たった今押したか、30カウンター以上押しっぱなしなら 
		if(UpPusingCounter>30) // 30カウンター以上押しっぱなしならカウンターを27へ 
			UpPusingCounter=27; // オートの場合4回に1回上に上がる。 
/* ひとつ上の選択肢にカーソルのY座標を移動 */
		y-=20; 
		if(y==80) // y座標が80なら(選択が一番上なら) 
			y=240; // 選択座標を一番下に 
	} 
/* 入力状態を引き継ぐ */
	OldDown=NewDown,OldUp=NewUp; // 新しい入力情報を古い入力情報へ 

	if( ProcessMessage() == -1 ) break ; //エラーが起きたら終了 
/* 画面表示 */
                char_disp(White,y); // カーソルを描画
		ScreenFlip() ; // 裏画面データを表画面へ反映 
} 

DxLib_End() ;// DXライブラリ使用の終了処理 
return 0 ; // ソフトの終了 

}
です。

やそ

Re:プログラムの書き方

#6

投稿記事 by やそ » 17年前

あれ、今思ったが、移動前のカーソルって消さなくていいんだろうか??
その辺の調整は考えてみてください。

あきら

Re:プログラムの書き方

#7

投稿記事 by あきら » 17年前

やそ様

このような初歩的な質問に対しても,真摯に答えていただき誠にありがとうございます。

早速,自分で書いたプログラムとどのように違うか検討したみたいと思います。

まだまだ勉強が足りないのは重々承知ではありますが,今後ともよろしくお願い致します。

あきら

Re:プログラムの書き方

#8

投稿記事 by あきら » 17年前

再度問題が生じたため,質問させていただきます。

よろしくお願いします。

やそ様に回答いただいたプログラムをコピーペーストし,デバッグを行ってみました。

するとwhiteが宣言されていないというエラーが出たため,色々と調べてみました。

結果,ビルドが成功するまで修正する事が出来たのですが,修正の仕方が間違ってないかご指導いただけないでしょうか。


修正前   // char_disp(White,y); // 文字を描画
修正後    char_disp(White,y); // 文字を描画
こちらですが,ここは説明箇所ではないので,先頭の//は間違いではないでしょうか。

修正前      char_disp2(); // 選択肢を描画
修正後      char_disp2(White); // 選択肢を描画
Whiteが定義されていないというエラーが出たため,Whiteを入れてみました。

修正前      char_disp(White,y); // カーソルを描画

修正後      char_disp(White,y); // カーソルを描画
char_disp2(White); // コンティニュー等を描画
コンティニュー等が画面に表示されていなかったのでchar_disp2(White); を入れてみました。

やそ

Re:プログラムの書き方

#9

投稿記事 by やそ » 17年前

あ、やっぱりWhiteは宣言エラーでますか^^;
void char_disp2(){
では特に引数を必要としないと思ったので省いちゃってました^^;
あきらさんの言われるとおり
void char_disp2(int White){



}

として、使うときにも
char_disp2(White); // 選択肢を描画
で良いかと思います。


>修正前   // char_disp(White,y); // 文字を描画
>修正後    char_disp(White,y); // 文字を描画
>こちらですが,ここは説明箇所ではないので,先頭の//は間違いではないでしょうか。

についてはここで呼ぶのはおかしいのであえてコメントにしてあります。
(削除しても良かったのですが、違いを分かりやすく見せるための措置です)

おかしいと言うその理由は前述しておりますが・・・
この場所ではY座標計算前なので呼んでも意味が無いからです。

あきら

Re:プログラムの書き方

#10

投稿記事 by あきら » 17年前

やそ様

回答いただきありがとうございます。

重複している時点で明らかに不自然ですね。

>おかしいと言うその理由は前述しておりますが・・・
まだまだ勉強不足のため,記述する位置が理解できておりませんでした。

お恥ずかしい限りです。

残念ながら(?),Whiteはエラーが出てしまいました。

今さらですが,VC 2008 EEを使用しております。

本当に,懇切丁寧に色々とご助言いただきありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る