重複なしでランダムに画像を表示する方法

このQ&Aのポイント
  • C#で重複なしでランダムに画像を表示するプログラムのエラーを修正する方法を教えてください。
  • GetNextIndex()関数内で起こっているエラーを修正する方法を教えてください。
  • ランダムな番号の配列を作成して、重複をチェックしながら画像を表示する方法を教えてください。
回答を見る
  • ベストアンサー

重複なしでランダムに画像を表示する方法

現在、C#で重複なしでランダムに画像を表示するプログラムを作成しています。 下記のように書いてコンパイラをすると 型 'string' を型 'int' に暗黙的に変換できません 名前 'n' は現在のコンテキスト内に存在しません。 名前 'n' は現在のコンテキスト内に存在しません。 名前 'n' は現在のコンテキスト内に存在しません。 というエラーが出て直し方が分からない状態です。 このエラーは、GetNextIndex()関数内で起こっています。 どうか力を貸してください。お願いします。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //定数 private const int IMAGES = 3;//イメージの総数=各配列の要素数 //メンバー変数 private string[] sPathes = {@"D:\A.BMP",//1番目の画像のパス @"D:\B.BMP",//2番目の画像のパス @"D:\C.BMP",//3番目の画像のパス;//パス配列の宣言と定義 }; private Image[] myImages = null;//イメージ配列変数の宣言 private int m_nIndex;//表示する画像の番号 //private int[] m_nUsed = null;//表示済画像の番号の配列 private int m_nTimes = 0;//これまでに表示した枚数(3まで) public void Init()//引数なし、メンバー変数の初期化 { //イメージ配列の初期化 //・・・インスタンスメモリの確保(メモリーの確保は最初の1回だけ) if (myImages == null) myImages = new Image[IMAGES];//本当はnewのチェックが必要 //・・・ファイルを読み込んでイメージ配列に格納 for (int n = 0; n < IMAGES; n++) { string sPath = sPathes[n];//パス文字列 Image img = Image.FromFile(sPath);//イメージ読込 myImages[n] = img;//配列に格納 }//for終わり //this.m_nUsed(-1); } protected virtual void OnCreate()//OnLoadから呼ばれる { //変数の初期化を行う this.Init(); } //初回更新用の関数 protected virtual void OnInitialUpdate() { this.OnUpdate();//更新をかける } //更新関数 protected virtual void OnUpdate() { if(m_nIndex < 0)//画像番号が設定されていなければ何もしない。 return; //画像の更新 pictureBox1.Image = myImages[m_nIndex]; } //次に表示する画像番号の取得 protected int GetNextIndex() { //ランダムな配列を作成 Random r = new Random(); //重複チェック int[] a = new int[n]; for (int i = 0; i < n; ++i) a[i] = i + 1; for (int i = n; i > 1; --i) { int k = r.Next(i); int tmp = a[i - 1]; a[i - 1] = a[k]; a[k] = tmp; } return r.ToString(); } private void button1_Click(object sender, EventArgs e) { if(m_nTimes >= IMAGES) return; int n = GetNextIndex();//次なる番号の取得 if (n < 0)//適当な番号が得られなければ return;//何もしない //やっと画像番号を変える m_nIndex = n; //更新を呼び出す this.OnUpdate(); } } }

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

> 値として何を返せばよろしいのでしょうか? それを考えるのが「プログラミング」というものです。 まず、プログラムの仕様をまとめた方がいいです。 それから、一気に作らず、各メソッドが期待通りに動作しているか、テストした方がよいでしょう。今回のだったら、画像の表示等は後にして、GetNextIndexが「重複していない整数」をちゃんと返すかどうか、確認してから次へ進めましょう。 button1_Clickの動作からして、GetNextIndexは、m_nIndexに設定するための0以上IMAGES未満の整数を、重複無しにランダムに返してくることが期待されているのではないでしょうか。あとは、エラー時には負の整数を返すことも。 そこで、GetNextIndexを見ると、returnの直前では int a[] : 1以上n以下の整数をシャフルした配列 となっています。nは定義されていないので、IMAGESの間違いで、 > for (int i = 0; i < IMAGES; ++i) a[i] = i + 1; の a[i] = i + 1;をa[i] = i ;にすれば int a[] : 0以上IMAGES未満の整数をシャフルした配列 となり、このaの値をGetNextIndexが呼ばれる度に一つずつ返せば、目的の動作になるはずだ、ということがわかります。 なので return a[X] ; のような形になるでしょう。 ところが、今のままでは、 ・配列aを毎回作っている。これではシャフルの意味がない ・どこまで使って、次に何を返せばいいのか、覚えておく仕組みが無い ・配列をリセットする手段が無い。 と言う問題があります。 解決策としては、Randomのようなインターフェースで専用のクラスを用意するのがいいのでは、と思います。

usaginabe
質問者

お礼

回答ありがとうございました。 kmeeさんのおっしゃる通りに1つずつ作成していったら 目標とする動きが出来ました。 ありがとうございました。 それでは、失礼いたします。

その他の回答 (1)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

> protected int GetNextIndex() と宣言したのに > return r.ToString(); なぜstringで返すのでしょう? 戻り値がintのはずなのに、stringが指定してあって、戻り値の型にあわせるためにstring→intの変換をしようにも変換方法がわからない(暗黙の変換が無い)というエラーです。 そもそもこのGetNextIndexですが ・Randomクラスであるrを返すこと自体おかしい ・呼ばれるたびに、毎回新しい乱数と新しい重複チェック配列を作っています。これらはreturn後に自動で削除されます。 まったく、重複チェックになっていません。

usaginabe
質問者

お礼

回答ありがとうございます。 値として何を返せばよろしいのでしょうか?

関連するQ&A

  • 4つの数字を用いて重複することなく並べる

    題名のとおりなのですが 例えば{1,2,3,4},{2,3,4,1}などです。 これら24通りを[24][4]の要素をもつ2次元配列に入れたいのですがどうすればいいのでしょうか? 一応自分で作ってみたのですが作ってみていかにも冗長であると感じています。 アドバイス、回答よろしくお願いします。 #include <stdio.h> int main(void){ int i,j,n=5,m,p; int l[24][4]={{1,2,3,4},{2,1,3,4},{2,3,1,4},{3,2,1,4},{3,2,4,1},{4,2,3,1}}; for(i=0;i<6;i++){ for(j=0;j<3;j++){ n++; if(!j)for(p=0;p<4;p++)l[n][p]=l[i][p];     else for(p=0;p<4;p++)l[n][p]=l[n-1][p]; m=l[n][0]; l[n][0]=l[n][1]; l[n][1]=l[n][2]; l[n][2]=l[n][3]; l[n][3]=m; } } for(i=0;i<24;i++){ for(j=0;j<4;j++){ printf("%d",l[i][j]); } printf("\n"); } return 0; }

  • 要素数が10の配列で、乱数0~9の値が重複しないようにする方法がわからなくて困っています。

    JAVAの練習問題でわからなくて困っています 以下は線形探索のプログラムで、このプログラムを改良して、 要素数が10の配列で、乱数0~9の値が重複しないようにする方法がわからなくて困っています。 以下のような簡単なプログラムでできる方法で行いたいです。 どなたか答えまたはヒントを下さい、お願いします。 ------------------------------------------------------------ import java.util.Random; import java.util.Scanner; public static void main (String[] args) { Random rand = new Random(); Scanner stdIn = new Scanner(System.in); final int n = 10; //要素数 int[] a = new int[n]; //配列を宣言 for (int j = 0; j < n;) a[j] = rand.nextInt(10); System.out.print("配列aの全要素の値\n{ "); for (int j = 0; j < n; j++) System.out.print(a[j] + " "); System.out.println("}"); System.out.print("探す数値 : "); int key = stdIn.nextInt(); int i; for (i = 0; i < n; i++) if (a[i] == key) break; if (i < n) //探索成功 System.out.println("それはa[" + i + "]にあります。"); else //探索失敗 System.out.println("それはありません。"); } }

  • C#からC言語で作成したDLLに文字列の配列の受け渡しをする方法を教えて下さい

    初めまして、プログラミング自体経験が初心者なので根本的なところで間違っているかもしれませんがご指摘いただければと思いまして投稿します。 C#のプログラムからC言語で書かれたDLLを使いたいのですが、いくつか分からないことがあります。1つは文字列の配列の受け渡し方法、もう1つはその配列要素の文字列がマルチバイト文字である場合の方法です。 C#側 using System; using System.Runtime.InteropServices; public class MainClass { [DllImport("Cmdll.dll")] public static extern void SampleMethod([In, Out] string[] s, int x); static void Main() {     string[] str1 = new string[2] {"月曜日", "火曜日"};     SampleMethod(str1, n);     for (int i = 0; i < n; i++)       Console.WriteLine("str1[{0}] = {1}", i, str1[i]);   } } C言語側 void __declspec(dllexport) SampleMethod(char *str[], int n) {   int i;   for (i = 0; i < n; i++)     strcat(str[i], "ですね"); } なお、私用する文字を1バイト文字にすると動作しました。 DllImportの使い方も付け焼刃なので使い方が間違っていたらご指摘願えますでしょうか。よろしくお願いいたします。環境はVisual Studio 2008です。

  • 並べ替え

    次のようなプログラムを作れ。 1.数値を次々に読み込んで配列に1番目から順に格納する。 2.配列に格納されている数値を逆の順番に並べ換える (最後に読み込んだ数値が配列の1番目に入る)。 3.その配列の内容を1番目から順番に画面に出力する。読み込み、逆転、出力の部分はそれぞれ関数にすること。 という課題をやっています。下のように作ってみたんですが 上手くいかなくて・・・ 何処が悪いか教えて下さい。 #include <stdio.h> #define MAX 100 void reve(int *, int *); void read(int *, int *); void write(int *,int *); int main () { int x[MAX]; int n=0; read(&n, x); reve(&n, x); write(&n, x); return; } void read(int *n, int x[]) { while(scanf("%d", &x[n]) == 1 ) { n += 1; } return; } void reve(int *n, int x[]) { int i, j, y; for(i = 0, j = n-1; i <j; i++, j--) { y = x[j]; x[j] = x[i]; x[i] = y; } return; } void write(int *n, int x) { int i; for(i = n; i = 0; i--) { printf("x[%d] = %d\n", i, x[i]); } return; }

  • イメージボックスについて

    こんにちわ、Visual Studio 2005のC++を使ってプログラミングしているものです。イメージボックスについてお聞きしたいのですが、 private:array< PictureBox^>^ picture; int n = 0; int m = 0; int l = 0; for ( int n = 0; n < 4; n++ ) { if(n % 4 == 0){m = m + 60; l = 0;} /** 4つずつImageboxを表示 **/ picture[n] = gcnew PictureBox(); /** イメージボックス生成 **/ picture[n]->Size = Drawing::Size( 50, 50 );  /** イメージボックスのサイズ **/ picture[n]->SizeMode = System::Windows::Forms::PictureBoxSizeMode::StretchImage; picture[n]->Location = Drawing::Point( 10+50*l,10+m);  /** イメージボックスの位置座標 **/ picture[n]->Name = String::Format( L"pictures{0}", n );  /** イメージボックスの名前 **/ this->Controls->Add( picture[n] ); Int32^ o = gcnew Int32( 0 ); System::String^ filename = "C:/Documents and Settings/user/デスクトップ/画像/"; filename += o->ToString("000") + ".bmp";  /** フォルダ内の画像 **/ bmp[n] = gcnew Bitmap(filename,true);   picture[n]->Image = bmp[n];  /** イメージボックスnにイメージn表示 **/ l++; } といった感じで、とりあえず4つのイメージボックスを作ろうとしているのですがうまくいきません。画像ファイルの名前の足し方に問題があるのでしょうか@@; もしこのプログラムが通るようになったとしてもループ中に画像がなかったらエラーが起こってしまいますね。もし指定のフォルダを選んで、そのフォルダ内の画像を全て表示させるといったことはできないのでしょうか??それと今までデザイン時にピクチャボックスをダブルクリックすると、 private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) {} といったクリック処理のための関数が現れるのですが、この場合はどう処理すればよいのでしょう? さらに言うとこれをパネルの上でやりたいのですが・・・ private: System::Void panel1_Paint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) { panel1->Controls->Add( picture[0] ); } とりあえずこれは置いといて、どうプログラムすればよいのか分かる方がいればご教授お願いします。

  • 処理の途中で不正な文字が表示される

    学校でjavaを勉強しています。 「指定した配列と、その配列中の最大値を表示させる」という プログラムを作りたいのですが、コンパイルし実行すると ↓のように表示されてしまいます。どこに問題があるのでしょうか?教えてください。 配列a[] = { 3 最大1 1 最大5 5 4 0 5 -1 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsExcept ion: 7 at kadai5.main(kadai5.java:13) 元のプログラムは↓です。 class kadai5{ public static void main(String[] arg) { int i=0; int max=0; int[] score={3,1,5,4,0,5,-1}; int n=score.length; System.out.print("配列a[] = { "); while(i<n){ System.out.print(score[i]+" "); i=i+1; if(max<score[i]){ max=score[i]; System.out.println("最大"+max); } } System.out.println("}"+"\n\n"); System.out.println("最大値は"+max+"です。"); } }

    • ベストアンサー
    • Java
  • 画像のランダム表示

    初心者です。。 画像のランダム表示で、下のものを使っているのですが、 画像の上にカーソルをもっていったときに手のマークにしたいのですが、 どのようにすればできるのでしょうか? onclickを使っているからだと思うのですが、 A href=を使えばできるのでしょうか? よろしくお願いします。 <script type="text/javascript"> <!-- var imgs = new Array; var n = 5; var i; for(i=0;i<n;i++){ imgs[i] = new Image(); } imgs[0].src="image/001.jpg"; imgs[1].src="image/002.jpg"; imgs[2].src="image/003.jpg"; imgs[3].src="image/004.jpg"; imgs[4].src="image/005.jpg"; function disp(img){ img.src=imgs[Math.round(Math.random()*(n-1))].src; } //--> </script> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> </head> <body> <div align="center"> <img src="image/001.jpg" border="0" onclick="disp(this)"> </div> </body> </html>

  • *を表示させるプログラムを

    //putChars()メソッドを呼ばず(使わず) for文のネストで、できますか import java.util.Scanner; class IsoscelesTriangleRB { //--- 文字cをn個連続表示 ---// static void putChars(char c, int n) { while (n-- > 0) System.out.print(c); } public static void main(String[] args) { Scanner stdIn = new Scanner(System.in); System.out.println("右下直角の三角形を表示します。"); System.out.print("段数は:"); int n = stdIn.nextInt(); for (int i = 1; i <= n; i++) { putChars(' ', n - i); // ' 'をn - i個表示 putChars('+', i); // '+'を i 個表示 System.out.println(); } } }

  • JAVAで配列を使って * を縦向きのグラフで表示したいです。

    JAVAの勉強をしています。 このプログラムは配列に乱数を生成して * を 横向きにするプログラムです。 練習問題で、以下のプログラムを書き換えて、* を縦向きのグラフで表示する問題なのですが、解く方法がわかりません。 どなたか答えもしくはヒントを下さい。 よろしくお願いします。 import java.util.Random; import java.util.Scanner; public class Test06_04 { public static void main (String[] args) { Random rand = new Random(); Scanner stdIn = new Scanner(System.in); System.out.print("要素数 : "); int n = stdIn.nextInt(); //要素数を読み込む int[] a = new int[n]; //配列を生成 for (int i = 0; i < n; i++) { a[i] = 1+ rand.nextInt(10); } for (int i = 0; i < n; i++) { System.out.print("a[" + i + "] : "); for (int j = 0; j < a[i]; j++) System.out.print('*'); System.out.println(); } } }

    • ベストアンサー
    • Java
  • 関数の中身

    整数型の配列dとデータの個数nを引数として受け取り、d[0]からd[n-1]までの内容を逆順に入れ替える関数void revをつくってます。 void rev(int d[],int n) { int a,b,i; a=n-1; b=1; for(i=1;i<=a;i++){ b[]=d[n-1]; n--; b++; } } と作ったのですが、うまく動きません。 どこがおかしいのでしょうか? 書き直してもらってかまいません。

専門家に質問してみよう