• ベストアンサー

プレゼント交換プログラム

クリスマスパーティーのプレゼント交換のためにプログラムを書いているのですがなかなか上手くいきません。下に実装したい機能(僕の考えた解決策)と僕の書いたコードを載せておくのでアドバイスをお願いします。よろしくお願いします。 実装したい機能(僕の考えた解決策) 1.自分の持ってきたプレゼントが自分に当たらないようにする (プレゼントの番号と配列に格納する順番を一致させれば解決できると 思うのですが…) 2.全員の手にプレゼントが渡るようにする (全ての数字(例えば参加者が5人なら0~4)が割り振られたことを確認し満たしていなければやり直しにすれば解決できると思ったのですが…) ---コードここから--- #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void){ char line[100]; /* キーボード入力用汎用変数 */ int participant; /* 参加者数 */ int flag = 0; int i, j; srand(time(NULL)); /* 参加者数を入力する */ printf("参加者数: "); fgets(line, sizeof(line), stdin); sscanf(line, "%d", &participant); int number[participant]; /* プレゼントの番号 */ char name[participant]; /* 参加者の名前 */ int check[participant]; /* チェック用配列 */ /* */ for(i = 0; i < participant; i++){ printf("参加者 %d 人目の名前: ", i + 1); fgets(line, sizeof(line), stdin); sscanf(line, "%s", &name[i]); } /* */ do{ for(i = 0; i < participant; i++){ number[i] = rand() % participant; check[i] = number[i]; } for(j = 0; j < participant; j++){ for(i = 0; i < participant; i++){ if(check[i] == j){ flag += 1; } } } }while(flag != participant); /* */ for(i = 0; i < participant; i++){ printf(" %s ―\―\>プレゼント %d\n", name[i], number[i] + 1); } return 0; } ---コードここまで---

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.2

7人居たら、number配列を number[0]=0 number[1]=1 number[2]=2 number[3]=3 number[4]=4 number[5]=5 number[6]=6 と、初期化します。 次に number[0]と、number[1]~number[6]のどれかと入れ替え(乱数で選ぶ) number[1]と、number[2]~number[6]のどれかと入れ替え(乱数で選ぶ) number[2]と、number[3]~number[6]のどれかと入れ替え(乱数で選ぶ) number[3]と、number[4]~number[6]のどれかと入れ替え(乱数で選ぶ) number[4]と、number[5]~number[6]のどれかと入れ替え(乱数で選ぶ) number[5]と、number[6]と入れ替え を実行してみましょう。 あと char name[participant]; /* 参加者の名前 */ では、7人たったら「charが7バイトあるだけ」で、7人分の名前を保持する事は出来ません。 上記の不具合を修正すると、以下のようになります。 #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void){ char line[100]; /* キーボード入力用汎用変数 */ int participant; /* 参加者数 */ int i, j, k; srand(time(NULL)); /* 参加者数を入力する */ printf("参加者数: "); fgets(line, sizeof(line), stdin); sscanf(line, "%d", &participant); int *number = new int[participant]; /* プレゼントの番号 */ char **name = new char *[participant]; /* 参加者の名前 */ for(i = 0; i < participant; i++){ name[i] = new char[100]; /* 人数分、100バイトづつの名前用バッファ確保 */ } /* */ for(i = 0; i < participant; i++){ printf("参加者 %d 人目の名前: ", i + 1); fgets(line, sizeof(line), stdin); sscanf(line, "%s", name[i]); /* &name[i]ではない事に注意 */ } /* */ for(i = 0; i < participant; i++){ number[i] = i; /* 通し番号で初期化。重複しない事が保証される */ } /* */ for(i = 0; i < participant - 1; i++){ j=(rand() % (participant - 1 - i)) + 1 + i; /* 入れ替えを行う */ k = number[i]; number[i] = number[j]; number[j] = k; } /* */ for(i = 0; i < participant; i++){ printf(" %s ――>プレゼント %d\n", name[i], number[i] + 1); } /* */ for(i = 0; i < participant; i++){ delete name[i]; /* 確保したら解放する */ } delete name; /* 確保したら解放する */ delete number; /* 確保したら解放する */ return 0; }

その他の回答 (1)

  • SAYKA
  • ベストアンサー率34% (944/2776)
回答No.1

あれ・・・どこかで聞いた事が有る話だね・・・ そのお話だと・・・ ・全員のプレゼントに番号を振る(皆が固定位置なら振らなくても良い) ・「1」「+」「+1」などとかかれた要するに+1の紙を自分以外の人数分用意する ・「0」とかかれた紙を+1の紙より1少ない数用意する ・箱に入れてかき回す ・自分以外の全員に1枚引かせる ・総計分だけ箱の番号をずらす とやると、全員が攪拌の権利を有し、かつ自分のプレゼントを自分で受け取る事は無くなるという方法。 (引く人数より0が1枚少ないので必ず1が1枚出て必ず1ずれ、自分は引かないので全員が1を引いても完全1周しない) 何番の質問だったかな・・・見つからないけどそんなやりかた。 原理が簡単だからプログラム化は 難しくないと思う。

関連するQ&A

  • プログラムを組んだのにエラーが出る!!!

    #include <stdio.h> #include <stdlib.h> #include <math.h> int main(void) { int i, j; int m, flag, count; FILE *fp; if (NULL == (fp = fopen("prime.txt", "w"))) { printf("Cannot open output file\n"); exit(1); } count = 0; for (i = 2; i < 1000; i++) { m =sqrt(i); flag = 1; for (j = 2; j <= m; j++) { if (i % j == 0) { flag = 0; break; } count++; } if (flag) { printf("%4d ", i); fprintf(fp," %4d", i); } } printf("\n乗除回数:%d\n", count); fprintf(fp,"\n乗除回数 %d\n", count); fclose(fp); return 0; } (通常課題2-3 1000以下の正の整数値のうち,素数をすべて計算し,結果をファイルに格納するプログラムを作れ. .また、計算の実行の中で乗除を行った回数もあわせて表示し、ファイルに格納すること 実行結果 2 3 5 7 11 13 17 … 991 997 乗除回数:78022 どこが間違ってるのか指摘してください お願いします!

  • プログラムの添削

    以下のような数当てゲームを作りました.なるべくうまいプログラムを書けるようになりたいのですが,どのような改善点がありますか?よろしくお願いします. /*数当てゲームを作りなさい.*/ #include<stdio.h> void maegaki(void); /*このように関数を定義しまくることに意味はあるのか?main関数はすっきりするけど.*/ void in_check_out(int i); int main(void) { int i; int j; maegaki(); for(j=0;j<10;j++) { scanf("%d",&i); in_check_out(i); if(!(i-1)) return 0; printf("残り%d回です.\n",9-j); } return 0; } void maegaki(void) { printf("数当てゲームをはじめます.\nぼくの好きな整数を当ててください.\nチャンスは10回です.\nヒントはボゾン\n"); } void in_check_out(int i) { if(!(i-1)) { printf("正解!答えは1です.\n"); } else { printf("残念!\n"); if(i>1) printf("%dより小さいです.\n",i); else printf("%dより大きいです.\n",i); } }

  • 簡単なプログラムの解説お願いします。

    #include<stdio.h> int main(void){ int i, j, temp, array[]={2, 7, 5, 4}; for(i = 0; i < 4; ++i){ for(j = i + 1; j < 4; ++j){ if(array[ i ] < array[ j ]){ temp = array[ i ]; array[ i ] = array[ j ]; array[ j ] = temp; } } for(j = 0; j < 4; ++j){ printf("%d,",array[j]); } printf("\n"); } return 0; } 7,2,5,4, 7,5,2,4, 7,5,4,2, 7,5,4,2, 答えはこのように表示されているんですが なぜこうなるのかが分かりません。 解説お願いします。

  • 単語数、文字数のカウントプログラム

    以下のような単語数、文字数のカウントプログラムを作ったのですが、10行目に「フォーマットは char ですが、引数は different type です」というエラーが出てしまいます。どのように修正したらよいでしょうか?教えてください。 #include <stdio.h> int main(void){ int wordcnt = 0; int charactercnt = 0; int i; char line[100]; printf("String: "); fgets(line, sizeof(line), stdin); sscanf(line, "%s", &line); if(line[0] != ' '){ wordcnt++; } for(i = 0; line[i] != '\0'; i++){ if(line[i - 1] == ' '){ wordcnt++; } if(line[i] != '\n'){ charactercnt++; } } if(wordcnt == 1){ printf("%d word,", wordcnt); }else{ printf("%d words,", wordcnt); } if(charactercnt == 1){ printf(" %d character", charactercnt); }else{ printf(" %d characters", charactercnt); } return 0; }

  • プログラム作成が出来ません

    プログラム作成の課題でエラーが出て進めません (1)~(3)までだけなら作成できるのですがどうしても(4) を表示させることができません^^; (1)3~99までの奇数を7*7の2次元配列に読み込み表示 (2)(1)の配列の行と列を入れ替えたものを表示 (3)全要素の平均 (4)要素の中から9の倍数を選び出し表示 添削よろしくお願いします。 #include <stdio.h> main() { int a[7][7]; int i,j,ave,sum; int c; for(i=0; i<7; ++i) { for(j=0; j<7; ++j) { a[i][j] =3+(j*2)+(i*14); } } for(i=0; i<7; ++i) { for(j=0; j<7; ++j) { for(c=0; c<49; ++c) { if((3+(j*2)+(i*14))%9==0) { c=3+(j*2)+(i*14); } } } } sum=0; for(i=0; i<7; ++i) { for(j=0; j<7; ++j) { sum=sum+a[i][j]; } } ave=sum/7/7; for(i=0; i<7; ++i) { for(j=0; j<7; ++j) { printf( "%2d ", a[i][j] ); } printf( "\n" ); } printf("\n"); for(i=0; i<7; ++i) { for(j=0; j<7; ++j) { printf( "%2d ", a[j][i] ); } printf( "\n" ); } printf("\n"); printf("average=%d\n",ave); printf("\n"); for(c=0; c<49; ++c) { printf("%d",c); } } 長々と失礼しました・・・

  • C言語でこのプログラムを完成させるには

    C言語でこのプログラムを完成させるには C言語初心者です。 1~6の乱数を100回発生させて、それぞれの出現回数をカウントし、ヒストグラムとして表示するプログラムを作成したいのですが上手くいきません。 #include <stdio.h> #include <time.h> #include <stdlib.h> int rnd(int m, int n) { return (int)(n-m+1)*(rand()/(RAND_MAX+0.1))+m; } int main(void) { int i, j, r; int hist[7]; for (i=1; i<7; i++) hist[i]=0; srand((unsigned)time(NULL)); for (i=0; i<100; i++) { r=6; while (6-- > 0) putchar('*'); putchar('\n'); } for (i=1; i<7; i++) { printf("%2d:", i); for (j=0; j<hist[i]; j++) printf("*"); printf("\n"); } return 0; } 何がいけないのでしょうか? よろしくお願いします。

  • 一つのプログラムを自由に操りためには

    c言語上達のためには自分で課題を考えて一つのプログラムを自由に操れるようになるほうが早いと思い最近は同じものばかりやっているんですが、つまずきます。質問させて下さい #include <stdio.h> #include <stdlib.> #include <time.h> #define S_NUMBER 5 #define N_NUMBER 50 int main( void ) { int s; int s_number[S_NUMBER]; int n; int n_number[N_NUMBER]; int m; int sum; int pum; int j; printf( データA\n"); for( s = 0; s < S_NUMBER; s++ ) { scanf( "%d", &s_number[s] ); } printf( "データB\n" ); for( n = 0; n < N_NUMBER; n++ ) { scanf( "%d", &n_number[n] ); } srand( time ( NULL ) ); for( m = 0; m < 5; m++ ) { do{ for( j = 0; j < 100; j++ ) { int x = rand() % n; int y = rand() % n; int tmp; tmp = n_number[x]; n_number[x] = n_number[y]; n_number[y] = tmp; } sum = 0; pum = 0; for( j = 0; j < 4; j++ ) { sum += n_number[j]; if( ( n_number[j] % 2 ) == 0 ) ++pum; } } while( sum < ( 70 - s_number[s] ) || sum > (150 - s_number[s] ) || pum < 2 || pum > 3 ); for( j = 0; j < 4; j++ ) printf( "%d %d \n", s_number[s], n_number[j] ); printf( "\n" ); } return 0; } たとえば、 5 11 36 78 109 という 5つの数字の表示をすることを考えます。 最初の5はデータAより、残りの11 36 78 109 はデータB よりデータBはシャッフルして表示する、なおかつ 5つの合計が70-データA(この場合5)~150-データA(この場合5)の範囲内として5つの数字の割合が奇数2:偶数3か奇数3:偶数2 とする。といゆうふうにしたいんですが、上記のコードではどこが違っているのかしりたいです。 直す箇所の訂正もお願いします。

  • 並べ替えのプログラム

    整数を20個入力し、まずそのまま表示してその後大きい順に並べ替えて表示するプログラムを作っているのですが、最大値しか表示されません。多分for文の3重ループの中がおかしいと思うのですがよくわかりません。 #include <stdio.h> int main(int argc, char* argv[]) { int c,i,x,max; int sav = 0; int before[20]; int after[20]; int check[20] = {0}; printf("整数を20個入力してください: "); for(i = 0; i < 20; i++) { scanf("%d",&before[i]); } printf("\n"); printf("BEFORE\n"); for(i = 0; i < 20; i++) { printf("%d\n",before[i]); } printf("\n"); max = 0; for(c = 0; c < 20; c++) { for(x = 0; x < 20; x++) { for(i = 0; i < 20; i++) { if(before[i] > max && check[i] == 0) max = before[i]; sav = i; } if(check[sav] == 0) check[sav] = 1; after[19 - x] = max; } } printf("AFTER\n"); for(x = 0; x < 20; x++) { printf("%d\n",after[x]); } return 0; } よろしくお願いします。

  • C言語のプログラムでおかしな動作をするのですが教えて頂けないでしょうか?

    VisualStudio2008使用しています。 問題は、サイコロを200回振ってその出た目の数の個数分*を表示するプログラムです。 サイコロの目はランダムで出しています。 次のプログラムは正常に動作するものです。 /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; int y[7]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } */ 次のプログラムが問題で、授業で先生が配列にはstaticをおまじないとしてつけないと暴走すると言われたので、つけて見ると明らかに間違ってると思われるプログラムで動作するのですが原因を教えて頂けないでしょうか? 以下問題のプログラム! 配列の前にstaticをつけたら、添え字をいくつにしても正常に動作します。普通は添え自分しか領域って確保されないですよね??? /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; //以下が問題の配列宣言 static int y[2]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 質問の意味が正確に伝わらなかった場合は補足しますので、ご回答よろしくお願いします。

  • C言語で半角スペースをデリミタとしたデータファイルを読み込むプログラム

    C言語で半角スペースをデリミタとしたデータファイルを読み込むプログラムを作っています. まず, データのレコード数とフィールドの数をカウントしてその後, double型の2次元配列に必要なメモリ領域をmalloc関数にて確保して, 2次元配列にデータを代入していくという処理をやらせています. とうプログラムをコンパイルして実行した所以下のようなエラーが出てどうやらFreeを2重にしてしまっていることがエラーログから分かるのですが, どこを修正していいかわかりません. どなたかお力を貸していただけないでしょうか? ■ソース■ #include<stdio.h> #include<string.h> #include<malloc.h> #define LINE_MAX_SIZE 5120 int main(void){ __road("test.dat"); } int road(char fname[100]){ __FILE *fp; __char line[LINE_MAX_SIZE]; __char *tp; __char *token=" "; __int rn=0; __int fn; __int i=0; __int j=0; __ __fp=fopen(fname,"r"); ____/* ____ check record number and field number ____*/ ____while(fgets(line,sizeof(line),fp)){ ______ ______tp=strtok(line,token); ______fn=0; ______while(tp!=NULL){ ________tp=strtok(NULL,token); ________fn++; ______} ______rn++; ____} ____//printf("rn=%d fn=%d\n",rn,fn); ____/* ______make 2 dimension array dynamically ____*/ ______double **data; ______ ______data=malloc(sizeof(double *)*rn); ______// then data have 2 pointer to double type ______for(j=0;j<fn;j++){ ________data[j]=malloc(sizeof(double)*fn); ______} ____ ____/* ____ insert data to array ____*/ ____i=j=0; ____while(fgets(line,sizeof(line),fp)){ ______j=0; ______tp=strtok(line,token); ______data[i][j]=atof(tp); ______while(tp!=NULL){ ________j++; ________tp=strtok(NULL,token); ________data[i][j]=atof(tp); ______} ______i++; ____} ____for(i=0;i<rn;i++){ ______for(j=0;j<fn;j++){ ________printf("%f ",data[i][j]); ______} ______printf("\n"); ____} ____/* ____/ free memory for data[][] ____*/ ____if(data){ ______for(j=0;j<fn;j++){ ________if(data[j]){ __________free(data[j]); ________} ______} ______free(data); ____} __fclose(fp); } /* int freeMem(){ } */

専門家に質問してみよう