乱数が重複

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

乱数が重複

#1

投稿記事 by Z400FX » 6年前

code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void *card(void){
int num,i;
char *test[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
srand((unsigned)time(NULL));
num = rand() % 13;
return test[num];
}

int main (void){
char c;
char *funyu;

while(1){
printf("Hit or Stand?(h/s)¡§");
scanf("%c",&c);
if(c == 's')break;
funyu = card();
printf("%s\n",funyu);
}

return 0;
}
code

乱数が重複しないようにするにはどうすれば良いですか?
トランプのカードの種類も出さなくてはいけません。

超絶右留斗羅天才プログラマー
記事: 44
登録日時: 6年前

Re: 乱数が重複

#2

投稿記事 by 超絶右留斗羅天才プログラマー » 6年前

乱数が重複するのは、使う乱数を決めるための関数
srand((unsigned)time(NULL));
をcard関数内で何度も呼び出しているのが原因です。

main関数内で一度だけ呼び出すようにしてみましょう。
ただの超絶右留斗羅天才プログラマーです。同人ゲーム制作進捗度:7%

Z400FX

Re: 乱数が重複

#3

投稿記事 by Z400FX » 6年前

main関数内にしましたが重複してしまいます。

KORYUOH
記事: 44
登録日時: 7年前

Re: 乱数が重複

#4

投稿記事 by KORYUOH » 6年前

srand((unsigned)time(NULL));
をwhile文の中でやっていませんか?
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

Z400FX

Re: 乱数が重複

#5

投稿記事 by Z400FX » 6年前

やっていません。

超絶右留斗羅天才プログラマー
記事: 44
登録日時: 6年前

Re: 乱数が重複

#6

投稿記事 by 超絶右留斗羅天才プログラマー » 6年前

一応、正常なプログラムを貼り付けておきます(*´▽`*)
どうしても分からなくなったら、スポイラーを開いて確認してみましょう。
► スポイラーを表示
最後に編集したユーザー 超絶右留斗羅天才プログラマー on 2013年6月21日(金) 18:14 [ 編集 1 回目 ]
ただの超絶右留斗羅天才プログラマーです。同人ゲーム制作進捗度:7%

Z400FX

Re: 乱数が重複

#7

投稿記事 by Z400FX » 6年前

最初のアドバイスでそれをやってみましたが、重複したので改めて質問させて頂いたのですが・・・。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: 乱数が重複

#8

投稿記事 by h2so5 » 6年前

おそらくZ400FXさんが実現したいのはランダムな順列ですよね。
ちょうど良い解説を見つけました。
http://pcnetbeginners.seesaa.net/article/208460691.html

Z400FX

Re: 乱数が重複

#9

投稿記事 by Z400FX » 6年前

探してもらったところすみませんが順列ではなく
実行結果は
Hit or Stand?(h/s):h
A
Hit or Stand?(h/s):h
10
Hit or Stand?(h/s):h
Q
Hit or Stand?(h/s):h
5
Hit or Stand?(h/s):h
2
Hit or Stand?(h/s):h
2
Hit or Stand?(h/s):h
K
Hit or Stand?(h/s):h
4
Hit or Stand?(h/s):h
2
こうなるのですが、見た通り2が重複してますよね?
これを解決したいのです!

KORYUOH
記事: 44
登録日時: 7年前

Re: 乱数が重複

#10

投稿記事 by KORYUOH » 6年前

もし、連続して同じカードを引きたくないのであれば前の値を保持しておき同じであるならば生成しなおす方法をお勧めしますが、
すべて重複したくないのであるならば配列をシャッフルしてしまうのがいいと思います。
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

Z400FX

Re: 乱数が重複

#11

投稿記事 by Z400FX » 6年前

1度引いたカードはその実行中には2度と出てこないようにしたいのです。

KORYUOH
記事: 44
登録日時: 7年前

Re: 乱数が重複

#12

投稿記事 by KORYUOH » 6年前

それでしたら配列の中身をランダムにシャッフルして取得するたびに配列の添え字をインクリメントするのが簡単でしょう。
ただし、配列の大きさ以上に取得使用としたときの対応が必要になりますが。
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: 乱数が重複

#13

投稿記事 by h2so5 » 6年前

Z400FX さんが書きました:1度引いたカードはその実行中には2度と出てこないようにしたいのです。
それを実現するのがランダムな順列です。

超絶右留斗羅天才プログラマー
記事: 44
登録日時: 6年前

Re: 乱数が重複

#14

投稿記事 by 超絶右留斗羅天才プログラマー » 6年前

先程は失礼致しました。

以下を全て直すと実現できます。
①scanfの内容をscanf("%s",&c);に直しておきます。
②card関数の戻り値をchar型とします。
③funyuの変数をchar型とします。
④card関数に新しくstatic int型の変数を一つ用意し、初期値を13とします。
⑤card関数のtestをchar型にし、"1"とくくっていたものを'1'と全て直します。
⑥num=rand() % maxと変更します。
⑦戻り値を保持するchar型変数にtest[num]を保持します。
⑧一度選んだものを潰すために、for文を回します。
⑨maxの値を一つ引きます。
⑩保持しておいたものをreturnします。
⑪13回以上引くとエラーが起きるので、13回以降は'\0'をreturnします。

コードは以下のようになります。
► スポイラーを表示
ただの超絶右留斗羅天才プログラマーです。同人ゲーム制作進捗度:7%

アバター
usao
記事: 1565
登録日時: 6年前

Re: 乱数が重複

#15

投稿記事 by usao » 6年前

他のトピックと酷似しているようですが,
こっちではスートの概念がない(1~13の13枚しかカードがない)ということでいいのかな?
http://dixq.net/forum/viewtopic.php?f=3&t=13282

forで回さずとも1要素だけ動かせば良いように思います.

コード:

    //for( i = num; i < max - 1; i++ )
    //    test[i] = test[i+1];
    test[num] = test[max-1];

アバター
みけCAT
記事: 6246
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 乱数が重複

#16

投稿記事 by みけCAT » 6年前

自分が昔書いたライブラリ(をC言語に移植したもの)を貼っておきます。
► スポイラーを表示
移植元のC++のコードはここにあります。
http://dixq.net/forum/blog.php?u=536&b=3091
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Z400FX

Re: 乱数が重複

#17

投稿記事 by Z400FX » 6年前

'A','2','3','4','5','6','7','8','9','10','J','Q','K'};
超絶右留斗羅天才プログラマーさん
この部分が謎なのですが?

Z400FX

Re: 乱数が重複

#18

投稿記事 by Z400FX » 6年前

皆様どうもありがとうございました

超絶右留斗羅天才プログラマー
記事: 44
登録日時: 6年前

Re: 乱数が重複

#19

投稿記事 by 超絶右留斗羅天才プログラマー » 6年前

シングルクォーテーションでくくると、何故か文字化けしてしまうのですよね(ノ_・;)
⑤と⑪に該当する部分ですので、元のプログラムを元に変更してください。
他に文字化けしている所も、元のプログラムを参照してください。
ただの超絶右留斗羅天才プログラマーです。同人ゲーム制作進捗度:7%

Z400FX

Re: 乱数が重複

#20

投稿記事 by Z400FX » 6年前

トランプのカードを1 枚ひく(カードのスーツと数字を返す) 関数を作れ。1, 11, 12, 13 につい
ては、それぞれA, J, Q, K と表示させること。スペード、ハート、ダイヤ、クラブについては、そ
れぞれS, H, D, C と表示させること。また、トランプは1 組だけ使用するものとし、同じカード
が重複してひかれることは許されない。さらに、プログラムを実行し直すたびに、異なるカード
が出るようにすること。

/*
// トランプを引くプログラム
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//トランプを引く処理

void *pull(void){
int rand_cards,rand_suit; //乱数を格納する変数
int suit[4] = {1,2,3,4}; //トランプの絵柄
char *cards[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"}; //トランプの数字

srand((unsigned)time(NULL)); //乱数を初期化する。この処理がないと乱数が初期化されずに同じ結果がでる。
rand_suit = rand() % 4; //乱数を生成してスートを決めて変数に格納する。
srand((unsigned)time(NULL));
rand_cards = rand() % 13; //乱数を生成して数字を決めて変数に格納する。
printf("%d%s\n",suit[rand_suit],cards[rand_cards]); //結果を表示
}

int main(void){
char c;

while(1){ //無限ループ
printf("Hit or Stand?(h/s):");
scanf(" %c",&c);
if(c == 's')break;
pull();
}

return 0;
}
あれから考えてみましたが、やはり分かりません。

KORYUOH
記事: 44
登録日時: 7年前

Re: 乱数が重複

#21

投稿記事 by KORYUOH » 6年前

ソース部分はcodeタグで囲っていただきたいです

数値とスート別々に管理するのではなく、構造体で管理するのはいかがでしょうか?
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

アバター
usao
記事: 1565
登録日時: 6年前

Re: 乱数が重複

#22

投稿記事 by usao » 6年前

「何が」わからないのでしょうか?
当初は13枚で考えていたように見えたのですが,13枚の場合はできたのでしょうか?
13枚から52枚に増えたからといって特段何も変わらないと思うのですが.

Z400FX

Re: 乱数が重複

#23

投稿記事 by Z400FX » 6年前

usaoさん
int suit[4]={1,2,3,4};のところをD,S,Q,Hにしたいのですが、どうすれば良いですか?
ちなみにchar型にしても出来ません。
結果が重複しないため、52回実行すると自動的に終了したい。
出来るのならば教えてください。

Z400FX

Re: 乱数が重複

#24

投稿記事 by Z400FX » 6年前

usaoさん
出来そうですか?

KORYUOH
記事: 44
登録日時: 7年前

Re: 乱数が重複

#25

投稿記事 by KORYUOH » 6年前

単に52回にしたいのであれば無限ループではなく有限ループに変更するだけで対応可能です。

ソースを読んだところpullを行うたびにsrandしてしまっていますがこれは意図してやっていますか?
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

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

Re: 乱数が重複

#26

投稿記事 by non » 6年前

char *cards[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
今、現在こうなっているのを
char *cards[52] = {"SA","S2","S3","S4","S5","S6","S7","S8","S9","S10","SJ","SQ","SK","HA","H2","H3","H4","H5","H6", 以下略 };
にするのはどうでしょう。
non

Z400FX

Re: 乱数が重複

#27

投稿記事 by Z400FX » 6年前

KORYUOHさん
これではいけないのですか?
有限ループがわかりません・・・。

KORYUOH
記事: 44
登録日時: 7年前

Re: 乱数が重複

#28

投稿記事 by KORYUOH » 6年前

これでも可能です。
もし無限ループでやりたいのであればカウンターでbreakさせなければなりませんが。
有限ループはforでやる方法とwhileでやる方法があります。
たとえば確実に一定回数やる場合はfor
条件が正しい間だけやる場合はwhileでやるとよいでしょう
最後に編集したユーザー KORYUOH on 2013年6月21日(金) 16:57 [ 編集 1 回目 ]
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

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

Re: 乱数が重複

#29

投稿記事 by non » 6年前

KORYUOH さんが前に言われている
>もし、連続して同じカードを引きたくないのであれば前の値を保持しておき同じであるならば生成しなおす方法をお勧めしますが、
>すべて重複したくないのであるならば配列をシャッフルしてしまうのがいいと思います。

この2つの方法のどちらかで行うのだと思いますが、いつまでたってもその方向に進んでいきませんね。
non

アバター
usao
記事: 1565
登録日時: 6年前

Re: 乱数が重複

#30

投稿記事 by usao » 6年前

>int suit[4]={1,2,3,4};のところをD,S,Q,Hにしたいのですが、どうすれば良いですか?
>ちなみにchar型にしても出来ません。
意味がわかりません.
char suit[4] = { 'D', 'S', 'Q', 'H' };
とか書きたいのでしょうか?

>52回
>有限ループがわかりません・・・。
あなた自身が「無限ループ」を書いて,ユーザ入力の結果によって終了するようにコードを書いているのですが…??
一定回数だけ繰り返したいのであれば,そのように書くだけだと思いますが.
「一定回数繰り返させる書き方がわからない」とかいう話なのであれば…さすがに回答しがたいです.
(この課題に挑む前にまずはCを一から勉強してください,としか言えない)

超絶右留斗羅天才プログラマー
記事: 44
登録日時: 6年前

Re: 乱数が重複

#31

投稿記事 by 超絶右留斗羅天才プログラマー » 6年前

こちらでどうでしょうか(*´ω`*)
► スポイラーを表示
ただの超絶右留斗羅天才プログラマーです。同人ゲーム制作進捗度:7%

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

Re: 乱数が重複

#32

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

傍観してましたが、超絶右留斗羅天才プログラマーさんが他の人のやっていることを台無しにしそうなのでコメントさせていただきました。
面倒でしょうが、答えに誘導する形での回答をお願いします。

どうしても、直接的なコードが必要だと思うのならプレイベートメッセージで他の人に確認をとるとか協調をお願いします。
【補足】あっ、私に強制権はありませんのでお願いになります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1565
登録日時: 6年前

Re: 乱数が重複

#33

投稿記事 by usao » 6年前

あらあら またダイレクトにコード投下されてますね…まぁその方針にはあえて文句は言いませんけど.
とりあえずコードについては
return ret;
とか,どうかと思います.

閉鎖

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