WedX - журнал о программировании и компьютерных науках

Змеиное движение в змеиной игре

Пожалуйста, я следил за учебником о том, как сделать игру со змеей, и я понял все о коде вплоть до того, куда змея должна двигаться. Я просто не понимаю логики движения змеи. Фрагмент кода показан ниже:

. . . //the code block to setup the canvas and other basic stuff for the game
//creating the snake
var snake_array;  //an array of cells to make up the snake
function create_snake(){
    var length = 5;   //length of the snake
    snake_array = [] //starting with an empty array
    for (var i = 0; i < length; i++) {
        //this will create a horizontal snake starting from top left
        snake_array.push({x:i,y:0});
    }
}

create_snake() // invoking the method

//painting the snake
function paint(){

    . . . // code block to clear the trail of the snake on the canvas before the snake moves

    var nx = snake_array[0].x;
    var ny = snake_array[0].y;
    if(d == "right") nx++;    //d is a variable updated by the keydown event listener code(not shown here) 
    else if(d == "left") nx--;
    if(d == "up") ny--;
    if(d == "down") ny++;

    var tail = snake_array.pop(); // pops out the last cell
    tail.x = nx;
    tail.y = ny;
    snake_array.unshift(tail)

    . . . // code block to paint the snake cells

    }
}

paint() // invoking the method

Моя проблема такова: как часть кода, которую я описал выше, выполняет работу по продвижению змеи, потому что, когда я пытался следовать коду с помощью консоли браузера, после вызова create_snake() у меня есть массив из пяти объектов (которые представляют ячейки змеи ), которые имеют следующие свойства и значения: {x:0,y:0},{x:1,y:0},{x:2,y:0},{x:3,y:0},{x:4,y:0}. После вызова метода рисования у меня все еще есть массив из пяти объектов, но со следующими свойствами и значениями: {x:1,y:0},{x:0,y:0},{x:1,y:0},{x:2,y:0},{x:3,y:0}. Теперь, как змея движется вперед, когда d = "right"так как свойство/координата x последней ячейки змеи после вызова paint() на 1 меньше, чем ее исходное значение до вызова метода, и снова две ячейки теперь перекрываются, так как два объекта в змея_массив теперь имеет ту же координату ({x:1,y:0})


Ответы:


1

Соответствующий код инициируется следующим образом:

var snake_array;
function create_snake(){
    var length = 5;
    snake_array = [];
    for(var i = length-1; i>=0; i--){
        snake_array.push({x: i, y:0});
    }
}

Важно отметить, что этот код генерирует змейку в обратном порядке, поэтому она выглядит так: {x:4,y:0}, {x:3,y:0}, {x:2:,y:0}, {x:1,y:0}, {x:0,y:0}. Это потому, что i начинается с length-1, а length устанавливается на 5 выше цикла for. Это выглядит так:

[T][x][x][x][H][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]

Затем в функции рисования он захватывает положение хвоста, так как он намеревается переместить хвост в положение, в котором должна быть голова (делая это таким образом, ему не нужно перемещать какие-либо другие ячейки до следующего рисования). , так как они никогда не изменятся, поскольку змея никогда не перемещается более чем на одну клетку за цикл.)

    var nx = snake_array[0].x;
    var ny = snake_array[0].y;
    if(d == "right") nx++;
    else if(d == "left") nx--;
    else if(d == "up") ny--;
    else if(d == "down") ny++;

В этой схеме хвост змеи всегда является последним элементом массива, а голова всегда первым. Таким образом, змея_массив[snake_array.length] ВСЕГДА является хвостом, а змея_массив[0] ВСЕГДА является головой.

Помня {x:4,y:0}, {x:3,y:0}, {x:2:,y:0}, {x:1,y:0}, {x:0,y:0} и предполагая, что наше движение по умолчанию правильное, мы можем вычислить {nx:5,ny:0}. nx и ny теперь представляют собой ячейку, которая не является частью змеи, но ячейка, в которую змея хочет переместиться. Таким образом, код выполняет некоторые ограничения и проверку столкновений для этой ячейки, чтобы увидеть, пересекается ли она с какой-либо стеной или другими сегментами змеи, и если это происходит, он перезапускает игру.

Он также проверяет столкновение с едой и обрабатывает его (вместо того, чтобы двигать хвостом, он просто создает новую голову в позиции ячейки и генерирует еще один кусок еды).

Но, предполагая, что эта позиция ячейки (nx,ny) ни с чем не сталкивается, он запускает этот код:

    var tail = snake_array.pop();
    tail.x = nx; tail.y = ny;

Который удаляет хвост из массива змей, устанавливает его позицию в позицию ячейки, которую мы вычислили ранее (nx,ny), а затем сдвигает этот «хвост» в первую позицию массива (которая всегда является головой, по нашему соглашению из ранее):

    snake_array.unshift(tail);

Таким образом, это заканчивается так:

[ ][x][x][x][H][T]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]

Но на самом деле массив по-прежнему имеет форму [H][x][x][x][T], потому что мы решили, что все, что находится в позиции первого элемента змеиного_массива[0], является головой, а все, что находится в последнем элементе позиция змеи_массива[snare_array.length] была хвостом. Так что это действительно:

[ ][T][x][x][x][H]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ]

И тогда весь процесс может повторяться снова и снова, пока вы не выиграете или не проиграете!

07.11.2015
  • пожалуйста, можете ли вы расширить, если есть перекрытие, то на холсте должно быть 3 ячейки змеи, а не 4, так как две ячейки будут нарисованы в одном и том же положении x, y - координата 07.11.2015
  • На самом деле, я немного неправильно прочитал код, дайте мне одну минуту, чтобы исправить мой ответ. 07.11.2015
  • Спасибо за ваш ответ, он немного прояснил ситуацию, но из вашего ответа новая координата не должна быть {x:5,y:0} but {x:1,y:0}, потому что из кода, который я вставил выше в вопросе, nx = snake_array[0].x который равен 0, и если мы предположим, что змея движется вправо направлении, выполняется nx++ в коде и nx становится 1. Затем мы pop() голову змеи возвращаем в массив, делая ее координаты равными координатам nx и ny. 07.11.2015
  • Да, я отредактировал свой ответ, потому что неправильно его прочитал (я думал, что он работает со значениями последнего элемента в массиве). Я думаю, что это, вероятно, ошибка, которая делается как есть (если это не так, я бы нужно увидеть больше кода, чтобы понять, почему.) 07.11.2015
  • хорошо, большое спасибо за ответы. Это ссылка на учебник, возможно, вы можете проверить его, чтобы получить полное представление, так что это поможет вам лучше объяснить thecodeplayer.com/walkthrough/ Спасибо. 07.11.2015
  • Ах, после просмотра, что происходит, в основном движение управляет головой, но вместо того, чтобы отображать голову перед остальными частями (что может вызвать проблему, о которой я упоминал в ответе о непересекающихся сегментах), она движется хвост туда, где голова будет следующей. Но он также проверяет наличие столкновений между этими двумя ситуациями, поэтому, когда происходит столкновение, он перезапускается. Я мог бы переписать ответ с этой информацией, если вы думаете, что это поможет. 07.11.2015
  • определенно да. Вы можете переписать ответ. Я действительно хочу понять, что происходит в этой части кода. Система сетки, которую вы использовали для объяснения, наглядна и делает ее более понятной. Спасибо. 07.11.2015
  • Вау! Большое спасибо за усилия. Я понимаю это сейчас. Спасибо. 07.11.2015
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]