0

我正在尝试制作一个简单集中游戏的 OOP 版本。一切看起来都不错,即游戏的每个实例都会显示游戏板和卡片,但卡片不会翻转。

我正在尝试使用 Firefox Web Developer 进行调试,这是我收到的错误消息:

TypeError: game_1.flip 不是函数。

我一生都无法弄清楚翻转功能出了什么问题。我已经阅读了几个 TypeError 问题和回复,但似乎没有一个适用于我的问题。

代码

<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>"More Concentration"</title>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />  
    <style type="text/css">
        body {background-color:green;}
        p {color: white}
        img {border:1px solid black}    
        #theGame {width: 400px; height: 390px; border: 1px solid white; padding:15px; text-align: center;  margin-left: auto; margin-right: auto;}
        #wrapper {text-align: center;}
    </style>
<script type="text/javascript">
// <![CDATA[
function Card() {
this.value = ""; 
this.suit = ""; 
this.name = ""; 
this.image = ""; //add a spot to store a path to the card image.
}
function Game(gameId) {
this.gameId = gameId;   
var firstCard = 'unused'; // A place to remember the first pick...
var touchedCard = 'unused'; // ... and the last touched card
var waiting = false; // This variable will control WHEN we can flip cards.
this.Deck = new Array(52);

this.shuffle = function() {
    var r;
    var someCard = new Card();

    for (i=51;i >= 0;i--){
        r = Math.round(Math.random() * i);
        someCard = this.Deck[i]; this.Deck[i] = this.Deck[r]; this.Deck[r] = someCard;
    }
};

this.initDeck = function() {    
var Names = new Array("2","3","4","5","6","7","8","9","10","jack","queen","king","ace");
var suitNames = new Array("spades","diamonds","hearts","clubs");
    for (var i=0;i<13;i++){
        for (var j=0;j< 4;j++){     

        this.Deck[i + (j * 13)] = new Card();
        this.Deck[i + (j * 13)].suit = suitNames[j];
        this.Deck[i + (j * 13)].value = i;
        this.Deck[i + (j * 13)].name = Names[i];

        //This line builds the path to the card image based on available info.
        this.Deck[i + (j * 13)].image = 'images/' + suitNames[j] + '_' +  Names[i] + '.png';

        }
    }

};

this.flip = function(passedCard){
//This function is the core of the interactivity

    if (waiting == false){ 
    //check to see if we're "waiting" for any flips to finish

         touchedCard = passedCard;

         document.images[touchedCard].src = this.Deck[touchedCard].image;

        if (firstCard  == 'unused'){ 
                   //If this is the first cards selected...

            firstCard = touchedCard; // ... remember it for later

        }else{ //If this is the second card selected ...

            waiting = true; //... disallow further flips and ...

            if (this.Deck[touchedCard].value ==  this.Deck[firstCard].value){ // ... compare it to the first.

                //If they match, do this.//


            setTimeout(this.gameId + ".retireSelection("+ this.firstCard + '_' + this.gameId + ","+touchedCard+")",2000);

            } else { 


                setTimeout(this.gameId + ".resetSelection("+   this.firstCard + '_' + this.gameId + ","+touchedCard+")",2000);
                }

                 firstCard  = 'unused';

        }
    }
};


this.resetSelection = function(carda,cardb){
      //Turn the cards facedown after NOT matching
    document.images[carda].src = 'images/card_back.png'; 
    document.images[cardb].src = 'images/card_back.png';
    waiting = false; // re-allow more flips
};

this.retireSelection = function(carda, cardb){
    //Indicate the cards are matched using the "X' card.
    document.images[carda].src = 'images/blank.png';
    document.images[cardb].src = 'images/blank.png';
    //Deactivate the handler so they can't be flipped again after a match.
    document.images[carda].onclick = '';
    document.images[cardb].onclick = '';
    waiting = false; // re-allow more flips

 };

 this.plop_cards = function(){
     //Writes HTML to put cards on the page     
     this.shuffle();
    //document.writeln("<p>" +this.gameId + "</p>");
    document.write('<div id="theGame">');
     for(var i=0;i<52;i++){     
    document.writeln("<img src = 'images/card_back.png' id =" + this.gameId +  ' Card_' + i + " onclick='" + this.gameId + ".flip("+i+")'>");

    }
    document.write('</div>');
 }; 
 }  
     // ]]>
</script>
  </head>
  <body>      
  <div id="pageTitle">
<h1>&quot;More Concentration&quot; <br /> By Dawn Lassen</h1>
  </div>
  <div id="wrapper" class="center">

  <script type="text/javascript">
  // <![CDATA[


    var game_1 = new Game('game_1');
    var game_2 = new Game('game_2');
    var game_3 = new Game('game_3');
    var game_4 = new Game('game_4');
    var game_5 = new Game('game_5');

    game_1.initDeck();
    game_2.initDeck();
    game_3.initDeck();
    game_4.initDeck();
    game_5.initDeck();

    game_1.plop_cards();
    game_2.plop_cards();
    game_3.plop_cards();
    game_4.plop_cards();
    game_5.plop_cards();

    // ]]>
</script>
   </div>
   </body>
   </html>

任何帮助,指导,建议表示赞赏。你可能会说,我是这个论坛的新手,也是 JavaScript 的新手。

4

1 回答 1

1

问题是您在编写图像时创建了无效的 (X)HTML。请参阅您的代码的这一行:

document.writeln("<img src = 'images/card_back.png' id =" + this.gameId + ' Card_' + i + " onclick='" + this.gameId + ".flip("+i+")'>");

id属性没有引号,因此输出将是乱码,因为它将包含类似<img ... id=game_1 Card_1 onclick=...>. 一方面这是完全错误的,因为一个游戏的所有卡片都将具有相同的 id(这在 HTML 中也是无效的,也不是您想要的),特别是在 XHTML 的情况下,禁止使用未引用的属性。

简单的解决方法是正确引用它

document.writeln("<img src = 'images/card_back.png' id ='" + this.gameId + ' Card_' + i + "' onclick='" + this.gameId + ".flip("+i+")'>");

但是,尝试直接写入 DOM 流是一个坏主意。如果您完全避免使用方法会更好,document.write因为通常建议不要使用它们,而是使用 DOM 方法。

例如,您可以执行以下操作:

var img = document.createElement('img');
img.src = 'images/card_back.png';
img.id = this.gameId + ' Card_' + i;
img.onclick = (function(_this, i) {
    return function() {
        _this.flip(i);
    };
})(this, i);
document.body.appendChild(img);

你可以在这个小提琴中看到它允许flip被调用。小提琴现在破坏了页面的格式,这只是一个快速演示。顺便说一句,我还建议不要使用id带空格的属性。

出于好奇:您使用 XHTML 有什么特别的原因吗?您也可以使用 HTML(即 HTML5),然后摆脱脚本周围的 CDATA 块注释。虽然 XHTML 更加严格,这通常并不算太糟糕,但 HTML5 的传播范围要广得多,因此没有理由不使用它。

于 2013-10-13T09:51:34.227 回答