サイコロの問題 乱数編

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

サイコロの問題 乱数編

#1

投稿記事 by しょしょしょしんしゃ » 16年前

 学校の課題です。
 問題文は、
  「1から6の目が等確率では出ないサイコロがあり、
  それぞれの目の出る確率は以下のように、

  p1=1/4,p2=1/6,p3=1/6,p4=1/6,p5=1/6,p6=1/12

piはi(i=1,2,3,4,5,6)の目がでる確率を表しています。
  このようなサイコロを100回投げたときにどの目が
  何回出たかを数えるプログラミングの作成。」
 
 わたしのわからないところは、
 >p1=1/4,p2=1/6,p3=1/6,p4=1/6,p5=1/6,p6=1/12
 をどのように分け、乱数を使用するのでしょうか?
 >100回投げたときにどの目が何回出たかを数える
case文かif文を使うのでしょうか?
 
 自分は普通のサイコロを10回ふって、N回目にaのサイコロの目がでる。
 というプログラムしか作る能力しかできませんでした。(一応書いときます)
 
#include<stdio.h>
        #include<stdlib.h>
        #include<time.h>
        #define N 10

      int main(void){
	int i;
	int a;
	srand((unsigned)time(NULL));
	for(i=0;i<N;i++){
		a=rand()%6+1;
		printf("%d回目のサイコロの目は%dです\n",i+1,a);
         }
           return 0;
         }
たぶん これを使用して、応用すればできるような感じがします。
 よろしくお願いします。

 

Dixq (管理人)

Re:サイコロの問題 乱数編

#2

投稿記事 by Dixq (管理人) » 16年前

まず、わかることから作ってみましょう。

1/4の確率で「当たり」と。3/4の確率で「外れ」と表示するプログラムを作ってみてください。

1/5の確率で「1番」と。
2/7の確率で「2番」と、それ以外の場合「それ以外」と表示するプログラムを作ってみてください。

そうするとだんだんわかってくるのではないでしょうか。
以下ヒントです。

int r = rand()%3;
if(r ==0 )

これって1/3ですよね。

int r = rand()%3;
if( r==0 || r==1 )

これは2/3ですね。

box

Re:サイコロの問題 乱数編

#3

投稿記事 by box » 16年前

考え方のひとつを挙げてみます。

何らかの方法で0~11の整数の乱数を発生させます。
その乱数の値が、
0,1,2のとき、サイコロの1の目が出たとみなす
3,4のとき、サイコロの2の目が出たとみなす
5,6のとき、サイコロの3の目が出たとみなす
7,8のとき、サイコロの4の目が出たとみなす
9,10のとき、サイコロの5の目が出たとみなす
11のとき、サイコロの6の目が出たとみなす

lbfuvab

Re:サイコロの問題 乱数編

#4

投稿記事 by lbfuvab » 16年前

int GetDice(void){
    int i;
    int dice[12]={1,1,1,2,2,3,3,4,4,5,5,6};//p1=1/4,p2=1/6,p3=1/6,p4=1/6,p5=1/6,p6=1/12
    
    i=(rand()/(double)RAND_MAX)*12;
    
    
    return dice;
}


とかですかね。

バグ

Re:サイコロの問題 乱数編

#5

投稿記事 by バグ » 16年前

とりあえず、確率の数値の分母をそろえてみて考えてみては如何でしょうか?
ソース内にコメントで書きましたが、分母をそろえると…

p1 = 3 / 12
p2 = 2 / 12
p3 = 2 / 12
p4 = 2 / 12
p5 = 2 / 12
p6 = 1 / 12

になりますよね?
ここまでくると、なんとなく見えてきませんか?

p1 = (1, 2, 3)
p2 = (4, 5)
p3 = (6, 7)
p4 = (8, 9)
p5 = (10, 11)
p6 = (12)

12個の乱数をこういう風に割り振れば、いけそうではないでしょうか?

で、更に偏りを防ぐ為に12個ではなく、120個の乱数で考えたら…というのが下記のソースです。
効率は悪いですが、分かりやすさ重視で書いてみました。

p1 = (1~30)
p2 = (31~50)
p3 = (51~70)
p4 = (81~90)
p5 = (91~110)
p6 = (111~120)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
	int i = 0, rnd = 0;
	int dice[6] = {0, };

	srand((unsigned)time(NULL));

	// サイコロの処理
	for (i = 0; i < 100; ++i)
	{
		rnd = rand() % 1200;

		if (rnd < 300)
		{
			// p1 = (1 / 4) = (300 / 1200)
			++dice[0];
		}
		else if (rnd < 500)
		{
			// p2 = (1 / 6) = (200 / 1200)
			++dice[1];
		}
		else if (rnd < 700)
		{
			// p3 = (1 / 6) = (200 / 1200)
			++dice[2];
		}
		else if (rnd < 900)
		{
			// p4 = (1 / 6) = (200 / 1200)
			++dice[3];
		}
		else if (rnd < 1100)
		{
			// p5 = (1 / 6) = (200 / 1200)
			++dice[4];
		}
		else
		{
			++dice[5];
		}
	}

	// 表示
	for (i = 0; i < 6; ++i)
	{
		printf("%d = %d\n", i + 1, dice);
	}

	return 0;
}

バグ

Re:サイコロの問題 乱数編

#6

投稿記事 by バグ » 16年前

>>で、更に偏りを防ぐ為に12個ではなく、120個の乱数で考えたら…というのが下記のソースです。

ゴメンなさい。120個ではなく、1200個ですね(^_^;)

しょしょしょしんしゃ

Re:サイコロの問題 乱数編

#7

投稿記事 by しょしょしょしんしゃ » 16年前

管理人さん 最初の問題はできましたが、
>1/5の確率で「1番」と。
>2/7の確率で「2番」と、それ以外の場合「それ以外」と表示するプログラムを作ってみてください。
 は 1/5と2/7をどのように分けるのか?

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 10

int main(void){
	int i;
    
	srand((unsigned)time(NULL));
	for(i=0;i<N;i++){
	int r=rand()%4;
	if(r==0){
		printf("当たり\n");
	}else{
		printf("外れ\n");
	}
	}
  return 0;
}
 これは できました。
srand((unsigned)time(NULL));
	for(i=0;i<N;i++){
	int r=rand()%35;
	if(r==0 || r==5  ){
		printf("1番\n");
	}else if(r==0 || r==7){
		printf("2番\n");
	}else{
		printf("それ以外\n");
 ではだめでした。

boxさん 考え方のは
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 10

int main(void){
	int i;
	int a;
    
	srand((unsigned)time(NULL));
	for(i=0;i<N;i++){
	a=rand()%11+1;
	if(a==0 || a==1 || a==2){
		printf("サイコロの目は1です\n");
	}else if(a==3 || a==4 ){
		printf("サイコロの目は2です\n");
	}else if(a==5 || a==6){
		printf("サイコロの目は3です\n");
	}else if(a==7 || a==8){
		printf("サイコロの目は4です\n");
	}else if(a==9|| a==10){
		printf("サイコロの目は5です\n");
	}else if(a==11){
		printf("サイコロの目は6です\n");
	}
	}
  return 0;
}
のように なりましたが どうでしょうか?

box

Re:サイコロの問題 乱数編

#8

投稿記事 by box » 16年前

> 	a=rand()%11+1;

11で割ったあまりは0~10のいずれかです。
それに1を加えると1~11のいずれかになります。0~11にも1~12にもなりません。
12で割ったあまりを素直に使うと0~11の12種類の整数を得ることができ、
if文はそのまま使えます。

non

Re:サイコロの問題 乱数編

#9

投稿記事 by non » 16年前

if(r==0 || r==5  ){    <-ここ間違い
		printf("1番\n");
	}else if(r==0 || r==7){  <-ここ間違い
		printf("2番\n");
1/5と2/7ですから、7/35と10/35ですね。
ですから、範囲で0から6までは1番、7から16までは2番となるようにすればいいです。

しょしょしょしんしゃ

Re:サイコロの問題 乱数編

#10

投稿記事 by しょしょしょしんしゃ » 16年前

すみません 見落としていました。
a=rand()%12+1;
 でよろしいのですか?
lbfuvabさん バグさん 回答の方 ありがとうございます。

box

Re:サイコロの問題 乱数編

#11

投稿記事 by box » 16年前

> a=rand()%12+1;
>  でよろしいのですか?

自分の頭で考えるのと人に聞くのと、どちらの優先順位が高いですか?
まず自分の頭と手を使って試してみる、という発想には至りませんか?

しょしょしょしんしゃ

Re:サイコロの問題 乱数編

#12

投稿記事 by しょしょしょしんしゃ » 16年前

nonさん ありがとうございます
if(0<=r && r<=6  ){
		printf("1番\n");
	}else if(7<=r && r<=16){
		printf("2番\n");
	}else{
		printf("それ以外\n");
と直したところ うまくいったと思います。
これを 参考にしていきたいです。
ありがとうございます。

non

Re:サイコロの問題 乱数編

#13

投稿記事 by non » 16年前

> a=rand()%12+1;
>  でよろしいのですか?

よろしくないです。ですからboxさんが怒ってます。(確認してないことを)

しょしょしょしんしゃ

Re:サイコロの問題 乱数編

#14

投稿記事 by しょしょしょしんしゃ » 16年前

>自分の頭で考えるのと人に聞くのと、どちらの優先順位が高いですか?
まず自分の頭と手を使って試してみる、という発想には至りませんか?
>よろしくないです。ですからboxさんが怒ってます。(確認してないことを)

 すみませんでした +1 を とりました。 
 boxさんの回答を2つも見落としていました。

 自分自身で実行しないで、さぼってしまいました。
 以降は 気をつけていきたいと思います。
nonさん 忠告 ありがとうございます。

  皆さんの回答で、参考になりました。
  上手く 実行できました。
  また よろしくお願いします。

Dixq (管理人)

Re:サイコロの問題 乱数編

#15

投稿記事 by Dixq (管理人) » 16年前

イコールをどちらかにつけないほうが感覚的にわかりやすくなりますよ。
if( 0<=r && r<7 ){

		printf("1番\n");

	}else if( 7<=r && r<17 ){

		printf("2番\n");

	}else{

		printf("それ以外\n");
 
どちらがわかりやすいかは人それぞれでしょうけど、
こっちの方が感覚的に、最初7、それから10となっているように見えないでしょうか?

ibis

○×ゲーム作ってみた。

#16

投稿記事 by ibis » 16年前

とあるスレッドを見てたら○×ゲームを作りたくなったので。

でもゲームを作るのはあまり好きではないので、1時間半くらいで意欲が消失しました。
それからはもう何も考えずにキーボード叩いて、気づけば動くものができてた、という感じです。
故に終盤にコーディングした部分は「動けば何でも良い」みたいな状態になってますが・・・
製作時間は2時間ちょい。
何なんでしょうねぇ、ライブラリとか作るのは何時間でも楽しめるのですが。


用法:
1.数字が書いてあるマスをクリックして入力します。
2.1を繰り返します。
3.勝敗決定時にダイアログボックスで勝者を表示します。ダイアログボックスを消すとプロセスを終了します。
4.引き分けの場合は何も起こりません。手動で終了してください。

座標計算がおかしい気もしますが、
まぁそれも愛嬌ということで許してやってくださいな。


あ、そうそう。
ややこしくなってるので一応明記しときますが、
これはコンソールアプリケーションとしてコンパイルしてます。

Dixq (管理人)

Re:○×ゲーム作ってみた。

#17

投稿記事 by Dixq (管理人) » 16年前

遊んでみました^^
これは、一人二役ってことですか?w 難しいw

私も昔○×ゲーム作ったことあります。
その当時は最強AIを作るのに苦労しました^^;

まず最強のAI作るためには自分が最強のアルゴリズム知ってないといけないんですよね・・。

ノートに何度も自分で○×ゲームかいて考えた記憶があります。

>何なんでしょうねぇ、ライブラリとか作るのは何時間でも楽しめるのですが。

そうなんですかぁ、私は逆でゲーム作ってると何日でも寝なくて大丈夫です(ぇ

ibis

Re:○×ゲーム作ってみた。

#18

投稿記事 by ibis » 16年前

>一人二役
いや、2人用というか何と言うか。
確かにこれは1人では楽しめませんね。
その内AIでも作ってみましょかねぇ。

>最強AI
あー。
多分、優先順位が「詰む所>真ん中>直線上に敵がいない角>対角以外の角(すでに角を取ってる場合)>角>それ以外」みたいな感じかな。

とりあえず、気合を入れなおして座標計算を改善しました。
やっぱり座標計算間違ってました。

閉鎖

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