prototype プロパティというものがようやく少しわかってきたような気がするので、覚書を書いておく。
<script type="text/javascript">
function A(){
this.a = "A の a";
this.b = "A の b";
}
var B = new A;
A.prototype.c = "A の c";
alert(B.c); // A の c
A.prototype = { a : "A2 の a" , b : "A2 の b" , c : "A2 の c"};
alert(B.c); //A の c
var C = new A;
alert(C.a); //A の a
alert(C.b); //A の b
alert(C.c); //A2 の c
</script>
prototypeプロパティはコンストラクタに関連付けされている参照型のプロパティである。 従って、クラス A のインスタンス B を作成してから、A の prototype プロパティに c というプロパティを作成した場合でも、B から参照可能である。 しかしながら、参照しているのはあくまでも B が作成された時点で A に設定されている prototype オブジェクトであり、このprototypeプロパティ自体をオブジェクト初期化演算子で書き換えると、書き換えた後に作成されたインスタンス C では書き換えられた後の prototype プロパティを参照するが、prototype プロパティを書き換える前に作成されていたインスタンス B は相変わらず書き換えられる前の prototype オブジェクトを参照しているため、c プロパティの値は相変わらず"A の c"となる。 ちなみにコンストラクタ関数の中で this で設定されたプロパティが優先されるので、C.a は"A の a"、C.b は"A の b"になる。
<script type="text/javascript">
function A( a , b ){
this.a = a;
A.prototype.b = b;
}
var B = new A("B の a" , "B の b");
alert( B.a + B.b ); //B の aB の b
var C = new A("C の a" , "C の b");
alert( C.a + C.b ); //C の aC の b
alert( B.a + B.b ); //B の aC の b
</script>
prototype プロパティに設定されたプロパティは参照型なので、複数のインスタンスが同一のプロパティを参照することになり、b プロパティに別の値が代入されれば、他のインスタンスでも b プロパティの値は代入後の値になる。 単に this でプロパティを設定しておけば、そのプロパティは参照型ではないので、インスタンス毎に別の値を取り得る。 従って、インスタンス変数として、複数のメソッドでその変数を使うような場合には、コンストラクタ関数内において this で設定したプロパティを使用する。 他方、メソッドのように複数のインスタンスで同一のプロパティを使いたい場合は、prototype プロパティにそのプロパティ(メソッド)を追加する。 実際にはprototypeプロパティにメソッドを追加する場合は、new する度に設定しなおさないようにコンストラクタの外で行う。 メソッドを単にコンストラクタ内で this.c = function(){} で設定することも可能だが、インスタンスが作られる毎にそれだけ別のプロパティが作成されることになり、new する度に余計な処理が行われ、メモリも無駄に消費されてしまう。 prototypeにしておけば、複数のインスタンスで1つのメソッドを共有できるので、コンストラクタの外で this.prototype.c = function(){} とするべきである。
今回は場合の数がかなり多いみたい。 ヒントの出し方にばらつきがあるんだよね。 次回はポイント数が足りないので、作らないかも。
<script type="text/javascript">
/*
*1.マークはすべて異なる
*2.2枚目が1番大きい
*3.マークは黒が少ない
*4.3枚中2枚は同じ数字
*5.2枚目は3の倍数
1.1枚目の記号はランダム
2.2枚目の数字を出してから1枚目と3枚目の数字を出す
3.1枚目と3枚目は同じ数字
4.1枚目の記号が赤なら、2枚目は1枚目以外でランダム、1枚目が黒なら赤でランダム
5.1枚目が赤で2枚目も赤なら、3枚目は黒でランダム
5.1枚目が赤で2枚目が黒なら、3枚目は赤の1枚目じゃない方
6.1枚目が黒なら、3枚目は赤の2枚目じゃない方
7.2枚目の数字は[3,6,9,12]のランダム
8.2枚目が3なら1枚目は[2,1]のランダム
9.2枚目が6なら1枚目は[5,4,3,2,1]のランダム
10.2枚目が9なら1枚目は[8,7,6,5,4,3,2,1]のランダム
11.2枚目が12なら1枚目は[11,10,9,8,7,6,5,4,3,2,1]のランダム
*/
Array.prototype.random_num = null;
Array.prototype.random_elm = function(){
this.random_num = Math.floor ( Math.random() * this.length );
return this [this.random_num];
}
function choice_card(){
var mark = ["heart","dia","spade","club"];
var red_mark = ["heart","dia"];
var black_mark = ["spade","club"];
var num_ary = [3,6,9,12];
var num_obj = { 3 : [2,1] , 6 : [5,4,3,2,1] , 9 : [8,7,6,5,4,3,2,1] , 12 : [11,10,9,8,7,6,5,4,3,2,1] };
var card = [];
var first_mark = mark.random_elm();
mark.splice( mark.random_num , 1 );
var first_bool = ( first_mark == "heart" || first_mark == "dia" );
var second_mark;
if ( first_bool ) second_mark = mark.random_elm();
else {
second_mark = red_mark.random_elm();
red_mark.splice( red_mark.random_num , 1 );
}
var second_bool = ( second_mark == "heart" || second_mark == "dia" );
var third_mark;
if ( first_bool ){
third_mark = second_bool ? black_mark.random_elm() : mark[0]; //spliceしているから0番目
}
else third_mark = red_mark[0]; //spliceしているから0番目
var second_num = num_ary.random_elm();
var first_num,third_num;
first_num = third_num = num_obj[second_num].random_elm();
card[0] = first_mark + first_num;
card[1] = second_mark + second_num;
card[2] = third_mark + third_num;
return card.join(",");
}
var choiced_card = [];
var i , i_max;
for( i = 0 , i_max = 15 ; i < i_max ; i++ ){
choiced_card[i] = choice_card();
}
var choiced_str = choiced_card.join(",");
var reg_exp;
var str = "";
for( i = 0 ; choiced_card[i] ; i++ ){
reg_exp = new RegExp( choiced_card[i] , "g" );
if( ( choiced_str.match( reg_exp ) ).length > 1 ) {
if( str.indexOf( choiced_card[i] ) > -1 ) {
choiced_card.splice( i , 1 );
i--; //spliceするとインデックス番号がずれるのを修正
}
str += choiced_card[i];
}
}
var joint_array = choiced_card.join("<br>");
document.write ( joint_array );
</script>
フレーム越しフローティングメニューを更に修正。っていうか、かなり基本的なことを見落としていて微妙に落ちてます。
もちろん誰にでもこういう見落としはあるのでしょうけれど。 まだまだ経験値不足を感じます。
まだ成長できる余地があるということは喜ばしいことでもあります。
昨日forループを使うといろいろ問題がある
と書いたけど、下記のように書けば問題ないですね。(部分的なコードなのでvar宣言が抜けてます。)
for( i = 0 ; choiced_card[i] ; i++ ){
reg_exp = new RegExp( choiced_card[i] , "g" );
if( ( choiced_str.match( reg_exp ) ).length > 1 ) {
if( str.indexOf( choiced_card[i] ) > -1 ) {
choiced_card.splice( i , 1 );
i--; //spliceするとインデックス番号がずれるのを修正
}
str += choiced_card[i];
}
}
本日正解発表分。 今回は重複した回答を削除する機能を実装してみた。
<script type="text/javascript">
/*
*1.3枚とも奇数
*2.1枚目 > 2枚目 > 3枚目
*3.マークは2種類で赤が多い
*4.3を仕様
*5.1枚目は13
1.1枚目の記号はランダムで数字は13
2.1枚目の記号が黒なら2枚目は赤、1枚目が赤なら2枚目はランダム
3.2枚目の数字は[11,9,7,5,3]のうちのどれか
4.1枚目と2枚目の記号が同じなら3枚目はそれ以外の記号でランダム
5.3枚目の記号が4.でない場合、1枚目が黒なら2枚目と同じ、1枚目が赤で2枚目が黒なら1枚目と同じ、両方赤ならハートかダイヤ
5.3枚目の数字は2枚目が[11,9,7,5]なら3、2枚目が3なら1
*/
Array.prototype.random_num = null;
Array.prototype.random_elm = function(){
this.random_num = Math.floor ( Math.random() * this.length );
return this [this.random_num];
}
function choice_card(){
var mark = ["heart","dia","spade","club"];
var red_mark = ["heart","dia"];
var num_ary = [11,9,7,5,3];
var card = [];
var first_mark = mark.random_elm();
var first_num = 13;
var first_random_num = mark.random_num;
var first_bool = ( first_mark == "spade" || first_mark == "club" );
var second_mark = first_bool ? red_mark.random_elm() : mark.random_elm();
var second_num = num_ary.random_elm();
var second_bool = ( second_mark == "spade" || second_mark == "club" );
var third_mark;
if( first_mark == second_mark ) {
mark.splice( first_random_num , 1 );
third_mark = mark.random_elm();
}
else third_mark = first_bool ? second_mark : ( second_bool ? first_mark : red_mark.random_elm() );
var third_num = ( second_num == 3 ) ? 1 : 3;
card[0] = first_mark + first_num;
card[1] = second_mark + second_num;
card[2] = third_mark + third_num;
return card.join(",");
}
var choiced_card = [];
var i , i_max;
for( i = 0 , i_max = 20 ; i < i_max ; i++ ){
choiced_card[i] = choice_card();
}
var choiced_str = choiced_card.join(",");
var reg_exp;
var str = "";
i = 0;
while(choiced_card[i]){
reg_exp = new RegExp( choiced_card[i] , "g" );
if( ( choiced_str.match( reg_exp ) ).length > 1 ) {
if( str.indexOf( choiced_card[i] ) > -1 ) {
choiced_card.splice( i , 1 );
i--; //spliceするとインデックス番号がずれるのを修正
}
str += choiced_card[i];
}
i++;
}
var joint_array = choiced_card.join("<br>");
document.write ( joint_array );
</script>
場合の数を正確に把握するのは面倒なので、出来た回答の配列から重複したものを排除しています。 forループを使うといろいろ問題があるので、whileループにしてみました。
11月9日正解発表分。 ロジックを組んでいくと、かなり場合の数が少ないことに気づく。 これでは答えの出力回数を増やすと、ダブりも多くなる。
<script type="text/javascript">
/*
*1.赤のマークが多い
*2.1枚目 × 2枚目 < 3枚目
*3.1枚目 × 1枚目 = 2枚目 //1枚目は3以下
*4.2種類とも69回と同じマーク //マークは2種類でクラブとハート
*5.3枚目の数字は11
//4.と1.からハートが2枚でクラブが1枚と分かる
//2.と5.より1枚目と2枚目をかけて11より小さい数で3.の式を満たす場合を考えればよい
//とりあえず2.と5.だけ満たす場合を考えると
//1枚目が1なら2枚目は10以下
//1枚目が2なら2枚目は5以下
//1枚目が3なら2枚目は3以下
//これで3.を満たすのは
//1枚目が1なら2枚目は1
//1枚目が2なら2枚目は4
//したがって、[1,1,11]か[2,4,11]のどちらかしかない
1.数字は最初に2種類の数字列を選ぶランダムにする
2.1枚目の記号はクラブかハートのランダム
3.2枚目の記号は1枚目がクラブのときはハートで3枚目の記号もハート
4.2枚目の記号は1枚目がハートで1のときはクラブで3枚目の記号はハート
5.2枚目の記号は1枚目目がハートで2のときはランダム
6.3枚目の記号は5.で1枚目と2枚目が同じときはクラブで、異なるときはハート
*/
Array.prototype.shuffle = function(){
return this [ Math.floor ( Math.random() * this.length ) ];
}
function choice_card(){
var Mark = ["heart","club"];
var num_str = ["1,1,11","2,4,11"];
var card = [];
var return_str = num_str.shuffle();
var return_num = return_str.split(",");
var first_mark = Mark.shuffle();
var second_mark , third_mark;
if(first_mark == "club") second_mark = third_mark = "heart";
else if(first_mark == "heart" && return_num[0] == "1"){
second_mark = "club";
third_mark = "heart";
}
else {
second_mark = Mark.shuffle();
third_mark = (first_mark == second_mark) ? "club" : "heart";
}
card[0] = first_mark + return_num[0];
card[1] = second_mark + return_num[1];
card[2] = third_mark + return_num[2];
return card.join(",");
}
var choiced_card = [];
for(i=0;i<10;i++){
choiced_card[i] = choice_card();
}
var joint_array = choiced_card.join("<br>");
document.write ( joint_array );
</script>
ダブりがないかどうかチェックするのなら、ループの回数も場合の数以下にするとか、ダブっていた場合はbreakするとか考えないといけないが、 そんなに場合の数が少ないのなら、手作業ですべて書き出した方が手っ取り早い。 でも、いちいち手書きするのも癪なので、JavaScriptで書き出してみることにする。
<script type="text/javascript">
var card = {
"1,1,11" : "heart,club,heart|club,heart,heart" ,
"2,4,11" : "heart,heart,club|heart,club,heart|club,heart,heart"
};
var split_value , i , j , i_max , j_max , split_array , mark_array , num_array ;
var temp_array = [];
var result_array = [];
for(i in card){
split_value = card[i].split("|");
for(j = 0 , j_max = split_value.length ; j < j_max ; j++){
temp_array.push( split_value[j] + "|" + i )
}
}
for(i = 0 , i_max = temp_array.length ; i < i_max ; i++){
split_array = temp_array[i].split("|");
mark_array = split_array[0].split(",");
num_array = split_array[1].split(",");
result_array[i] = [];
for(j=0 , j_max = mark_array.length ; j < j_max ; j++){
result_array[i].push( mark_array[j] + num_array[j] );
}
}
var result = result_array.join("<br>");
document.write(result);
</script>
なんと5通りしかない答えのためにこんな大変なことに!
まったくもって、意味なし芳一ですな。
トランプ3枚当て用スクリプト(その3)で配列のインデックス番号を後で取り出すときに不便
って書いたけど、よく考えたら、ほしい値をグローバル変数に代入すればいいだけでした。
でも、どうせならグローバル変数じゃなくてオブジェクトのプロパティに代入しちゃいましょう。
prototypeでネイティブオブジェクトのプロパティを定義してもあまり意味がないと思ってたけど、そうでもないかな。
<script type="text/javascript">
Array.prototype.random_num = null;
Array.prototype.random_elm = function(){
this.random_num = Math.floor ( Math.random() * this.length );
return this [this.random_num];
}
var Mark = ["heart","dia","spade","club"];
var return_elm = Mark.random_elm();
alert(Mark.random_num);
alert(return_elm);
</script>
11月2日正解発表分。
Array.prototype.shuffle
ってやるのは、配列のインデックス番号を後で取り出すときに不便なんで、微妙なところもあります。
やっぱ関数にした方が式の途中の値を使うときは便利かも。
わざわざtemp_mark.splice ( --first_num / 2 , 1 )
とかやってたり。
<script type="text/javascript">
/*
*1.絵札はなし
*2.1枚目 ÷ 2枚目 = 1 //1枚目と2枚目は同じ数字即ち違うカード
*3.クラブを使用
*4.マークは2種類で違う色
*5.数字は3枚とも奇数
1.1枚目の記号はスペード以外でランダム
2.2枚目の記号は1枚目がクラブならハートかダイヤ、1枚目がクラブでないならクラブ
3.3枚目の記号は1枚目か2枚目のどちらか
4.1枚目の数字は奇数で9以下でランダム
5.2枚目の数字は1枚目と同じ
6.3枚目の数字は奇数で9以下で1枚目の数字以外でランダム
*/
Array.prototype.shuffle = function(){
return this [ Math.floor ( Math.random() * this.length ) ];
}
function choice_card(){
var Mark = ["heart","dia","club"];
var Mark2 = ["heart","dia"];
var heart = [1,3,5,7,9];
var dia = [1,3,5,7,9];
var club = [1,3,5,7,9];
var card = [];
var first_mark = Mark.shuffle();
var temp_mark = eval ( first_mark );
var first_num = temp_mark.shuffle();
card[0] = first_mark + first_num;
var second_mark = ( first_mark == "club" ) ? Mark2.shuffle() : "club";
var second_num = first_num;
card[1] = second_mark + second_num;
var temp_array = [];
temp_array.push( first_mark , second_mark );
var third_mark = temp_array.shuffle();
temp_mark.splice ( --first_num / 2 , 1 ); //1を引いて2で割ると0から数えた位置になる
var third_num = temp_mark.shuffle();
card[2] = third_mark + third_num;
return card.join(",");
}
var choiced_card = [];
for(i=0;i<10;i++){
choiced_card[i] = choice_card();
}
var joint_array = choiced_card.join("<br>");
document.write ( joint_array );
</script>
もともとキャバクラのサイトを見ているうちにインターネットにハマり、最近はJavaScriptに凝っている今日この頃です。
FC2 Blog Rankingに参加中。
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
---|---|---|---|---|---|---|
- | - | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | - | - | - |