ページ 11

このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 12:50
by まみ
私は、C言語を軽くかじった程度初心者です。

コード:

#include "DxLib.h"				
int img[3],sound[5];//画像、音楽
int Key[256];//キー
int player,com,state;//プレイやー、コンピュータ、状態
int sound_flag[5],sound_state;//再生フラグ、再生状態

//入力処理
int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[]){
    char GetHitKeyStateAll_Key[256];
    GetHitKeyStateAll( GetHitKeyStateAll_Key );
    for(int i=0;i<256;i++){
        if(GetHitKeyStateAll_Key[i]==1) GetHitKeyStateAll_InputKey[i]++;
        else                            GetHitKeyStateAll_InputKey[i]=0;
    }
    return 0;
}

//最初の初期化
void first_ini(){
	player	=-1;
	com		=-1;
	state	=-1;
	sound_state=0;//未再生
	SetFontSize(20);
}

//フラグの初期化
void ini(){
	memset(sound_flag,0,sizeof(int)*5);
}

//リセット
void reset(){
	//再生フラグがオフなら
	if(sound_state==0){
		sound_flag[0]=1;//ジャンケン・・
		sound_state=1;//再生した状態に変更
	}
	if(Key[KEY_INPUT_RETURN]==2)//エンターが押されていたら
		first_ini();//最初の初期化
}

//ロード
void load(){
	img[0]=LoadGraph("dat/0.PNG");
	img[1]=LoadGraph("dat/1.PNG");
	img[2]=LoadGraph("dat/2.PNG");
	sound[0]=LoadSoundMem("dat/ジャンケン.wav");
	sound[1]=LoadSoundMem("dat/あいこで.wav");
	sound[2]=LoadSoundMem("dat/やったね.wav");
	sound[3]=LoadSoundMem("dat/ポコ.wav");
}

//ジャンケン処理
void calc_janken(){
	if(player!=com){
		if(player == (com+1)%3){
			state=1;//負け状態
			sound_flag[3]=1;
		}
		else{
			state=2;//勝ち状態
			sound_flag[2]=1;
		}
	}
	else{
		state=0;//あいこ状態
		sound_flag[1]=1;
	}
}

//入力処理
void input_janken(){
	if(!(state==-1 || state==0))//まだ未入力か、あいこじゃないなら処理しない
		return ;
	//何か入力があれば
	if(Key[KEY_INPUT_0]==2 || Key[KEY_INPUT_1]==2 || Key[KEY_INPUT_2]==2){
		if(Key[KEY_INPUT_0]==2)//グーなら
			player=0;
		if(Key[KEY_INPUT_1]==2)//チョキなら
			player=1;
		if(Key[KEY_INPUT_2]==2)//パーなら
			player=2;
		com=GetRand(2);//コンピュータの入力
		calc_janken();//ジャンケン処理
	}
}

//描画
void graph_janken(){

	DrawFormatString(  0,  0,GetColor(255,255,255),"%s","Enterキーでリセット 0:グー 1:チョキ 2:パー");
	if(state==-1)
		DrawFormatString(150,50,GetColor(255,255,255),"%s","ジャンケン・・・");
	else if(state==0)
		DrawFormatString(150,50,GetColor(255,255,255),"%s","あいこで・・・・");
	else if(state==1)
		DrawFormatString(150,50,GetColor(255,255,255),"%s","******ポコ******");
	else
		DrawFormatString(150,50,GetColor(255,255,255),"%s","***やったね!***");

	DrawFormatString(150,130,GetColor(255,255,255),"%s","相手:");
	DrawFormatString(150,310,GetColor(255,255,255),"%s","自分:");

	if(0<=player && player<=2)
		DrawGraph(320,100,img[com],TRUE);
	if(0<=com && com<=2)
		DrawGraph(320,280,img[player]   ,TRUE);
}

//音楽再生
void play_sound(){
	for(int i=0;i<5;i++){
		if(sound_flag[i]==1){
			PlaySoundMem(sound[i],DX_PLAYTYPE_BACK);
		}
	}
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
	first_ini();//初期化
	load();//画像ロード
    while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない

		ini();//フラグの初期化

		reset();//リセット

		input_janken();//入力させる

		graph_janken();//描画

		play_sound();//音楽再生

        ScreenFlip();//裏画面反映
    }

    DxLib_End();//DXライブラリ終了
    return 0;
}
このジャンケンゲームなのですが(サンプルプログラミングの館にあるソース)
全体の構造は軽く理解できるのですが
一つ一つの処理がどう行われているのか全然わかりません。
たくさん質問すると答えるのに苦労しますので分割で質問させてもらいます。

①//フラグの初期化
void ini(){
memset(sound_flag,0,sizeof(int)*5);//
}
これは具体的に何をしているのかわかりません。
どんな処理をしているのか教えてくれませんか?

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 13:02
by non
これと同じ

コード:

void ini(){
	sound_flag[0]=0;
	sound_flag[1]=0;
	sound_flag[2]=0;
	sound_flag[3]=0;
	sound_flag[4]=0;
}

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 13:41
by まみ
解説ありがとうございます。

①ところでなぜ5なのでしょうか?
プログラム自体に
Sound_frag[4]=0が見当たらないのですが


//最初の初期化
void first_ini(){
player =-1;
com =-1;
state =-1;
sound_state=0;//未再生
SetFontSize(20);
}

これはなぜ
player = -1
com = -1
state = -1
-1なのでしょうか?


Sound_state=0は0だから未再生なのでしょうか?

解説していただけませんか?

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 13:45
by びす

コード:

int sound_flag[5]
は、intを5個つくり、その先頭のアドレスをsound_flagに入れています

↓ ここをsound_flagへ
[int0][int1][int2][int3][int4]

よって、sound_flagからint5個分を0で埋めることで

コード:

sound_flag[0]=0;
sound_flag[1]=0;
sound_flag[2]=0;
sound_flag[3]=0;
sound_flag[4]=0;
と同じ働きをします

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 13:57
by non
まみ さんが書きました: ①ところでなぜ5なのでしょうか?
プログラム自体に
Sound_frag[4]=0が見当たらないのですが
作者に訊かないとわからないですね。
もう一つ、何かの効果音が欲しかったのかも?

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 13:59
by まみ
解説ありがとうございます!
①と③は理解することが出来ました!

②はどうして-1なのでしょうか?

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 14:03
by non
まみ さんが書きました:
//最初の初期化
void first_ini(){
player =-1;
com =-1;
state =-1;
sound_state=0;//未再生
SetFontSize(20);
}

これはなぜ
player = -1
com = -1
state = -1
-1なのでしょうか?
これも、作者の趣味でしょう。
0,1,2の3つの値に意味を持たせてあります。初期状態はそれ以外の数値にしたかったので
作者は-1にしたのでしょう。
初期状態を0にして、状態を1,2,3にしても問題なかったはずです。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 14:18
by まみ
なるほど!
理解しました!
ありがとうございます!

次にこのプログラムです。

//リセット
void reset(){
//再生フラグがオフなら
if(sound_state==0){
sound_flag[0]=1;//ジャンケン・・
sound_state=1;//再生した状態に変更
}
if(Key[KEY_INPUT_RETURN]==2)//エンターが押されていたら
first_ini();//最初の初期化
}

雰囲気では、わかるのですが本当にこれでいいのかとわからないんで
やはり正確な解説が聞きたいです。
プログラムの一行一行に解説コメントを書いてくれませんか?

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 14:32
by たかぎ
まみ さんが書きました:雰囲気では、わかるのですが本当にこれでいいのかとわからないんで
やはり正確な解説が聞きたいです。
プログラムの一行一行に解説コメントを書いてくれませんか?
では、雰囲気でわかったことを一行一行コメントで書いてみては?
間違っていれば、誰かが正確な解説をしてくれるでしょうし、間違っていなければそれでOKといってくれるでしょう。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 15:23
by まみ
雰囲気でわかったことは

if(sound_state==0){

これがオフなら

sound_flag[0]=1;//ジャンケン・・
sound_state=1;//再生した状態に変更
}

この処理を行うってこと

オフでなければ

if(Key[KEY_INPUT_RETURN]==2)//エンターが押されていたら
first_ini();//最初の初期化
}
この処理が行われる。

こんな感じしかわかりません。

具体的に言いますと

コード:

//リセット
void reset(){
	//再生フラグがオフなら
	if(sound_state==0){//①これは未再生を表しているのでしょうか?
		sound_flag[0]=1;//②この再生フラグの[0]=1がなぜこうなのかわかりません。
		sound_state=1;//③再生した状態に変更ってことは、sound_state=1は再生の意味なのでしょうか?
	}
	if(Key[KEY_INPUT_RETURN]==2)//④これは意味はわかるのですがなぜ2なのかわかりません。
		first_ini();//最初の初期化
}
以上の①から④までの解説をおねがいします!

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 16:10
by non
まず、基本的なことの確認なのですが、
126行から140行までは常に繰り返しているということは理解できていますか?
途中でキー入力待ちなどで止まっていることはありません。
実行画面では、キー入力待ちで止まっているように見えるかも知れませんが・・・
わかってますか?

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 16:45
by まみ
non さんが書きました:まず、基本的なことの確認なのですが、
126行から140行までは常に繰り返しているということは理解できていますか?
途中でキー入力待ちなどで止まっていることはありません。
実行画面では、キー入力待ちで止まっているように見えるかも知れませんが・・・
わかってますか?
すみません。126から140までの処理は、そのプログラムの上に書いてる関数をループしているのはわかるのですが

実行画面でキー入力待ちで止まっていないとはわかりませんでした。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 18:36
by non
状態遷移という考え方を先に理解した方がよいと思います。
検索して、どういうものか調べてみましょう。
例えば
http://blog.goo.ne.jp/uiweo8864/e/91653 ... 80e019275b
など、もっとわかりやすく書かかれたページもあるかも知れませんが・・・

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 19:05
by まみ
non さんが書きました:状態遷移という考え方を先に理解した方がよいと思います。
検索して、どういうものか調べてみましょう。
例えば
http://blog.goo.ne.jp/uiweo8864/e/91653 ... 80e019275b
など、もっとわかりやすく書かかれたページもあるかも知れませんが・・・
わざわざありがとうございます!

だけどここに書いてあるのは難しすぎてよくわかりません。

わかったのは

停止状態

再生

再生状態

再生

ポーズ状態→再生→再生状態→停止→停止状態

停止

停止状態

こんな感じでわかったのですが

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 19:12
by non
状態を表すのに、sound_stateやstateが使われていることを理解してください。
そして、それらstateの値が何のときにどのような状態なのか絵を書いてみることをお勧めします。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 21:03
by まみ
わかりました。

改めて

コード:

//リセット
void reset(){
	//再生フラグがオフなら
	if(sound_state==0){
		sound_flag[0]=1;//ジャンケン・・
		sound_state=1;//再生した状態に変更
	}
	if(Key[KEY_INPUT_RETURN]==2)//エンターが押されていたら
		first_ini();//最初の初期化
}
もう一度一行一行どんな処理を行っているか教えてくれませんか?
そうすればわかると思うんです。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 21:29
by non
逆質問です。
if(sound_state==0)
sound_stateが0ということは、どういう状態ですか?
また、sound_stateが0になっている時間はどれくらいの時間ですか?

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 21:41
by ISLe
変数に値を代入したら、変数はその値を記憶するだけです。
何も起きません。

変数はただのメモとしての役割りしかありません。

sound_stateに1を代入した途端に再生されるわけではありません。
このプログラムを書いたひとは再生中のときはsound_stateを1にしておくと決めたようです。
ただそれだけです。

そして実際にはsound_stateはそのような使われ方をしていません。
意味としては合っていますが極々狭い意味で使われています。
sound_stateの正確な意味を理解するにはsound_stateが使われているところを追いかけるだけでも理解できると思います。

一行一行理解するのも大切ですが、個々の変数に着目して追いかける訓練をしたほうがプログラムを速く理解できるようになりますよ。
まずsound_flagがどういう役割りをしているか、次にsound_stateがどういう役割りをしているかを考えてみてください。
どんな値を取りうるかと、それぞれの値のときの意味と、それぞれどんなときに値が変化するかを箇条書きしてみてください。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 22:37
by softya(ソフト屋)
私が思う一番理解する方法は書いてあるプログラムの内容をできるだけ短い日本語にまとめてみる事です。今の一行ごとのコメントではなく、その命令の組み合わせで起こる動作を日本語にすることですね。
これは小説を要約することに似ていると思います。つまり、意味をつかんでいないと短くまとめることが出来ないと言うことです。
ここでまとめた内容を質問すれば合っているか回答がよせられると思います。

次にソースコードを見ずにその日本語だけ見てプログラムを書いてみる事です。これで同じ動作をするものが出来たなら理解できたと言うことですね。
ISLeさんなども書かれていることですが全体の流れの中での部分部分の役割を理解しないと全体として何をしているかは分かって来ません。なので個々の理解と全体の理解は同時に進めないといけません。理解できた様に思うのが初心者が一番陥りやすい罠ですので気をつけてみてください。

それと質問毎に名前を変えられているようですが統一していただくと過去にどんな質問をしていたか参照できるので、その人の傾向が分かるため回答しやすくなります。
フォーラムルールにありますように「なるべくオリジナルな名前を決め、以後同じ名前を使い続けてください。」をお守り下さい。
http://dixq.net/board/board.html

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月27日(金) 23:53
by たかぎ
本当にソースコードが理解できないときは、私は次のようにしています。
分からない箇所のソースコードを1行ずつ消していくのです(コメントアウトでも可)。
単純に消すだけではコンパイルエラーになるかもしれないので、そこは適当に調整する必要はあります。

1行ずつ消したとき、どんな影響が出るかを調べれば、その行が何のためにあるのかが分かりやすくなります。
ゲームの場合は影響が比較的分かりやすいので、この方法はかなり有効だと思います。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月28日(土) 18:28
by まみ
みなさん解説してくれて本当にありがとうございます。

私は、C言語に関してあまり知識がなくて
本当にどんな処理をしているのか理解できないんです。

ただなんとなくはわかるんですけど、それは言葉ではあまり表せないもので。

自分勝手ですいませんが
私の理解の仕方は、
プログラム一行一行に解説をしてもらって
それで自分で理解することだったのです。

みなさんが私のためにヒントを教えてくれているのはわかるのですが
それでも理解することが出来ないときもあります。

(そふとやさんすいません。今度から気をつけます。)

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月28日(土) 18:51
by softya(ソフト屋)
目的がDXライブラリでゲームプログラムを作ることで他の言語へ移植するのではない場合、C++か最低限C言語の理解は不可欠です。
同様にプログラムの考え方やアルゴリズムの理解も不可欠で、本当に理解できているならサンプルと同じものが書けるように成っているはずです。
もし出来ないとしたら、どこか理解方法に問題があると思います。

何処に目的を置くかですが、やはり実現したいことのために最低限の必要な知識はあるものです。
みなさんが色々な教え方をしようとしているのは、プログラムの考え方を理解してもらうためにやっていますので一行一行だけに拘るよりも大きな視点を持ってみてください。
プログラムはよくミクロの視点とマクロの視点を行き来して組むと言われます。一行一行はミクロの視点で、sound_stateのような仕組みは全体的なマクロの視点の理解です。
両方が組み合わさって全体的なプログラムの流れを構成しますので、ぜひ両方を理解して下さい。
まみ さんが書きました:(そふとやさんすいません。今度から気をつけます。)
名前の件はこれから固定していただけば結構ですので、よろしくお願いします。

Re: このプログラムがどんな処理をしているのか理解できません。

Posted: 2012年1月29日(日) 01:35
by ISLe
【reset関数のミクロな解説】
  1. sound_state変数が記憶している値が0と等しいとき、
    sound_flag配列変数の0番要素に1を代入し、
    sound_state変数に1を代入します。
  2. Key配列変数のKEY_INPUT_RETURN番要素が2と等しいとき、
    first_ini関数を呼び出します。
【理解できているかどうかを試す質問】 ※日本語で端的に答えてください。
  • reset関数においてsound_state変数が0になっているのはどんなときですか。
  • sound_flag配列変数の0番要素が1になるのはどんなときですか。