ページ 11

パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月13日(日) 17:34
by rayor
いつもお世話になっています。今度はパソコンと言葉のしり取りのゲームについての質問です。

問題に関する材料は以下の通りです。解答と解説は最後のページになります。

長い質問文になってすみません。

http://www.fastpic.jp/images/127/2782719258.jpg

http://www.fastpic.jp/images/506/5610951059.jpg

http://www.fastpic.jp/images/616/3611762173.jpg

http://www.fastpic.jp/images/767/8776179663.jpg

http://www.fastpic.jp/images/330/9053831204.jpg

http://www.fastpic.jp/images/625/2592764379.jpg

質問は以下のようです。

47)なぜインクリメントする必要がありますか。

48)文字列の長さは、この場合、どういう役割を果たしているのでしょうか。

50)lst[cnt].wdはどういう意味でしょうか。

51)説明全体がわかりません。

なお、プログラムの中核の部分(頁17-18)に、”あなたの負けです”、”コンピュータの負けです”に関しては、判定がどういうふうに行われているのでしょうか。条件としては、コードには何も書かれていないようです。実行のループを脱出したとたん、自然にこうなるでしょうか。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月13日(日) 18:02
by beatle
このプログラム、rayorさん自身で動かしてみましたか?
まずは正しい選択肢を埋めた状態で自分で動かし、次に疑問となっている部分を変更してみて、どういう動作になるのかを追っていけば何か分かるかもしれませんよ。
例えば(47)でのcntのインクリメントは必要なのか、という疑問は、cntのインクリメントをしないように改造してみたら何か分かるかもしれません。

プログラムの学習は本に印刷されたソースコードを見るだけじゃダメです。自分で入力して実際に動かし、改造してまた動かすことが大切です。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月13日(日) 18:19
by rayor
beatle さんが書きました:このプログラム、rayorさん自身で動かしてみましたか?
まずは正しい選択肢を埋めた状態で自分で動かし、次に疑問となっている部分を変更してみて、どういう動作になるのかを追っていけば何か分かるかもしれませんよ。
例えば(47)でのcntのインクリメントは必要なのか、という疑問は、cntのインクリメントをしないように改造してみたら何か分かるかもしれません。

プログラムの学習は本に印刷されたソースコードを見るだけじゃダメです。自分で入力して実際に動かし、改造してまた動かすことが大切です。
ご回答ありがとうございます。このプログラムには単語ファイル(word.dat)が必要なので、コードだけを実行しても、入力ファイルがオープンできませんって終わるのではないでしょうか。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月13日(日) 18:29
by non
いくつかデータを作ればいいでしょうね。
それより、かなり詳しく解説が書かれていますよね。まず、(47)ですが、本当にインクリメントしなければいけない理由がわからないのですか?
例えば、データを読み込んで配列に格納するプログラムがわからないってことですよね。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月13日(日) 18:32
by softya(ソフト屋)
マルチポストですので、相互リンクをお願いします。詳しくはフォーラムルールに記載されています。 http://dixq.net/board/board.html
http://detail.chiebukuro.yahoo.co.jp/qa ... 1275378117

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月13日(日) 18:53
by non
cnt++のサンプルを作りました。
入力された文字列を配列に格納しています。
cntをインクリメントしなければ同じ場所(data[0]に)上書き格納されていきますよね。
理解できますか?

コード:

#include <stdio.h>
 
int main(void)
{
	char data[301][11];
	int i;
	int cnt=0;
	while(scanf("%s",data[cnt])!=EOF){
		cnt++; //これが必要な理由がわかりますか?
	}
	for(i=0;i<cnt;i++)
		puts(data[i]);
	return (0);
}

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月14日(月) 13:52
by hss12

コード:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int wd_chk(char m_wd[11], int last); /* プレイヤーの負けの判断 */
int wd_scr(char m_lt); /* コンピュータの単語の検索 */

struct w_lst {
	char wd[11]; /* 単語 */
	int flg; /* フラグ */
} lst[301];

int cnt; /* 登録件数 */

int main(void)
{
	FILE *fp;
	int st = 301;
	char m_wd[11];

	/* ファイル入力 */
	if ((fp = fopen("word.dat", "r")) == NULL) {
		printf("入力ファイルがオープンできません\n");
		return -1;
	}
	cnt = 0;
	while (fscanf(fp, "%s", lst[cnt].wd) != EOF) {
		lst[cnt].flg = 0; /* 47 */
		cnt++; /* 分けて表記 */
	}
	fclose(fp);

	while (st != -1) {
		printf("あなたの番です:");
		scanf("%s", m_wd);
		st = wd_chk(m_wd, st);
		if (st == 0) {
			st = wd_scr(m_wd[strlen(m_wd) - 1]); /* 48 */
		} else {
			printf("あなたの負けです\n");
		}
	}
	return 0;
}

/* プレイヤーの負けの判定 */
int wd_chk(char m_wd[11], int last)
{
	int i;

	if (m_wd[0] == '.') {
		return -1;
	} else if (last < 301 && m_wd[0] != lst[last].wd[strlen(lst[last].wd) -1]) {
		return -1;
	} else {
		for (i = 0; i < cnt; i++) {
			if (strcmp(lst[i].wd, m_wd) == 0) { /* 49 */
				if (lst[i].flg == 1) {
					return -1;
				} else {
					lst[i].flg = 1;
					return 0;
				}
			}
		}
	}
	strcpy(lst[cnt].wd, m_wd); /* 50 */
	lst[cnt].flg = 1;
	cnt++; /* 分けて表記 */
	return 0;
}

/* コンピュータの単語の検索 */ 
int wd_scr(char m_lt)
{
	int i;
	for (i = 0; i < cnt; i++) {
		if (lst[i].wd[0] == m_lt && lst[i].flg == 0) { /* 51 */
			printf("コンピュータの番です:%s\n", lst[i].wd);
			lst[i].flg = 1;
			return i;
		}
	}
	printf("コンピュータの負けです\n");
	return -1;
}
47)
使用した単語はフラグを1にして判定しますが、まずすべての単語のフラグを0にします
lst[0].flg = 0;
lst[1].flg = 0;
lst[2].flg = 0;
・・・となるわけです。

48)
catという文字列の場合
+-----------+
| 0 | 1 | 2 | //配列
+-----------+
| c | a | t |
+-----------+
このように入っていますが、しりとりがしたいので
この場合配列の2番の文字がほしいわけです。
ところがstrlen関数を使うと文字数の3になるため
1を引いて2にしてtの文字を取得しています。

50)
しりとりは同じ単語を使用したら負けなので
使用した単語を配列に登録しているのですが
strcpy関数はプレイヤーが入力した単語 m_wd を
lst[cnt].wd 配列に文字列をコピーします。

51)
プレイヤーが入力した単語の最後の文字と
word.datのデータの単語の最初の文字が一致したものがある(しりとりができる)

まだ使用していない(フラグが0)の単語がある
の両方をみたしていればコンピュータは文字を表示できます。

もし両方をみたすものがない場合コンピュータの負けですと表示されてしまいます。
関数のifの中に return i; が書いてあるので負けでない場合は関数を抜けます。

プレイヤーのほうも前に使用した単語(フラグが1の単語)を使ってしまうと
return -1となってしまい if(st == 0) をみたさないのであなたの負けですと表示されます。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月14日(月) 17:58
by rayor
ご回答ありがとうございます。今の時点でわからないことをまとめて、コードの傍らに表記しておきます。

コード:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int wd_chk(char m_wd[11], int last); /* プレイヤーの負けの判断 */
int wd_scr(char m_lt); /* コンピュータの単語の検索 */
 
struct w_lst {
    char wd[11]; /* 単語 */
    int flg; /* フラグ */
} lst[301];
 
int cnt; /* 登録件数 */
 
int main(void)
{
    FILE *fp;
    int st = 301;
    char m_wd[11];
 
    /* ファイル入力 */
    if ((fp = fopen("word.dat", "r")) == NULL) {
        printf("入力ファイルがオープンできません\n");
        return -1;
    }
    cnt = 0;
    while (fscanf(fp, "%s", lst[cnt].wd) != EOF) {
        lst[cnt].flg = 0; /* 47 */
        cnt++; /* 分けて表記 */
    }
    fclose(fp);
 
    while (st != -1) {
        printf("あなたの番です:");
        scanf("%s", m_wd);
        st = wd_chk(m_wd, st);
        if (st == 0) {  /* st==0の条件はどういう役割を果たしているのでしょうか */
            st = wd_scr(m_wd[strlen(m_wd) - 1]); /* これは最後の文字を取得しているのでしょうか*/ 
        } else {
            printf("あなたの負けです\n");
        }
    }
    return 0;
}
 
/* プレイヤーの負けの判定 */
int wd_chk(char m_wd[11], int last)
{
    int i;
 
    if (m_wd[0] == '.') {
        return -1;
    } else if (last < 301 && m_wd[0] != lst[last].wd[strlen(lst[last].wd) -1]) {
        return -1;
    } else {
        for (i = 0; i < cnt; i++) {
            if (strcmp(lst[i].wd, m_wd) == 0) { /* 49 */
                if (lst[i].flg == 1) {
                    return -1;
                } else {
                    lst[i].flg = 1;
                    return 0;
                }
            }
        }
    }
    strcpy(lst[cnt].wd, m_wd); /* 50 */
    lst[cnt].flg = 1;
    cnt++; /* 分けて表記 */
    return 0;
}
 
/* コンピュータの単語の検索 */ 
int wd_scr(char m_lt)
{
    int i;
    for (i = 0; i < cnt; i++) {
        if (lst[i].wd[0] == m_lt && lst[i].flg == 0) { /* 51 */
            printf("コンピュータの番です:%s\n", lst[i].wd);
            lst[i].flg = 1;
            return i;/*return i の意味は今いちわかりません */
        }
    }
    printf("コンピュータの負けです\n"); /* ”あなたの負けです”、”コンピュータの負けです”に関しては、判定がどういうふうに行われているのでしょうか。条件としては、この行しか書かれていないようです。実行のループを脱出したとたん、自然にこうなるでしょうか*/
    return -1;
}


Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月14日(月) 18:05
by rayor
修正:間違えて、このトピックはすでに解決していますって選んでしまったようです。実はまだまだ問題点があります。ご回答を祈ります。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月14日(月) 19:45
by hss12
知恵袋と同じ方でしたら相互リンクをお願いします。
ここのアドレスを知恵袋に貼ってください。

まず関数とreturnについては理解されてるのでしょうか。

>st==0の条件はどういう役割を果たしているのでしょうか
その上の st = wd_chk(m_wd, st);
で代入されているのですが、プレイヤーの負けの判定関数で
プレイヤーの負け(フラグが1の単語を使用など)だと return -1; となり
st = -1; となりあなたの負けですと表示されます。
逆にしりとりができれば return 0; なので st = 0; で
あなたの負けですは表示されません。

>これは最後の文字を取得しているのでしょうか
そうですね。入力された最後の文字がコンピュータの単語の検索関数に渡されます。
51)の条件式によりしりとりができれば return i;
しりとりができなければコンピュータの負けですと表示されます。
しりとりができる場合は return i; で関数を抜けるのでコンピュータの負けですの表示はされません。
return i; なので main関数は st = i; となるわけですが
ここで st = wd_chk(m_wd, st); となっており
プレイヤーの負けの判定関数は
int wd_chk(char m_wd[11], int last)
なので i の数値は last に代入されます。
lst[last].wd と使われているのでコンピュータが表示した単語が何かを取得するためのものですね。
lst[last].wd[strlen(lst[last].wd) -1] はコンピュータが表示した単語の最後の文字が取得できます。
この文字とプレイヤーが入力した単語の最初の文字を比較してしりとりができているか判断しています。
もし一致していないと return -1; になっているので main関数で
st = -1; となりあなたの負けですと表示さるわけですね。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月14日(月) 20:34
by bitter_fox
rayor さんが書きました:ご回答ありがとうございます。今の時点でわからないことをまとめて、コードの傍らに表記しておきます。

コード:

 
/* コンピュータの単語の検索 */ 
int wd_scr(char m_lt) // (1)
{
    int i;
    for (i = 0; i < cnt; i++) { // (2)
        if (lst[i].wd[0] == m_lt && lst[i].flg == 0) { /* 51 */ // (3)
            printf("コンピュータの番です:%s\n", lst[i].wd);  // (4)
            lst[i].flg = 1; // (5)
            return i;/*return i の意味は今いちわかりません */ // (6)
        } // (*3)
    } // (*2)
    printf("コンピュータの負けです\n"); /* ”あなたの負けです”、”コンピュータの負けです”に関しては、判定がどういうふうに行われているのでしょうか。条件としては、この行しか書かれていないようです。実行のループを脱出したとたん、自然にこうなるでしょうか*/ // (7)
    return -1;
}

どういった処理が行われているのか分からないときは自分がコンピュータになったようにコンピュータの気持ちで一ステップずつ見ていきましょう。
特にこのwd_scr関数はそれを行えば簡単に理解できるはずです。

lstにはcnt個分、コンピュータがしりとりに使う単語と、使用済みかどうかを判別するフラグが入っています。
このことを踏まえてwd_scrを見ていきましょう。

コード:

(1):引数にm_ltが渡される。
(2):cnt回ループする。ループカウンタはi。処理は(2)から(*2)まで
まず、ここまでは良いですね?

ここからm_ltがどういった役割で使われているのかも気にしながら続きを見ていきましょう。
まずはコンピュータが答えを見つけることが出来た場合です

コード:

・・・
(3):lst[i].wd[0]とm_ltが同じ、かつ、lst[i].flgが0のならば(3)から(*3)までを実行
lst[i]と言うのは単語リストの中の現在注目している要素です。
それのwdと言うのは、その単語の事で、0番目の要素はその先頭の要素ですので、単語の先頭の文字です。
これをm_ltと比較しています。しりとりで答えるときに先頭と比較するのはなんでしょう?
しりとりをしたことがあればわかりますね。相手が答えた単語の末尾の文字です。
m_ltは相手が答えた単語の末尾の文字でした。こういった風にただ単に何をやっているのかではなくその裏にある理由も考えながら、処理の意図や引数、戻り値の意図を把握していきましょう。

同じく、それのflgと言うのは使用済みかどうかを表すフラグです。そして、lst[i].wd[0] == m_ltが真、かつ、それが0の時に(3)から(*3)までを実行しています。((3)~(*3)はコンピュータの答えが見つかった時の処理)
ここから導けるのはlst[i].flgが0の時は使用することができ(未使用)、0以外の時は使用できない(使用済み)ということになります。

(4):コンピュータの答えが見つかったのでその答えを出力。この時の答えは当然lst[i].wd
(5):二回同じ単語は使えないように使用済みにする
(6):iを返す。
ここでiを返すのはなぜでしょう?
これを理解するにはwd_scr関数だけを見ていても解決しません。
と言うのも、戻り値と言うのは呼び出し元で使われるのですから、呼び出し元を見てみましょう。この関数以外の解析はrayorさん自身が行ってみてください。
なぜ返すかと言う質問の答えとしては、コンピュータの次に相手(プレイヤー)が答えた単語が「しりとり」になっているかを判断するためにはコンピュータがどの単語を答えたのかを知っておく必要がありますよね?
そのためにiを返しています。(この時、iはlst内の答えた要素の添え字を表しています。)

コンピュータが答えることが出来たのでので、この関数を抜けます。
さて、ここまで見た限りではもしもコンピュータが答えを見つけることが出来た場合はiを返して関数を抜けるようです。
では(7)に来るというのはどういうときでしょう?
これは簡単です。コンピュータが答えを見つけることが出来た場合にのみfor内で関数を抜けるわけですから、そうでない場合のみ(7)に来ます。
つまり、コンピュータが最後まで答えを見つけることが出来なかった場合です。

wd_scr関数を考え方も交えながら読み解いてみました。
読み解くときは演繹的に読み解いてくのがベストです。
また、処理を理解するには単に処理が何をやっているのかではなく、処理がどういった意図をもっているのかまで気を配る必要があります。
時には広い視点で見なければ分からないこともあります。

このプログラムは関数名や変数名が分かりにくい名前になっていて読み解きにくいですが頑張って実際に読み解いてみてください。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月15日(火) 17:11
by rayor
bitter_fox さんが書きました:
rayor さんが書きました:ご回答ありがとうございます。今の時点でわからないことをまとめて、コードの傍らに表記しておきます。

コード:

 
/* コンピュータの単語の検索 */ 
int wd_scr(char m_lt) // (1)
{
    int i;
    for (i = 0; i < cnt; i++) { // (2)
        if (lst[i].wd[0] == m_lt && lst[i].flg == 0) { /* 51 */ // (3)
            printf("コンピュータの番です:%s\n", lst[i].wd);  // (4)
            lst[i].flg = 1; // (5)
            return i;/*return i の意味は今いちわかりません */ // (6)
        } // (*3)
    } // (*2)
    printf("コンピュータの負けです\n"); /* ”あなたの負けです”、”コンピュータの負けです”に関しては、判定がどういうふうに行われているのでしょうか。条件としては、この行しか書かれていないようです。実行のループを脱出したとたん、自然にこうなるでしょうか*/ // (7)
    return -1;
}

どういった処理が行われているのか分からないときは自分がコンピュータになったようにコンピュータの気持ちで一ステップずつ見ていきましょう。
特にこのwd_scr関数はそれを行えば簡単に理解できるはずです。

lstにはcnt個分、コンピュータがしりとりに使う単語と、使用済みかどうかを判別するフラグが入っています。
このことを踏まえてwd_scrを見ていきましょう。

コード:

(1):引数にm_ltが渡される。
(2):cnt回ループする。ループカウンタはi。処理は(2)から(*2)まで
まず、ここまでは良いですね?

ここからm_ltがどういった役割で使われているのかも気にしながら続きを見ていきましょう。
まずはコンピュータが答えを見つけることが出来た場合です

コード:

・・・
(3):lst[i].wd[0]とm_ltが同じ、かつ、lst[i].flgが0のならば(3)から(*3)までを実行
lst[i]と言うのは単語リストの中の現在注目している要素です。
それのwdと言うのは、その単語の事で、0番目の要素はその先頭の要素ですので、単語の先頭の文字です。
これをm_ltと比較しています。しりとりで答えるときに先頭と比較するのはなんでしょう?
しりとりをしたことがあればわかりますね。相手が答えた単語の末尾の文字です。
m_ltは相手が答えた単語の末尾の文字でした。こういった風にただ単に何をやっているのかではなくその裏にある理由も考えながら、処理の意図や引数、戻り値の意図を把握していきましょう。

同じく、それのflgと言うのは使用済みかどうかを表すフラグです。そして、lst[i].wd[0] == m_ltが真、かつ、それが0の時に(3)から(*3)までを実行しています。((3)~(*3)はコンピュータの答えが見つかった時の処理)
ここから導けるのはlst[i].flgが0の時は使用することができ(未使用)、0以外の時は使用できない(使用済み)ということになります。

(4):コンピュータの答えが見つかったのでその答えを出力。この時の答えは当然lst[i].wd
(5):二回同じ単語は使えないように使用済みにする
(6):iを返す。
ここでiを返すのはなぜでしょう?
これを理解するにはwd_scr関数だけを見ていても解決しません。
と言うのも、戻り値と言うのは呼び出し元で使われるのですから、呼び出し元を見てみましょう。この関数以外の解析はrayorさん自身が行ってみてください。
なぜ返すかと言う質問の答えとしては、コンピュータの次に相手(プレイヤー)が答えた単語が「しりとり」になっているかを判断するためにはコンピュータがどの単語を答えたのかを知っておく必要がありますよね?
そのためにiを返しています。(この時、iはlst内の答えた要素の添え字を表しています。)

コンピュータが答えることが出来たのでので、この関数を抜けます。
さて、ここまで見た限りではもしもコンピュータが答えを見つけることが出来た場合はiを返して関数を抜けるようです。
では(7)に来るというのはどういうときでしょう?
これは簡単です。コンピュータが答えを見つけることが出来た場合にのみfor内で関数を抜けるわけですから、そうでない場合のみ(7)に来ます。
つまり、コンピュータが最後まで答えを見つけることが出来なかった場合です。

wd_scr関数を考え方も交えながら読み解いてみました。
読み解くときは演繹的に読み解いてくのがベストです。
また、処理を理解するには単に処理が何をやっているのかではなく、処理がどういった意図をもっているのかまで気を配る必要があります。
時には広い視点で見なければ分からないこともあります。

このプログラムは関数名や変数名が分かりにくい名前になっていて読み解きにくいですが頑張って実際に読み解いてみてください。
丁寧なご回答ありがとうございます。
文法的には、lst.wd[0]とか、lst.flgとか記してあるが、どうしてこういうふうに表記できるのでしょうか。

また、return iは呼び出し元で使用されるとされるようですが、それは48)のところでしょうか。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月15日(火) 17:12
by rayor
bitter_fox さんが書きました:
rayor さんが書きました:ご回答ありがとうございます。今の時点でわからないことをまとめて、コードの傍らに表記しておきます。

コード:

 
/* コンピュータの単語の検索 */ 
int wd_scr(char m_lt) // (1)
{
    int i;
    for (i = 0; i < cnt; i++) { // (2)
        if (lst[i].wd[0] == m_lt && lst[i].flg == 0) { /* 51 */ // (3)
            printf("コンピュータの番です:%s\n", lst[i].wd);  // (4)
            lst[i].flg = 1; // (5)
            return i;/*return i の意味は今いちわかりません */ // (6)
        } // (*3)
    } // (*2)
    printf("コンピュータの負けです\n"); /* ”あなたの負けです”、”コンピュータの負けです”に関しては、判定がどういうふうに行われているのでしょうか。条件としては、この行しか書かれていないようです。実行のループを脱出したとたん、自然にこうなるでしょうか*/ // (7)
    return -1;
}

どういった処理が行われているのか分からないときは自分がコンピュータになったようにコンピュータの気持ちで一ステップずつ見ていきましょう。
特にこのwd_scr関数はそれを行えば簡単に理解できるはずです。

lstにはcnt個分、コンピュータがしりとりに使う単語と、使用済みかどうかを判別するフラグが入っています。
このことを踏まえてwd_scrを見ていきましょう。

コード:

(1):引数にm_ltが渡される。
(2):cnt回ループする。ループカウンタはi。処理は(2)から(*2)まで
まず、ここまでは良いですね?

ここからm_ltがどういった役割で使われているのかも気にしながら続きを見ていきましょう。
まずはコンピュータが答えを見つけることが出来た場合です

コード:

・・・
(3):lst[i].wd[0]とm_ltが同じ、かつ、lst[i].flgが0のならば(3)から(*3)までを実行
lst[i]と言うのは単語リストの中の現在注目している要素です。
それのwdと言うのは、その単語の事で、0番目の要素はその先頭の要素ですので、単語の先頭の文字です。
これをm_ltと比較しています。しりとりで答えるときに先頭と比較するのはなんでしょう?
しりとりをしたことがあればわかりますね。相手が答えた単語の末尾の文字です。
m_ltは相手が答えた単語の末尾の文字でした。こういった風にただ単に何をやっているのかではなくその裏にある理由も考えながら、処理の意図や引数、戻り値の意図を把握していきましょう。

同じく、それのflgと言うのは使用済みかどうかを表すフラグです。そして、lst[i].wd[0] == m_ltが真、かつ、それが0の時に(3)から(*3)までを実行しています。((3)~(*3)はコンピュータの答えが見つかった時の処理)
ここから導けるのはlst[i].flgが0の時は使用することができ(未使用)、0以外の時は使用できない(使用済み)ということになります。

(4):コンピュータの答えが見つかったのでその答えを出力。この時の答えは当然lst[i].wd
(5):二回同じ単語は使えないように使用済みにする
(6):iを返す。
ここでiを返すのはなぜでしょう?
これを理解するにはwd_scr関数だけを見ていても解決しません。
と言うのも、戻り値と言うのは呼び出し元で使われるのですから、呼び出し元を見てみましょう。この関数以外の解析はrayorさん自身が行ってみてください。
なぜ返すかと言う質問の答えとしては、コンピュータの次に相手(プレイヤー)が答えた単語が「しりとり」になっているかを判断するためにはコンピュータがどの単語を答えたのかを知っておく必要がありますよね?
そのためにiを返しています。(この時、iはlst内の答えた要素の添え字を表しています。)

コンピュータが答えることが出来たのでので、この関数を抜けます。
さて、ここまで見た限りではもしもコンピュータが答えを見つけることが出来た場合はiを返して関数を抜けるようです。
では(7)に来るというのはどういうときでしょう?
これは簡単です。コンピュータが答えを見つけることが出来た場合にのみfor内で関数を抜けるわけですから、そうでない場合のみ(7)に来ます。
つまり、コンピュータが最後まで答えを見つけることが出来なかった場合です。

wd_scr関数を考え方も交えながら読み解いてみました。
読み解くときは演繹的に読み解いてくのがベストです。
また、処理を理解するには単に処理が何をやっているのかではなく、処理がどういった意図をもっているのかまで気を配る必要があります。
時には広い視点で見なければ分からないこともあります。

このプログラムは関数名や変数名が分かりにくい名前になっていて読み解きにくいですが頑張って実際に読み解いてみてください。
丁寧なご回答ありがとうございます。
文法的には、lst.wd[0]とか、lst.flgとか記してあるが、どうしてこういうふうに表記できるのでしょうか。

また、return iは呼び出し元で使用されるとされるようですが、それは48)のところでしょうか。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月15日(火) 17:17
by softya(ソフト屋)
どうでも良いことだと思われているみたいなので再度書かせて頂きます。
ここのフォーラムルールにおいて、マルチポストは禁止されています。

以下引用。
相互リンクすればマルチポスト◯
相互リンクした場合のみ複数の掲示板で同じ質問をしてもOK

複数の掲示板で同じ質問をすることをマルチポストといい、大抵禁止されています。
しかし、ここでは相互リンクし、リンク先の掲示板でマルチポストが許されていれば
マルチポストはOKとしています。複数の掲示板で同じ質問をするときは相互リンクし、
どこの掲示板で同じ質問をしているか明確にして下さい。


問題があるからルールになっておりますので、ご理解をお願いします。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月15日(火) 17:44
by rayor
softya(ソフト屋) さんが書きました:どうでも良いことだと思われているみたいなので再度書かせて頂きます。
ここのフォーラムルールにおいて、マルチポストは禁止されています。

以下引用。
相互リンクすればマルチポスト◯
相互リンクした場合のみ複数の掲示板で同じ質問をしてもOK

複数の掲示板で同じ質問をすることをマルチポストといい、大抵禁止されています。
しかし、ここでは相互リンクし、リンク先の掲示板でマルチポストが許されていれば
マルチポストはOKとしています。複数の掲示板で同じ質問をするときは相互リンクし、
どこの掲示板で同じ質問をしているか明確にして下さい。


問題があるからルールになっておりますので、ご理解をお願いします。
わかりました。さっそく相互リンクを添付します。申し訳ありません。今度気を付けます。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月15日(火) 17:46
by rayor
rayor さんが書きました:
softya(ソフト屋) さんが書きました:どうでも良いことだと思われているみたいなので再度書かせて頂きます。
ここのフォーラムルールにおいて、マルチポストは禁止されています。

以下引用。
相互リンクすればマルチポスト◯
相互リンクした場合のみ複数の掲示板で同じ質問をしてもOK

複数の掲示板で同じ質問をすることをマルチポストといい、大抵禁止されています。
しかし、ここでは相互リンクし、リンク先の掲示板でマルチポストが許されていれば
マルチポストはOKとしています。複数の掲示板で同じ質問をするときは相互リンクし、
どこの掲示板で同じ質問をしているか明確にして下さい。


問題があるからルールになっておりますので、ご理解をお願いします。
わかりました。さっそく相互リンクを添付します。申し訳ありません。今度気を付けます。
http://detail.chiebukuro.yahoo.co.jp/qa ... 1275378117
相互リンクをリンク先の掲示板にもつけました。遅くなり申し訳ありません。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月15日(火) 19:56
by bitter_fox
rayor さんが書きました: 文法的には、lst.wd[0]とか、lst.flgとか記してあるが、どうしてこういうふうに表記できるのでしょうか。

lstが構造体の配列なので、lstとしたときには構造体へのアクセスと同じようなアクセスが出来ます。
http://9cguide.appspot.com/16-01.html
http://9cguide.appspot.com/16-03.html

rayor さんが書きました: また、return iは呼び出し元で使用されるとされるようですが、それは48)のところでしょうか。

どういった根拠で推論しましたか?

[hr][修正]
lstはポインタではなく配列だったので修正。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月17日(木) 01:49
by rayor
bitter_fox さんが書きました:
rayor さんが書きました: 文法的には、lst.wd[0]とか、lst.flgとか記してあるが、どうしてこういうふうに表記できるのでしょうか。

lstが構造体の配列なので、lstとしたときには構造体へのアクセスと同じようなアクセスが出来ます。
http://9cguide.appspot.com/16-01.html
http://9cguide.appspot.com/16-03.html

rayor さんが書きました: また、return iは呼び出し元で使用されるとされるようですが、それは48)のところでしょうか。

どういった根拠で推論しましたか?

[hr][修正]
lstはポインタではなく配列だったので修正。


プログラムには、lst[301]は、構造体の{}の外で宣言しているようで、それでも構造体の配列なのでしょうか。

return iは、呼び出し元で使われているので、48)のところでは、st=wd_scrc と、一か所、引用されているので、そう思います。でも実際どうだろうかよくわかりません。

Re: パソコンと言葉のしり取りのゲームについての質問です

Posted: 2011年11月17日(木) 13:19
by bitter_fox
rayor さんが書きました: プログラムには、lst[301]は、構造体の{}の外で宣言しているようで、それでも構造体の配列なのでしょうか。
構造体定義の{}内で宣言するとそれはその構造体のメンバとなります。
構造体の変数や配列・ポインタの宣言は主にその外で行います。
今回

コード:

struct w_lst {
    char wd[11]; /* 単語 */
    int flg; /* フラグ */
} lst[301];
としているのは

コード:

struct w_lst {
    char wd[11]; /* 単語 */
    int flg; /* フラグ */
};
struct w_lst lst[301];
と言った風に読み替えることが出来ます。
rayor さんが書きました: return iは、呼び出し元で使われているので、48)のところでは、st=wd_scrc と、一か所、引用されているので、そう思います。でも実際どうだろうかよくわかりません。
確かにそこでも使われてますが、wd_scrを呼び出してその戻り値をstに代入しているだけです。
代入されたstが処理の流れ上のそれ以降でどういった風に使われているのかにも注目してください。