質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.38%

  • C

    4824questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • マイコン

    87questions

    マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

PICマイコンのC言語で重複しない乱数生成の方法をご教授願います。

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 487
退会済みユーザー

退会済みユーザー

PICでもぐらたたき風ゲームを作っているのですが、LED1~8まである中で、下記のプログラムだと乱数が重複して、同じLEDが2回3回連続して光ってしまうのですが、連続で同じLEDが光らないようにするにはどうすればいいでしょうか?

#include<16f887.h>  
#define RAND_MAX 7
#include <stdlib.h>                 
#use delay(clock=20000000)
#fuses hs ,nowdt
#byte porta=0x05                    
#byte portb=0x06  
#byte portc=0x07
#byte portd=0x08  


long ct,n,i,r;
int _7seg(int data10)
{
   int  x,databcd,a1,b1,c1,d1,a2,b2,c2,d2;
   databcd = data10+(data10/10)*6;
   a1=(databcd&0x01)<<3;               // 1桁
   b1=(databcd&0x02)<<1;
   c1=(databcd&0x04)>>1;
   d1=(databcd&0x08)>>3;

   a2=(databcd&0x10)<<3;               // 2桁
   b2=(databcd&0x20)<<1;
   c2=(databcd&0x40)>>1;
   d2=(databcd&0x80)>>3; 

  x=a1|b1|c1|d1|a2|b2|c2|d2;
  return(x);
 }

int data;
int const  s[100] ={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void main(void)
{ 

   int h;


   set_tris_a(0);
   set_tris_b(0xff);
   set_tris_c(0);
   set_tris_d(0);
   PORTB=0;            //カウンタ(7セグ)
   PORTD=0;            //LED
   PORTC=0;            //ボタン
   ct=0;
   n=0;
   i=0;
   h=0;

   //t=0;


while(1)
{

   h = rand();  
   i = s[h];
   portd=i;          // モグラの頭 出る


     while(ct<6000 )  // 入力を待ちながらボタン判定
      {
         if (portd == ~ portb ){ n++;           // 押されたらカウント
                                 portc=_7seg(n);
                                 break;
                                 }
        ct++ ;

        delay_us(1000);        //光ってる時間
      }    

        ct = 0;

         portd=0;
         delay_ms(1000);   // シリンダー引っ込み待ち

    // 次のモグラへ

}

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

単純に連続しないようにするって話なら、
前回の値を覚えておいて、今回の乱数が同一値なら、再度乱数で選び直す、ってことをすればよろしい

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/11 10:35

    下記のようにしてそのようにやってみたらカウントだけ進んでいき、LEDが点灯しませんでした。

    while(1)
    {
    h = rand();
    i = s[h];

    if( i == ~z)
    portd=i; // LED点灯
    else
    continue;

    portd=0;
    i = z;
    delay_ms(500); // 待ち

    // 次のLEDへ

    }

    キャンセル

  • 2019/01/11 10:43

    > if( i == ~z)

    z ってなに?

    キャンセル

  • 2019/01/11 10:47

    zは前回の値を記憶させた変数です

    キャンセル

  • 2019/01/11 10:51

    > i = s[h];

    sというのも意味不明ですねー
    各変数の内容をシリアルポートにでも出してPCで見れるようにしましょう。
    コードだけを眺めて、あてずっぽでコード書いててもなんにもなりませんぜ

    キャンセル

0

乱数なので重複するのは当然です。
重複しないようにするのであれば、あらかじめ配列などに取りうる数字を入れておき、
配列のインデックスを乱数で決定していく、決定した要素は使わないようにする
といった処理をすれば良いかと。
もちろん、配列の内容をランダムに入れ替え、頭から取得するなどでも良いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

簡単に対処するには、乱数の範囲を0~7ではなく0~6にしてはいかがでしょうか。
そして乱数を求めるたびに、乱数の位置の要素と末端の要素を入れ替える。
そうすることで前回の値が取得される事はなくなります。

int const  s[100] ={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
↓
int s[100] ={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //constを削除while(1)
{
   h = rand();  
   i = s[h];
   s[h] = s[RAND_MAX]; // 入れ替え処理
   s[RAND_MAX] = i;    // 入れ替え処理
   portd=i;          // モグラの頭 出る


但し、初回は一番右端は選ばれなくなってしまうのが問題…。
PICって使ったこと無いですが、乱数の範囲はRAND_MAXで決定するしかないのでしょうか?
通常の使い方ができるのなら、初回はrand()%8で、2回目以降はrand()%7するような作りにすれば対処できます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/11 09:38

    メモリ不足?使えるメモリはそんなに少ないのでしょうか?
    とりあえずの対策としてs[100]をs[RAND_MAX+1]にしてみたらどうなりますか?

    キャンセル

  • 2019/01/11 10:45

    今までのことを全て試してみたのですが、while文の中で入れ替え自体ができないみたいです…

    キャンセル

  • 2019/01/11 10:47

    そんなことないと思いますが・・・。
    s配列のconst外してますよね?

    キャンセル

0

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C

    4824questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • マイコン

    87questions

    マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。