10000枚を重複無しで出すと言うのは結構難しいですね。
ActionScript で,
0~9999 の重複しないランダムな要素を持つ配列の作成に挑戦しましたが,
その時点で断念しました↓(失敗部品)↓。
-----------------------------------------------
// 写真の枚数の登録
var pNum = 10000;
//
//※処理時間を求めるためのスクリプト1
var time1 = getTimer();
//
// 配列 aArr 要素の作成
var aArr = new Array();
// aArr[0]~aArr[9999] の配列に 0~9999 の数を代入
for (var i = 0; i<pNum; i++) {
aArr[i] = i;
}
// 配列 bArr 要素の作成
var bArr = new Array();
//
for (i=0; i<pNum; i++) {
// 変数rNumに aArr の要素数までの整数の乱数を取得
rNum = Math.floor(Math.random()*aArr.length);
// 出力配列 に入力配列の乱数番目の要素を代入
bArr[i] = aArr[rNum];
// 入力配列の乱数番目の要素を抜き取る
// (aArr.length はこの時点で1つ減る)
aArr.splice(rNum, 1);
}
//
//※処理時間を求めるためのスクリプト2
var time2 = getTimer();
trace(time2-time1);
-----------------------------------------------
※注意
上記スクリプトは実行させない方が良いです。
私の CPU 2000MHz くらいの PC ではフリーズしました。
フリーズというか,例の(私は)よく見る,
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
ムービー内のスクリプトが原因で Flash Player の
実行速度が遅くなっています。
このまま継続すると、反応しなくなることがあります。
スクリプトの実行を中止しますか?
[ はい(Y) ] [ いいえ(N) ]
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
のダイアログ出るという意味です。
var pNum = 10000; を var pNum = 1000; に
変更する(1/10 にする)と大丈夫で,
処理時間 約 1100ミリ秒 (1秒少し)で,
0~999 の重複しないランダムな要素を持つ配列が
作成できました。
上の重複しないランダムな整数が取得できると後は簡単なのですけどね。
上のようにあらかじめ重複しない数を出すのではなく,
前に出した数字と重複しない数をその都度出すというのも,
後になればなるほど処理が増すのでいやですし,
ActionScript だけで解決するのは困難ではないかと思います(おそらく)。
////////////////////////////////////////////////////////
前置きの失敗談はこの辺で置いておいて,
別案で,
Excle を使ってデータを用意する方法を提案します。
Excle の「A1」セル(一番左上のセル)に
=RAND()
と書きます。
そして,
「B1」セル(一番上の左から2列目のセル)に
="&p"& ROW() &"="&RANK(A1,$A$1:$A$10000,1)-1 & "&"
と書きます。
そして,
「A1」 セルと「B1」セルの2つのセルを選択した状態で,
「B1」セルの右下のコーナー辺りにある□(ハンドル)を,
10000行目まで,ダーーーッとドラッグします。
つまり オートフィル機能で連続コピペをします。
すると,
「B1」~「B10000」に,
------------------
&p0=2593&
&p1=5289&
&p2=9651&
&p3=60&
&p4=6546&
&p5=2831&
&p6=3022&
&p7=2448&
&p8=9452&
&p9=9921&
&p10=187&
…略…
&p9997=3631&
&p9998=8418&
&p9999=1465&
------------------
のようなものが得られます。
ランダムなので,当然右辺は人や時によって違います。
2593 とか 5289 とか 9651 など右辺の値は,
0 ~9999 までの重複しない数になっているはずです(確率的におそらく)。
もし心配であれば,
=IF(COUNTIF(A:A,A1)>1,"重複","")
と 「C1」 セルに書いて,
これまた 10000行 までオートフィルでコピーしてください。
重複があれば「重複」が表示されると思いますから,
もし「重複」が表示されれば再計算させれば良いと思います。
Excel でも計算はかなりもたつきますよ。
でもそのもたつく処理は作成時の1度きりですし,
Flash のようにアニメーションソフトではないので,
もたついても問題はないでしょう。
また,Flash がもたつくと多くの見る人にとって迷惑ですが,
作者だけがもたつくわけですから,少々は我慢です。
それで,この,
「B1」~「B10000」を選択して「コピー」,
メモ帳などテキストエディタを起動させて,
「ペースト」します。
そして,
そのテキストデータを,
例えば「mydata.txt」というテキストファイルで保存します。
改行コードなども指定できるテキストエディタだと,
「改行=LF」など1つにしておくとファイル容量も削減できます。
改行コードを LF のみにして,「mydata.txt」を保存すると,
私の場合 124 KB (127,780 バイト) のテキストファイルになりました。
この「mydata.txt」のデータを Flash でロードして使えば良いのではないでしょうか。
Aというフォルダにある10000枚の画像ファイルは,
「0.jpg」,「1.jpg」,「2.jpg」,「3.jpg」,…,「9999.jpg」というファイル名にしておきます。
Flash も 「mydata.txt」 も「Aフォルダ」と同じフォルダに置くものとします。
任意のフォルダ
├ ○○.html
├ ○○.swf
├ mydata.txt
└ A
├ 0.jpg
├ 1.jpg
├ 2.jpg
… 略 …
└ 9999.jpg
Flash の作成ですが,
まず,ステージ上に JPEG をロードするためのムービークリップを作成します。
これは,1辺10px くらいの小さなムービークリップで良いです。
そのムービークリップに「myMC」というインスタンス名を付けたとします。
そして,
_root のタイムラインのフレーム1に次のように書けば一応完成です。
--------------------------------------------
// 写真の枚数の指定(可変)
var pNum = 10000;
//
// カウンタの初期化
var cnt = 0;
//
// 画像を読み込むユーザ定義関数の定義
function loadGazou() {
// myMC に Aフォルダ内のランダムjpgをロード
_root.myMC.loadMovie("A/"+myLV["p"+cnt]+".jpg");
// カウントの加算
cnt++;
// もしカウントが指定枚数に達すれば
if (cnt>=pNum) {
// setIntervalを解除
clearInterval(myID);
}
}
// LoadVareクラスのインスタンス myLV を作成
var myLV = new LoadVars();
//
// 外部テキストがロードされたときの処理を定義
myLV.onLoad = function() {
// ユーザ定義関数 loadGazou の初回実行
loadGazou();
// そのあと loadGazou を2000ミリ秒ごとに実行
myID = setInterval(loadGazou, 2000);
};
//
// LoadVarsインスタンスにテキストのロード
myLV.load("mydata.txt");
--------------------------------------------
一応以上で,ご質問の回答にはなっていると思います。
上の例で行くと,2秒間隔で写真が変わるので,
約5時間半の間,重複しない画像がランダムに表示されます。
その後(約5時間半後)のことは知りませんよ。
上の例の場合,約5時間半後,10000枚目が表示されたままストップします。
普通の場合は,また始めの写真に戻ると思いますが,
その場合,「重複」になるので,この回答にはならないためここで終わりとなります。
しかし,
上の方法は,大きな欠点が1つありますよね。
ご質問には書かれていませんから,どうでもいいことなのかもしれませんが,
1回目に見るときも,2回目に見るときも,何回目に見るときも,
例えば「p0=2593」は固定なのですから,毎回 「2593.jpg」 からの閲覧になります。
この欠点は,
SharedObject(Cookieみたいなもの) を使って,
変数 cnt の値を保存しておくと,
次回閲覧からは続きの JPEG から見ることが可能になり,解消されます。
--------------------------------------------
// 写真の枚数の指定(可変)
var pNum = 10000;
//
// SharedObject mySO の作成&データの読み込み
var mySO = SharedObject.getLocal("mysol");
// もし mySO のデータに cnt という変数が存在しなければ
if (mySO.data.cnt == undefined) {
// mySO のデータに cnt の初期化
mySO.data.cnt = 0;
}
//
// 画像を読み込むユーザ定義関数の定義
function loadGazou() {
// myMC に Aフォルダ内のランダムjpgをロード
_root.myMC.loadMovie("A/"+myLV["p"+mySO.data.cnt]+".jpg");
// mySO のカウントを加算
mySO.data.cnt++;
// もしカウントが指定枚数に達すれば
if (mySO.data.cnt>=pNum) {
// setIntervalを解除
clearInterval(myID);
}
}
// LoadVareクラスのインスタンス myLV を作成
var myLV = new LoadVars();
//
// 外部テキストがロードされたときの処理を定義
myLV.onLoad = function() {
// ユーザ定義関数 loadGazou の初回実行
loadGazou();
// そのあと loadGazou を2000ミリ秒ごとに実行
myID = setInterval(loadGazou, 2000);
};
//
// LoadVarsインスタンスにテキストのロード
myLV.load("mydata.txt");
--------------------------------------------
10000枚目到達までであれば,
何回見ても重複することはありません。
毎日1時間ずつ見ても5日目くらいまでは重複無しです。
しかし,
これも,10000枚目が表示された後のことは知りませんよ。
同じく,最後は10000枚目が表示されたままストップします。
SharedObject に関しては度々回答しております。
つい先日回答したものがありますが参考になるかもしれません。
「一日一度の抽選の方法」
http://oshiete1.goo.ne.jp/qa2809647.html
↑教えて!goo ↓OKWave (同じです)
http://okwave.jp/qa2809647.html
======================
あと
先に書くべきだったことかもしれませんが,
この方法で,実際に作業し始めるとわかると思うのですが,
A というフォルダにある10000枚の画像ファイルは,
「0.jpg」,「1.jpg」,「2.jpg」,「3.jpg」,…,「9999.jpg」というファイル名にしなくても良いのですよ。
Excel で,先に単に重複しないランダムな数を出したので,
後から上のように 「0.jpg」,「1.jpg」,「2.jpg」,「3.jpg」,…,「9999.jpg」というファイル名にしなければならないだけです。
実際は何でも良いのです。
何でしたら今現在の実際の名前のままでも良いです。
Excel の VBA フォルダ内のファイル名の一覧表を作って,
それをランダムにシャッフルして,
とにかく,外部テキストを,
------------------
&p0=sep0003&
&p1=apr0009&
&p2=may0121&
&p3=oct0010&
&p4=jun6546&
&p5=dec1831&
&p6=may0002&
&p7=jan00048&
&p8=mar0052&
&p9=sep09921&
&p10=feb0170&
…略…
&p9997=aug0031&
&p9998=dec0018&
&p9999=jul0014&
------------------
このような形にしさえすれば,
上記スクリプトをそのままの使えます。
こういう点においても,データ作成はExcle を使うと便利ですね。
ファイルネームの自動取得も簡単です↓。
「Office TANAKA - VBA講座:ファイルの操作(ファイルの一覧を取得する)」
http://officetanaka.net/excel/vba/file/file07.htm
ActionScript では,こんなことは普通はできません。
VBA だと簡単です。
ファイルネームの自動取得後のランダムシャッフルは,
上の =RAND() 関数を使えばできますよね。
「A列」 にファイル名を得た場合,
「B列」にダーーーーッと =RAND() を書いて,
「A列」全体と「B列」全体を選択した状態で,
「データ」→「並べ替え」を選択して,
「優先されるキー」を「列 B」にして,並べ替えをすれば良いだけです。
VBA でもできますが,
VBA を考える時間があったら,上の方法で何百回でもシャッフルできると思います。
私自身,Flash 作成のために,
実際に シート関数 や VBA を使うことは多々あります。
こういう大きなデータを扱う場合は,ActionScript だけでなく,色んなものを利用する方が良いと思います。
お礼
素晴らしい回答・・・助かります! なるほど、、、やはりぼんやり考えていた通り外部テキストファイルを利用するのですね。 なにぶん初心者なもので当回答を解釈するのも難しそうですが、土日にでもご回答を参考にいろいろ試してみようと思います。 これがOKWeb初の質問なのですが、これほどまでに丁寧で詳細な回答がいただけるとは思いませんでした。 本当にありがとうございました!!