1989年開業 情報工学部門 文部科学省登録番号 第22082号 公益社団法人日本技術士会会員 東大阪商工会議所会員

≫サンプルプログラム一覧 

オープンソース/C言語サンプルプログラム 小倉百人一首

●小倉百人一首の歌をコンピュータがランダムに10首選びます。
●その中の1首をコンピュータが選びます。
●選んだ10首の歌番号と下の句を表示します。
●選んだ1首の上の句を表示します。
●上の句に対応する下の句の歌番号を入力します。
●正しい歌番号が入力されると、新しく10首を選んでゲームが続きます。
●文字"0"が入力されるとプログラムを終了します。
●Ctr+Cキーで強制終了できます。
●和歌はテキストファイル ogura100.txt に保存されています
 ※1首は1行で保存され、上の句、下の句、読み人はTab文字で区切られています。
  ≫ソースファイルのダウンロード: ogura100.C
  ≫テキストファイルのダウンロード:ogura100.txt
【問題】
●このプログラムでは、場の10首に同じ歌が選ばれることがあります。
 同じ歌が選ばれないように改良してみよう。
  ≫解答例のダウンロード: ogura100-2.C
●正解の後、上の句、下の句、詠み人を表示するように改造してみよう。
 ≫解答例のダウンロード: ogura100-3.C

/******************/
/*  小倉百人一首  */
/******************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

void  REDtxt(int*);                                     // テキストファイルを読む
void  explode(char*,char*,int);                         // 項目を取り出す

char  kami[100][64];                                    // 上の句
char  simo[100][64];                                    // 下の句
char  yomi[100][64];                                    // 詠み人
int   utaNo;                                            // 歌番号
int   utaNoB[10];                                       // 場の歌番号

void  main( )
{
    char c[128];
    int  N,i,j;

    printf("\n##################\n");
    printf("\n#  小倉百人一首  #\n");
    printf("\n##################\n");
    printf("\n 0を入力すると終了します\n\n");
    fflush(stdout);

    srand(time(NULL));                                  // 乱数の準備

    REDtxt(&N);                                         // テキストファイルを読む
    if ( N==0 ) goto END;

    while ( 1 )
      {
        //--10首選択--
        for( i=0; i<10; i++ )
          {
            utaNoB[i]=rand( )%100+1;                    // 歌番号計算
          }

        //--読み札選択--
        utaNo=utaNoB[rand( )%10];                       // 読み札歌番号計算

        // 下の句表示
        printf("\n【下の句】"); fflush(stdout);
        for( i=0; i<10; i++ )
          {
            j=utaNoB[i]-1;                              // 場の歌添え字
            printf("\n%3d: %s",j+1,&simo[j][0]); fflush(stdout);
          }

        // 上の句表示
        printf("\n\n\n【上の句】"); fflush(stdout);
        printf("\n %s\n",&kami[utaNo-1][0]); fflush(stdout);

        while( 1 )
          {
            printf("\n歌番号: "); fflush(stdout);
            gets(c);                                    // 歌番号入力
            if ( strcmp(c,"0")==0 )  break;

            if ( atoi(c)==utaNo )                       // 歌番号が一致
              {
                Beep(660,100); Beep(523,200);           // ミド
                break;
              }

            Beep(440,100); Sleep(50); Beep(440,300);    // ドド
            printf("お手つきです\n\n"); fflush(stdout);
            continue;
          }

        printf("\n----------------------------------\n");
        fflush(stdout);

        if ( strcmp(c,"0")==0 ) break;
      }

END: ;
}


void  REDtxt(
/*--------------------------*/
/*  テキストファイルを読む  */
/*--------------------------*/
int  *N)    // 行数
{
    FILE *fp=NULL;
    char  buf[512],*cp;
    int   i;

    *N=0;
    memset(&kami[0][0],'\0',6400);                      // 上の句
    memset(&simo[0][0],'\0',6400);                      // 下の句
    memset(&yomi[0][0],'\0',6400);                      // 詠み人

    fp=fopen("ogura100.txt","r");                       // テキストファイル開く
    if ( fp==NULL ) goto END;

    for( i=0; i<100; i++ )
      {
        cp=fgets(buf,500,fp);                           // テキストファイル読む
        if ( cp==NULL ) break;                          // EOF

        explode("\t",buf,i);                            // 項目を取り出す
        (*N)++;
      }

END: if ( fp!=NULL ) fclose(fp);                        // テキストファイル閉じる
}


void  explode(
/*------------------------------------*/
/*  テキストデータから項目を取り出す  */
/*------------------------------------*/
char *kugiri,    // 区切り文字
char *buf,       // テキスト1行
int  i)
{
    char *cp0,*cp;    // 文字列アドレス
    int  len;

    len=strlen(buf);                                    // 文字列長さ
    if ( len==0 ) goto END;
    if ( buf[len-1]=='\n' ) buf[len-1]='\0';            // 改行文字をnullに

    //--上の句--
    cp0=buf;
    cp=strstr(cp0,kugiri);                              // 区切り文字検索
    if ( cp==NULL ) goto END;
    len=cp-cp0;                                         // 項目の文字数
    memcpy(&kami[i][0],cp0,len);                        // 上の句

    //--下の句--
    cp0=cp+1;                                           // 次の文字のアドレス
    cp=strstr(cp0,kugiri);                              // 区切り文字検索
    if ( cp==NULL ) goto END;
    len=cp-cp0;                                         // 項目の文字数
    memcpy(&simo[i][0],cp0,len);                        // 下の句

    //--詠み人--
    cp0=cp+1;                                           // 次の文字のアドレス
    strcpy(&yomi[i][0],cp0);                            // 詠み人

END: ;
}
   

※SSL暗号化通信対応

佐伯英子技術士事務所 〒542-0073 大阪市中央区日本橋 1-14-13 サンオフィス日本橋601  E-mail: info@saeki-pe.com