复制步骤:
访问http://playclassicsnake.com/play
见3个绿色方块和1个红色圆圈
调整屏幕的大小,使其足够小,以使蛇居住的网格更小
红色圆圈将被适当地调整大小和替换,1个绿色正方形也将被适当地替换,看起来
console.log(SG.snake.links.length);查看蛇上确实有3个链接。如果用SG.snake.links[k].pos.xSG.snake.links[k].pos.y分别查看这三个坐标中的每个坐标,您将看到它们位于同一坐标上。
问题根源:
源代码必须是处理板和板上元素大小调整的函数的实现它是

this.rescale = function ( newWidth )
{
    // newWidth: new width of the div containing

    this.board.setSize(newWidth, newWidth); // set the size of the board to be that of the containing div
    var blockWidth = this.board.getSize().width / this.numBlocks; // width in pixels of a block on the board

    this.food.elem.remove(); // remove old food element
    this.food.elem = this.board.circle(this.food.pos.x * blockWidth + blockWidth / 2, this.food.pos.y * blockWidth + blockWidth / 2, blockWidth / 2).attr('fill', '#cf6a4c');  // create food element to replace old one, in same grid location (see http://raphaeljs.com/reference.html#Paper.circle)

    for (var i in this.snake.links)
    {
        var thisLink = this.snake.links[i];
        thisLink.elem.remove(); // remove old link element
        thisLink.elem = this.board.rect(thisLink.pos.x * blockWidth, thisLink.pos.y * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'); // creata new link to replace old one http://raphaeljs.com/reference.html#Paper.circle
    }
}

代码转储:
如果你想看到代表游戏的对象的完整逻辑,它如下所示。
// define game object
function Game ( board, numBlocks ) {
    //     board: Raphael object that the snake will live on
    // numBlocks: Number of blocks both horizontally AND vertically -- the grid structure should be squares

    this.board = board;
    this.numBlocks = numBlocks;
    this.snake; // Snake object on the board
    this.coords = []; // map whose key-value pairs represent whether a coordinate is open or taken
    this.food = null; // food element on board

    this.getCoords = function ( )
    {
        // returns a nested list gridList of all grid coordinates on the canvas,
        // acting like a map so that gridList[i,j]=true if the coordinate i,j is
        // occupied, and gridList[i,j]=false if the coordinate is not occupied
        var gridList = [];
        for (var i = 0; i < this.numBlocks; ++i)
        {
            var innerList = [];
            for (var j = 0; j < this.numBlocks; ++j) innerList.push(true);
            gridList.push(innerList);
        }
        return gridList;
    }

    this.elementOnGrid = function (elem, xpos, ypos) {
        //       elem: Rapael element (see: http://raphaeljs.com/reference.html#Element)
        // xpos, ypos: x and y grid coordinates of the current position of the element
        return { elem: elem, pos: { x: xpos, y: ypos } };
    }


    this.rescale = function ( newWidth )
    {
        // newWidth: new width of the div containing

        this.board.setSize(newWidth, newWidth); // set the size of the board to be that of the containing div
        var blockWidth = this.board.getSize().width / this.numBlocks; // width in pixels of a block on the board

        this.food.elem.remove(); // remove old food element
        this.food.elem = this.board.circle(this.food.pos.x * blockWidth + blockWidth / 2, this.food.pos.y * blockWidth + blockWidth / 2, blockWidth / 2).attr('fill', '#cf6a4c');  // create food element to replace old one, in same grid location (see http://raphaeljs.com/reference.html#Paper.circle)

        for (var i in this.snake.links)
        {
            var thisLink = this.snake.links[i];
            thisLink.elem.remove(); // remove old link element
            thisLink.elem = this.board.rect(thisLink.pos.x * blockWidth, thisLink.pos.y * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'); // creata new link to replace old one http://raphaeljs.com/reference.html#Paper.circle
        }
    }

    this.Snake = function ( game )
    {
        // game: the Game function/object containing this function

        this.links; // list of

        this.createNew = function ( )
        {

            this.links = [];
            var blockWidth = game.board.getSize().width / game.numBlocks; // width in pixels of a block on the board
            var centerCoordXY = Math.round(game.numBlocks / 2); // x-y grid coordinate of center
            for (var i = 0; i < 3; ++i) // start with 3 blocks in the center-ish
            {
                var newX = centerCoordXY + i;
                this.links.push(new game.elementOnGrid(
                                    game.board.rect(newX * blockWidth, centerCoordXY * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'), // http://raphaeljs.com/reference.html#Paper.circle
                                    centerCoordXY,
                                    centerCoordXY
                                ) // add element of type elementOnGrid to the links
                );
                game.coords[newX][centerCoordXY] = false; // indicate that coordinates of element just added to snake is no longer open
            }

        }
    }

    this.placeFood = function ( )
    {
        do {
            var randXCoord = randInt(0, this.coords.length), randYCoord = randInt(0, this.coords.length);
        }
        while (this.coords[randXCoord][randYCoord] === false); // get random unused x-y coordinate

        var blockWidth = this.board.getSize().width / this.numBlocks; // width in pixels of a block on the board
        if (this.food == null) // if food element hasn't been initialized
        {
            // initialize the food element
            this.food = new this.elementOnGrid(
                    this.board.circle(randXCoord * blockWidth + blockWidth / 2, randYCoord * blockWidth + blockWidth / 2, blockWidth / 2).attr('fill', '#cf6a4c'),  // place circle in random location on the board (see http://raphaeljs.com/reference.html#Paper.circle)
                    randXCoord,
                    randYCoord
            ); // set food to be new element of type elementOnGrid

        }
        else // food element has been initialized (game is in play)
        {
            // move the food element

            // ...
        }

        this.coords[randXCoord][randYCoord] = false; // indicate that coordinates of the good element is not open

    }


    this.startNew = function ( ) {
        this.coords = this.getCoords();
        this.snake = new this.Snake(this);
        this.snake.createNew();
        this.placeFood();
    }
}

$(function () { // equivalent to $(document).ready(function() {

    // div that holds the game area
    var snakeBoardHolder = $('#snake-board-holder');
    // make it have the same height as width
    snakeBoardHolder.height(snakeBoardHolder.width());

    // draw canvas for the snake to live on
    // http://raphaeljs.com/reference.html#Raphael
    if (!Raphael.svg) throw new Error("Your browser does not support SVG elements! Game won't work.");
    snakeBoard = Raphael("snake-board-holder", snakeBoardHolder.width(), snakeBoardHolder.height());

    // start new snake game
    SG = new Game(snakeBoard, 16);
    SG.startNew();

    // make the game area (div) have height always equal to width,
    // and make the Raphel object (canvas) inside it and all its elements
    // to be resized proportionally
    $(window).resize(function () {
        var w = snakeBoardHolder.width();
        snakeBoardHolder.height(w);
        SG.rescale(w);
    });

});

如果您能帮助您确定导致错误的逻辑,我们将不胜感激!

最佳答案

在这个.Snake中,我认为createNew()应该是:

this.createNew = function ( )
{

    this.links = [];
    var blockWidth = game.board.getSize().width / game.numBlocks; // width in pixels of a block on the board
    var centerCoordXY = Math.round(game.numBlocks / 2); // x-y grid coordinate of center
    for (var i = 0; i < 3; ++i) // start with 3 blocks in the center-ish
    {
        var newX = centerCoordXY + i;
        this.links.push(new game.elementOnGrid(
                            game.board.rect(newX * blockWidth, centerCoordXY * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'), // http://raphaeljs.com/reference.html#Paper.circle
                            newX,
                            centerCoordXY
                        ) // add element of type elementOnGrid to the links
        );
        game.coords[newX][centerCoordXY] = false; // indicate that coordinates of element just added to snake is no longer open
    }

}

在this.links.push中,我用newx替换了centercoordxy的一个实例。
你有很多重复的数据(位置存储在3个不同的地方,有两种不同的格式?)如果你不能使它们保持同步,很可能会导致这样的问题。最好使用画布而不是svg。如果您设置了SVG,我建议使用更多的helper函数例如,而不是
new game.elementOnGrid(
    game.board.rect(newX * blockWidth, centerCoordXY * blockWidth, blockWidth, blockWidth).attr('fill', '#19FF19'), // http://raphaeljs.com/reference.html#Paper.circle
    newX,
    centerCoordXY
)

考虑一个函数,它允许您执行如下操作
newGridElement(newX, centerCoordXy, "#19FF19");

不管怎样,祝你好运!

10-07 17:28