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

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

ただいまの
回答率

87.93%

上手くscriptが機能してくれません........

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 1,143

score 347

こんにちは。

じゃんけんゲームのスクリプトをつけているのですが、重いからなのか、動作が上手くいったりいかなかったりします。コンソールにはエラーが出ていないので、書き方が悪いのでしょうが、キャッシュを溜める、チェーンを使うなどの対策をできる限りやってみても改善しません。

ここをこうしたほうが良いという意見をください。よろしくお願いいたします。

        <div id="screen_box">
            <div id="enemy_life"></div>
            <div id="our_life"></div>
            <div id="screen"><img src="" id="screen_img"></div>
        </div>
        
        <div id="text_box">ボタンを押してください</div>
        
        <div id="game_sta">ゲームスタート</div>
        
        <div id="your_hands">
            <div id="rock"><img src="img/%E3%81%90%E3%83%BC.png" class="hand_imgs"></div>
            <div id="scissors"><img src="img/%E3%81%A1%E3%82%87%E3%81%8D.png" class="hand_imgs"></div>
            <div id="paper"><img src="img/%E3%81%B1%E3%83%BC.png" class="hand_imgs"></div>
        </div>
        

イメージ説明スタートを押す前

イメージ説明スタートを押した後


<script>
        $(function(){
            //キャッシュ
            var screen = $('#screen');
            var screen_img = $('#screen_img');
            var text_box = $('#text_box')
            var rock = $('#rock');
            var scissors = $('#scissors');
            var paper = $('#paper');
            
            
            //敵のArray
            var enemy = [
                'img/%E3%81%90%E3%83%BC.png',
                'img/%E3%81%A1%E3%82%87%E3%81%8D.png',
                'img/%E3%81%B1%E3%83%BC.png'
            ];
            var enemy_name = ['グー','チョキ','パー'];
            
            
            //敵を決定する関数
            function show_up(){
                var num = Math.floor(Math.random()*3);
                
                screen_img.fadeIn(50);
                screen_img.attr('src',enemy[num]);
                text_box.text(enemy_name[num] + 'が現れた!');
                
                return num;
            };
            
            //スタートを押したとき
            $('#game_sta').click(function(){
                $('#your_hands').show();
                $(this).hide();
                
                game_proc();
            });
            
            //相手との戦闘の判定をする関数
            function game_proc(){
                on_command();
                show_up();
                
                if(show_up() === 0){
                    rock.on('click',function(){
                        counter();
                    });
                    scissors.on('click',function(){
                        lose();
                    });
                    paper.on('click',function(){
                        beat();
                    });
                }else if(show_up() === 1){
                    rock.on('click',function(){
                        beat();
                    });
                    scissors.on('click',function(){
                        counter();
                    });
                    paper.on('click',function(){
                        lose();
                    });
                }else if(show_up() === 2){
                    rock.on('click',function(){
                        lose();
                    });
                    scissors.on('click',function(){
                        beat();
                    });
                    paper.on('click',function(){
                        counter();
                    });
                }
            };
            
            //じゃんけんコマンドをオフ
            function off_command(){
                rock.off('click');
                scissors.off('click');
                paper.off('click');
            };
            
            //じゃんけんコマンドをオン
            function on_command(){
                rock.on('click');
                scissors.on('click');
                paper.on('click');
            };
            
            //相手を倒した時の関数
            function beat(){
                screen_img.fadeOut(1000);
                text_box.text('効果は抜群だ!');
                off_command();
                screen.click(function(){
                    game_proc();
                });
            };
            
            //相手と引き分けた時の関数
            function counter(){
                screen_img.fadeOut(20,function(){$(this).fadeIn(20,function(){$(this).fadeOut(20,function(){$(this).fadeIn(20)})})});
                text_box.text('相打ちだ!');
                off_command();
                screen.click(function(){
                    game_proc();
                });
            };
            
            //相手に負けた時の関数
            function lose(){
                screen_img.animate({height:"120px"}, 1000).animate({height:"300px"}, 1000);
                text_box.text('大ダメージを受けた!');
                off_command();
                screen.click(function(){
                    game_proc();
                });
            };
           
        });
    </script>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

0

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>じゃんけん jQuery.on の使い方サンプル</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<script>
var jankens = {
    "GOO" : {
        labelJp: "ぐー",
        labelEn: "Iron Fist",
        imageW : "GooW.png",
        imageH : "GooH.png",
        battle : function(te) {
            if (te == "GOO") return 1;
            if (te == "PAR") return 0;
            return 2; //CHO
        }
    },
    "CHO" : {
        labelJp: "ちょき",
        labelEn: "Blinding",
        imageW : "ChoW.png",
        imageH : "ChoH.png",
        battle : function(te) {
            if (te == "CHO") return 1;
            if (te == "GOO") return 0;
            return 2; // PAR
        }
    
    },
    "PAR" : {
        labelJp: "ぱぁ",
        labelEn: "Palm Bottom",
        imageW : "ParW.png",
        imageH : "ParH.png",
        battle : function(te) {
            if (te == "PAR") return 1;
            if (te == "CHO") return 0;
            return 2; // GOO
        }
    
    }
};
var tournament = {
    enemy: null,
    began : function() {
        $("#GOO, #CHO, #PAR, #PLAY").button();
        
        var self = this;
        $("#panels").on("click", "input[type=button]", function(e) {
            var te = e.target.id;
            if (te != "PLAY") {
                var battleCheck = self.enemy.battle;
                var result = (["勝ち", "あいこ", "負け"])[battleCheck(te)];
                alert("あなたの " + result);
            } else {
                var seed = Math.random() * (new Date()).getTime() % 3;
                var te2 = "";
                for (te2 in jankens) {
                    seed--;
                    if (seed < 0) break;
                }
                self.enemy = jankens[te2];
                $("#img").html("<img src='" + self.enemy.imageW + "' />");
            }
        });
    }
};

$(function() {
    tournament.began();
});
</script>
<style>
table {
    border-collapse: collapse;
    border: solid 1px gray;
    width: 60%;
    
}
table tr td {
    border-collapse: collapse;
    border: solid 1px gray;
    padding: 1em;
}
div#img {
    width: 100%;
    min-height: 200px;
}
</style>
</head>
<body>
<p>じゃんけんイメージ提供元:http://lmsnn.fc2web.com/material/janken.html</p>
<script>
// images preloader
for (var te in jankens) {
    document.write("<img src='" + jankens[te].imageW + "' style='display:none'/>");
    document.write("<img src='" + jankens[te].imageH + "' style='display:none'/>");
}
</script>

<table>
    <colgroup>
        <col width="10%" />
        <col width="80%" />
        <col width="10%" />
    </colgroup>
    <tr>
        <td></td>
        <td id="message"><div id="msg"></div></td>
        <td></td>
    </tr>
    <tr>
        <td id="side"></td>
        <td id="images"><div id="img"></div></td>
        <td id="side"></td>
    </tr>
    <tr>
        <td colspan="3" id="panels">
            <input type="button" value="ぐー" id="GOO" />
            <input type="button" value="ちょき" id="CHO" />
            <input type="button" value="ぱー" id="PAR" />
            <input type="button" value="敵表示" id="PLAY" />
            
        </td>
    </tr>
</table>

</body>
</html>
jQuery on の使い方です。ちょっと難解な書き方ですけど、ぜひマスターしてみてください。
コピペして、utf-8 jankenDemo.html で保存して、ブラウザに表示します。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/11/18 01:46

    鉄拳、目潰し、掌底 です。じゃんけんじゃないですね;;

    キャンセル

  • 2015/11/18 09:22

    非常に勉強になるコードをありがとうございます!

    本当にここまでして下さったことに、心より感謝申し上げます。
    必ずやマスターしてみせます!ありがとうございました!

    キャンセル

0

根本的な解決になるか分かりませんが、game_proc()を以下のように修正してみてください。
            function game_proc(){
                on_command();
                var num = show_up();
                
                if(num === 0){
                    rock.on('click',function(){
                        counter();
                    });
                    scissors.on('click',function(){
                        lose();
                    });
                    paper.on('click',function(){
                        beat();
                    });
                }else if(num === 1){
                    rock.on('click',function(){
                        beat();
                    });
                    scissors.on('click',function(){
                        counter();
                    });
                    paper.on('click',function(){
                        lose();
                    });
                }else if(num === 2){
                    rock.on('click',function(){
                        lose();
                    });
                    scissors.on('click',function(){
                        beat();
                    });
                    paper.on('click',function(){
                        counter();
                    });
                }
            };

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/11/17 15:24

    早速の返答ありがとうございます!

    やってみたのですが、やはり続けていくと動きがぎこちなくなったり(画像が出るのが遅れ出し、やがて出なくなる)、相手に勝つような手を出してもあいこのエフェクトが出たりします........。

    キャンセル

0

math.random() * 3 
ランダム値が偏りやすいので、
math.random() * (new Date()).getTime() % 3
とすればほんのちょっぴり均等に出てくると思います。体感的な問題なので、、、
 jquery on の使い方が間違っています。


on は、一度せっていすればよく、ぐー、ちょん、ぱーの判定毎に設定してはいけません。on は、内部で 
addeventlistener というメソッドを呼び出すことで、イベントを追加します。上書きではなくて追加なので、現状のロジックだと、開始ボタン、味方の攻撃ボタンを押下するたびにイベントが追加されてしまいます。

画面起動当初はそうでもないけど、何か操作してるうちにだんだんおもくなる、感じがするんじゃないかと。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/11/17 16:00

    ご返答ありがとうございます!

    なんと!ランダムの偏りをなくすのにそんな方法もあったとは........
    誠に参考になります。

    onを複数回使ってはいけないということは、初めの方でキャッシュにして、まとめたほうが良いということなのでしょうか?

    また、今回onを使おうと思ったのはoff機能が使いたかったからなので、もし何かの命令で無効化できて、なおかつイベントを追加しない方法があれば是非とも教えて欲しいです!

    キャンセル

  • 2015/11/17 16:21


    自分が言ってるのは、イベントの設定、解除という意味で、on はイベントの設定、じゃぁ逆は? off じゃないんです。jquery の on イベント追加用メソッドは、今は知らなくてもいいのですけど、イベント伝播という仕組みを利用して、ある纏まった部分に一度の設定で恒久的に、かつ内容が変わっても再設定する事なしに設定したイベントを捕まえましょう、という観点で実装されています。なので、何度も設定する必要がないのです。
    イベントハンドラは、独自に呼び出すことができますが、イベントの設定後は、そのイベントが発生するまでは設定したハンドラを動作させることができません。動作させるキッカケは、君が、ぐーちょきぱーの画像をクリックしたとき、です。ぐーを非表示にするだけでぐー画像は画面から消えるので押せませんよね?つまり、これが設定したイベントを無効にすつことと等価なんです。

    キャンセル

  • 2015/11/17 20:52

    返答が遅れて申し訳ありません!

    見事に理解が追いつかないのですが、「必ずしもonを使わなくても関数を無効化できるようなアルゴリズムは作れる」という解釈でよろしいでしょうか?

    キャンセル

0

show_upはランダムな値を返しているため、
その値を判定に使用している箇所で、
おかしくなったり、正しくなったりしているようですね。

既にその解決方法は出ていますので、
私は冗長なコードの短縮方法について書かせてもらいます。

.onの第二引数は、関数を指定します。
これは、既に定義している関数の関数名だけでよいです。

こんな感じ
rock.on('click',beat);

これを利用し、game_proc関数を以下のように変更することで、
コードを短縮できます。

            //相手との戦闘の判定をする関数
            function game_proc(){
                on_command();
                var num = show_up();
                rock.on('click',allocation(num + 2));
                scissors.on('click',allocation(num + 1));
                paper.on('click',allocation(num + 0));
            };
            
            //勝敗の決定
            function allocation(num){
                num = num % 3;
                if(num == 2){
                    return counter;
                }else if(num == 1){
                    return lose;
                }else{
                    return beat;
                }
            }

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/11/17 16:37

    とても短くなった........!!

    ご返答ありがとうございます!
    判定の仕方も工夫次第でこんなにも短縮できるのですね!

    ただ実装してみて、問題なく動いてくれているものの、やはり途中からぎこちなくなってしまいます........。

    一度皆様からの意見を整理してやり直してみます!

    キャンセル

  • 2015/11/18 09:20 編集

    ゲーム終了時にscreen.clickを毎回設定し、解除していないのが気になります。
    screen.clickを設定している箇所を関数の外(screenの宣言直後くらい)に出し、counter,lose,beat関数から消し、game_proc関数でscreen.off('click')を実行してみてください。

    キャンセル

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

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

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