【解決済み】複数の変数の値を比較・順位を算出するプラグイン

スズミ
記事: 9
登録日時: 2016年6月26日(日) 16:16

【解決済み】複数の変数の値を比較・順位を算出するプラグイン

投稿記事by スズミ » 2016年8月02日(火) 23:51

いつもお世話になっております。

『複数の変数の値を比較して、得られた結果をまた別の変数へと返してくれる』
プラグインをリクエストさせて頂きたいのですが…

希望している機能は、
『指定した複数の変数を、値の大きい順or小さい順に並び替えて、どの変数が何番目に大きいor小さいのか順位を出す。
そしてその結果の順位などを希望した変数へ代入する』
というものです。

例えば

変数#0001 = 10
変数#0002 = 5
変数#0003 = 20
変数#0004 = 7

だった場合、プラグインコマンドなどで
●『変数#0001~変数#0004の値を比較した中で、一番値が大きかった変数のIDを#0005に代入する』
と命令したら、

ここでは変数#0003 が一番大きいので、
#0005 = 3 と代入。

●『変数#0001~変数#0004の値の大きさを比較して、
1番目に大きい変数のID を #0011 へ、
2番目に大きい変数のID を #0012 へ、
3番目に大きい変数のID を #0013 へ、
4番目に大きい変数のID を #0014 へ、それぞれ代入』
と命令したら、

#0011 = 3
#0012 = 1
#0013 = 4
#0014 = 2   と代入。

…というような感じに、比較した結果をまた別の変数へと返してくれるプラグインが欲しいのです。


実際ゲーム中でどう使用したいのかと言いますと、

●例えばアクター全員の攻撃力の数値を予めどこか変数に代入しておき、
それらを全て比較して、攻撃力のランキングが作れるようにする。

●ゲーム内のミニゲームなどで、予め変数にスコアを記録しておき
ハイスコア3位以内に入ったら何かイベントを発生させる

…といった感じです。


説明が分かり辛くてすみません。

イベントの条件分岐からでも地道にできなくはない気もするのですが、
比較したい変数の数が増えくると流石に大変でして…(><;)

またもし同様の機能を持つ既存のプラグインや、効率のよいイベントの組み方を
ご存知の方いらっしゃいましたらお教え頂けますと大変助かります!
お手数ですがよろしくお願い致します。m(_ _)m
最後に編集したユーザー スズミ on 2016年8月04日(木) 07:40 [ 編集 1 回目 ]

VXaceからツクールを始めた初心者です。今はmvを勉強中。
プラグインを提供して下さる方々、いつも助けられております。ありがとうございます。
アバター
yamachan
記事: 107
登録日時: 2016年6月19日(日) 22:34

Re: 複数の変数の値を比較・順位を算出するプラグイン

投稿記事by yamachan » 2016年8月03日(水) 00:24

こんばんは! :D

最近は1行コードに少しハマっております。

変数#0001~変数#0004の値を比較した中で、一番値が大きかった変数のIDを#0005に代入する

でしたら、変数5の値のスクリプトのところに以下をコピーすればいけるかもしれません。

コード: 全て選択

(function(){var s=1,e=4,max=0,l=0;$gameVariables._data.slice(s,e).forEach(function(v,i){if (v>max){max = v;l=i}});return l + s})();

s=1,e=4 のところが変数の範囲で、変数10~20であれば s=10,e=20 です。
得たいのが最大の値であれば return 部分を変更して

コード: 全て選択

(function(){var s=1,e=4,max=0,l=0;$gameVariables._data.slice(s,e).forEach(function(v,i){if (v>max){max = v;l=i}});return max})();


『変数#0001~変数#0004の値の大きさを比較して、
1番目に大きい変数のID を #0011 へ、
2番目に大きい変数のID を #0012 へ、

こちらであれば、変数0011の式は以下で

コード: 全て選択

($gameVariables._data.map(function(v,i){return [v,i]}).slice(1,4).filter(function(v){return v[0]!==undefined}).sort().reverse())[0][1]

変数0012の式は以下で

コード: 全て選択

($gameVariables._data.map(function(v,i){return [v,i]}).slice(1,4).filter(function(v){return v[0]!==undefined}).sort().reverse())[1][1]

変数0013の式は以下で

コード: 全て選択

($gameVariables._data.map(function(v,i){return [v,i]}).slice(1,4).filter(function(v){return v[0]!==undefined}).sort().reverse())[2][1]

という風に、最後から二番目の数字が順位なので、0から1つづつ増やしていけばいけそうです。
ちなみに最後の数字を1から0にすると変数番号ではなく変数の値になります。
.slice(1,4) の部分が範囲です。変数10~20であれば .slice(10,20) です。

以上、書いてみたら思ったよりマニアックになってしまったので…
あくまで参考程度にしてください ;)

ではでは!
Toshio Yamashita (yamachan)
Plugin https://github.com/yamachan/jgss-hack/blob/master/README.ja.md
Twitter https://twitter.com/yamachan360

私が作成して本サイトに投稿したコードは著作権を放棄し、利用・改変・配布など全て自由です。
ただし同じ投降内に制限を明記している場合はそちらが優先します。
スズミ
記事: 9
登録日時: 2016年6月26日(日) 16:16

Re: 複数の変数の値を比較・順位を算出するプラグイン

投稿記事by スズミ » 2016年8月03日(水) 08:35

yamachanさま

前回の質問に引き続き、丁寧な回答頂けて嬉しいです!ありがとうございます。
さっそく頂いた記述の通りにスクリプト欄に入力し、制御文字等用いて試しに

『変数1~4番に毎回乱数を発生、
発生した乱数 と、 一番値が大きかった変数のID と、 その値 を知らせる』
というイベントを組んでみたのですが↓
変数プラグインのテスト01.jpg

基本大きい値を判別してくれるのですが
どうも変数4番が最大だった場合にのみ、結果がおかしくなるようです;


また、後半に載せて頂いた
大きい順に指定の変数へ一つずつ、代入させていくイベントも組んでみたのですが
何やらエラー?が出てしまいました↓
変数プラグインのテスト02.jpg



あとうっかり失念していたのですが、
『指定した複数の変数の中に、値が同じのもの(要は同点一位等)が発生した場合の処理』 も
設定しておかないと、いざランキングを作ろうとしたとき不都合が起きるかもしれないですね;;
(ちなみに今回組んでみたイベントでは、同じ値だった場合変数IDが若い方が優先されてました)

ちょっと手さぐりではありますが、頂いた回答を参考に
JavaScriptでのソートについて自分でも調べてみようと思います。ありがとうございました!
VXaceからツクールを始めた初心者です。今はmvを勉強中。
プラグインを提供して下さる方々、いつも助けられております。ありがとうございます。
アバター
yamachan
記事: 107
登録日時: 2016年6月19日(日) 22:34

Re: 複数の変数の値を比較・順位を算出するプラグイン

投稿記事by yamachan » 2016年8月03日(水) 11:25

おはようございます! :D

すみません、一点間違っていました。
.slice(1,4) の部分が範囲です。変数10~20であれば .slice(10,20) です。

の部分ですが、.sliceは 「第1引数から、第2引数の直前まで」 を返す仕様だったことを失念していました。
なので第2引数に指定する値は+1しなければなりません。

よって以下に変更させていただきます。

コード: 全て選択

(function(){var s=1,e=5,max=0,l=0;$gameVariables._data.slice(s,e).forEach(function(v,i){if (v>max){max = v;l=i}});return l + s})();

s=1,e=5 のところが変数の範囲で、変数10~20であれば s=10,e=21 です。

コード: 全て選択

($gameVariables._data.map(function(v,i){return [v,i]}).slice(1,5).filter(function(v){return v[0]!==undefined}).sort().reverse())[0][1]

.slice(1,5) の部分が範囲です。変数10~20であれば .slice(10,21) です。

後半が動かない件は、コンソールでしか動作確認していない弊害ですね、すみません。
いまちょっと時間がないので、あとで試してみます。

ではでは。
Toshio Yamashita (yamachan)
Plugin https://github.com/yamachan/jgss-hack/blob/master/README.ja.md
Twitter https://twitter.com/yamachan360

私が作成して本サイトに投稿したコードは著作権を放棄し、利用・改変・配布など全て自由です。
ただし同じ投降内に制限を明記している場合はそちらが優先します。
アバター
yamachan
記事: 107
登録日時: 2016年6月19日(日) 22:34

Re: 複数の変数の値を比較・順位を算出するプラグイン

投稿記事by yamachan » 2016年8月03日(水) 16:33

こんにちは! :D

後半の1行コードですが、こちらで実際に試したら問題なく動作しているようにみえます。
何かが違うのでしょうかね…

まあどれも原理は簡単なので、使えそうな部分を作成されるプラグインで利用いただければとおもいます。
ではでは。
Toshio Yamashita (yamachan)
Plugin https://github.com/yamachan/jgss-hack/blob/master/README.ja.md
Twitter https://twitter.com/yamachan360

私が作成して本サイトに投稿したコードは著作権を放棄し、利用・改変・配布など全て自由です。
ただし同じ投降内に制限を明記している場合はそちらが優先します。
スズミ
記事: 9
登録日時: 2016年6月26日(日) 16:16

Re: 複数の変数の値を比較・順位を算出するプラグイン

投稿記事by スズミ » 2016年8月04日(木) 00:24

yamachanさま
ご返信ありがとうございます
直して頂いた通りに.slice部分を記述し直したら、4番の変数も正しく比較してくれるようになりました。
シンプルでゲーム内のイベントにたくさん応用できそうです。わくわく! :D


そして並び替え・ランキング化のイベントもエラーは吐かずに動くようになりました。
↓ただし、桁の異なる数を比較した時のみ順位がなんだかおかしくなるようです??
変数テスト02.jpg

ちょっと調べてみましたが、おそらくソートの方式がデフォルトだとアルファベット辞書順?なのでしょうか?

できれば数の大小でソートさせたいので、
もしお手数でなかったら、解決できる記述を教えて頂けると有難いのですが…;
重ね重ねすみません、よろしくお願いします<(_ _)>
VXaceからツクールを始めた初心者です。今はmvを勉強中。
プラグインを提供して下さる方々、いつも助けられております。ありがとうございます。
アバター
yamachan
記事: 107
登録日時: 2016年6月19日(日) 22:34

Re: 複数の変数の値を比較・順位を算出するプラグイン

投稿記事by yamachan » 2016年8月04日(木) 01:35

スズミさん、こんばんは! :D

ご確認ありがとうございます!
なるほど、sort() の標準の比較関数は数値も文字列変換してしまうのですね…
知りませんでした、スイマセン… :oops:

では後半のほうですが .sort().reverse() を .sort(function(a,b){return b[0]-a[0]}) で置き換えていただけないでしょうか。
以下のようになります。

コード: 全て選択

($gameVariables._data.map(function(v,i){return [v,i]}).slice(1,5).filter(function(v){return v[0]!==undefined}).sort(function(a,b){return b[0]-a[0]}))[0][1]


ちなみに毎回↑をコピペするのが面倒な場合は、作業用の変数(今回は17番)にいったん

コード: 全て選択

$gameVariables._data.map(function(v,i){return [v,i]}).slice(1,5).filter(function(v){return v[0]!==undefined}).sort(function(a,b){return b[0]-a[0]})

とソート結果を代入しておけば、以後は以下のように簡単にアクセスできるとおもいます。

1位は $gameVariables.value(17)[0][1]
2位は $gameVariables.value(17)[1][1]
3位は $gameVariables.value(17)[2][1]
4位は $gameVariables.value(17)[3][1]

ではでは。

<追記>
今回ご紹介したソートでは、同じ値の場合には順番が不定になってしまいます。もし同じ値の場合には若い変数番号のほうが上位になるべきであれば
.sort(function(a,b){return b[0]-a[0]})
は以下のように同じ値の場合の処理を追加すべきかもしれません。
.sort(function(a,b){return b[0]==a[0] ? a[1]-b[1] : b[0]-a[0]})
逆に変数番号が大きいほうが上位にくるべきであれば以下でしょうか。
.sort(function(a,b){return b[0]==a[0] ? b[1]-a[1] : b[0]-a[0]})
Toshio Yamashita (yamachan)
Plugin https://github.com/yamachan/jgss-hack/blob/master/README.ja.md
Twitter https://twitter.com/yamachan360

私が作成して本サイトに投稿したコードは著作権を放棄し、利用・改変・配布など全て自由です。
ただし同じ投降内に制限を明記している場合はそちらが優先します。
スズミ
記事: 9
登録日時: 2016年6月26日(日) 16:16

Re: 複数の変数の値を比較・順位を算出するプラグイン

投稿記事by スズミ » 2016年8月04日(木) 07:39

yamachanさま

ご返信ありがとうございます!こちらこそよく分からないままリクエストしちゃってすいません;
なるほど、ソート時は数値も文字列として扱われる仕様だったんですね。

そして解説頂いた通りコードで置き換えてみたところ、ちゃんと数の大小で並び替わるようになりました!わーい :D
変数テスト03.jpg

また、気になっていた『同じ値が出たときの処理』や、コードの短縮化まで、至れり尽くせりで感謝です。

というか、変数に入った式ごと$gameVariables.valueで取得して使えちゃう?のですね :idea:
知らなかったので勉強になります。

こちらのコードを使えば、単なるランキング表示だけでなく
「攻撃力重視でおまかせパーティを編成」とか、色々便利なイベントも組めそうです。

今回は希望通りのプラグインを組んで頂けたので、
こちらのトピックはこれで解決済みとさせて頂きます。yamachanさま、分かりやすい解説をありがとうございました!
VXaceからツクールを始めた初心者です。今はmvを勉強中。
プラグインを提供して下さる方々、いつも助けられております。ありがとうございます。

“MV:プラグイン素材のリクエスト” へ戻る