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

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

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

#1

投稿記事 by rayor » 8年前

いつもお世話になっています。今度はパソコンと言葉のしり取りのゲームについての質問です。

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

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

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)に、”あなたの負けです”、”コンピュータの負けです”に関しては、判定がどういうふうに行われているのでしょうか。条件としては、コードには何も書かれていないようです。実行のループを脱出したとたん、自然にこうなるでしょうか。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

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

#2

投稿記事 by beatle » 8年前

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

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

rayor

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

#3

投稿記事 by rayor » 8年前

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

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

non
記事: 1097
登録日時: 9年前

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

#4

投稿記事 by non » 8年前

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

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

#5

投稿記事 by softya(ソフト屋) » 8年前

マルチポストですので、相互リンクをお願いします。詳しくはフォーラムルールに記載されています。 http://dixq.net/board/board.html
http://detail.chiebukuro.yahoo.co.jp/qa ... 1275378117
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

non
記事: 1097
登録日時: 9年前

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

#6

投稿記事 by non » 8年前

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);
}
non

hss12
記事: 40
登録日時: 8年前

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

#7

投稿記事 by hss12 » 8年前

コード:

#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) をみたさないのであなたの負けですと表示されます。

rayor

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

#8

投稿記事 by rayor » 8年前

ご回答ありがとうございます。今の時点でわからないことをまとめて、コードの傍らに表記しておきます。

コード:

#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;
}


rayor

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

#9

投稿記事 by rayor » 8年前

修正:間違えて、このトピックはすでに解決していますって選んでしまったようです。実はまだまだ問題点があります。ご回答を祈ります。

hss12
記事: 40
登録日時: 8年前

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

#10

投稿記事 by hss12 » 8年前

知恵袋と同じ方でしたら相互リンクをお願いします。
ここのアドレスを知恵袋に貼ってください。

まず関数と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; となりあなたの負けですと表示さるわけですね。

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

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

#11

投稿記事 by bitter_fox » 8年前

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

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

rayor

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

#12

投稿記事 by rayor » 8年前

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)のところでしょうか。

rayor

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

#13

投稿記事 by rayor » 8年前

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)のところでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

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

#14

投稿記事 by softya(ソフト屋) » 8年前

どうでも良いことだと思われているみたいなので再度書かせて頂きます。
ここのフォーラムルールにおいて、マルチポストは禁止されています。

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

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


問題があるからルールになっておりますので、ご理解をお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

rayor

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

#15

投稿記事 by rayor » 8年前

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

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

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


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

rayor

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

#16

投稿記事 by rayor » 8年前

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

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

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


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

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

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

#17

投稿記事 by bitter_fox » 8年前

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はポインタではなく配列だったので修正。

rayor

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

#18

投稿記事 by rayor » 8年前

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 と、一か所、引用されているので、そう思います。でも実際どうだろうかよくわかりません。

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

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

#19

投稿記事 by bitter_fox » 8年前

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が処理の流れ上のそれ以降でどういった風に使われているのかにも注目してください。

閉鎖

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