Moving objects in javascript (the start of the snake game) - javascript

Does anyone have an idea how to make these 3 colored squares move around the perimeter of the board, and not like now, i.e. in lines? (lines 57-78) https://codepen.io/diana-larussa/pen/ExgpXzo
function timer() {
ttl--
divElement = document.querySelectorAll('div')
divElement[nr_boxu].style.backgroundColor = "#6d5dfc"
divElement[nr_boxu].value = 0
nr_boxu = nr_boxu + 1
divElement[nr_boxu].style.backgroundColor = "#F25270"
divElement[nr_boxu+1].style.backgroundColor = "#F25270"
divElement[nr_boxu+2].style.backgroundColor = "#F25270"
spanTimer.innerHTML = "TIME: " + ttl
//if (nr_boxu>gridDOMElement.value-4) stop()
/*if (divElement[nr_boxu] == gridDOMElement.value - 4) {
divElement[gridDOMElement.value + 1].style.backgroundColor = "#F25270"
}*/
if (ttl == 0) stop()
}

I think for each grid size it is possible to generate perimeter sequence of indices and timer() function could pick 4 of those indices to update.
For example, in this grid 5x4:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
perimeter array would be: [0, 1, 2, 3, 4, 9, 14, 19, 18, 17, 16, 15, 10, 5] (indices highlighted in bold)
timer function will pick 4 indices out of the array, for example [0, 1, 2, 3] at the start and will colour element at index 0 with #6d5dfc and 1, 2, 3 with #F25270.
It will later follow around the perimeter, for example picking 4 elements: [2, 3, 4, 9] and colouring element 2 with #6d5dfc and 3, 4, 9 with #F25270 (need to be careful when reaching end of array).
nr_boxu seems to be incremented starting from 0 on every timer() call.
It can be used to pick 4 elements from perimeter array starting from 0 till the end of array.
The following formula - nr_boxu % perimeter.length uses remainder operator to keep iterating from 0 till perimeter.length - 1.
perimeter and timer can be built like this:
function getPerimeter(cols, rows) {
let res = [];
// top line: 0, 1, 2, 3, 4
for (let i = 0; i < cols; i++) {
res.push(i);
}
// right line: 9, 14
for (let i = 1; i < rows - 1; i++) {
res.push(cols * (i + 1) - 1);
}
// bottom line: 19, 18, 17, 16, 15
for (let i = 0; i < cols; i++) {
res.push(cols * rows - 1 - i);
}
// left line: 10, 15
for (let i = rows - 2; i > 0; i--) {
res.push(i * cols);
}
return res;
}
let perimeter = getPerimeter(numOfColumns, numOfRows);
function timer() {
ttl--
const ind1 = perimeter[nr_boxu % perimeter.length];
const ind2 = perimeter[(nr_boxu + 1) % perimeter.length];
const ind3 = perimeter[(nr_boxu + 2) % perimeter.length];
const ind4 = perimeter[(nr_boxu + 3) % perimeter.length];
divElement = document.querySelectorAll('div')
divElement[ind1].style.backgroundColor = "#6d5dfc"
divElement[ind1].value = 0
nr_boxu = nr_boxu + 1
divElement[ind2].style.backgroundColor = "#F25270"
divElement[ind3].style.backgroundColor = "#F25270"
divElement[ind4].style.backgroundColor = "#F25270"
spanTimer.innerHTML = "TIME: " + ttl
//if (nr_boxu>gridDOMElement.value-4) stop()
/*if (divElement[nr_boxu] == gridDOMElement.value - 4) {
divElement[gridDOMElement.value + 1].style.backgroundColor = "#F25270"
}*/
if (ttl == 0) stop()
}

Related

Compute the distance between elements in a bi-dimensional array in Javascript

Having the following input string: 923857614
This is represented into a matrix like this:
9 2 3
8 5 7
6 1 4
Having a moving sequence like this: 423692, this means that we start in point 4, we move to 2, then to 3, then to 6, then to 9 and finally to 2.
It must be computed the length of the road. At beginning it starts from 0, if the next step is adjacent to the current one, add 1, if it isn't adjacent, add 2.
How I tried to do it:
function computeRoadLength(keypad, movingSequence) {
// build the matrix
const arr = [[keypad[0], keypad[1], keypad[2]],
[keypad[3], keypad[4], keypad[5]],
[keypad[6], keypad[7], keypad[8]]];
let roadLength = 0;
for (i = 0; i < movingSequence.length; i++) {
// some way to compute the distance here
if (arr[i] > arr[i+1]) roadLength = roadLength + 1;
if (arr[i] < arr[i+1]) roadLength = roadLength + 2;
}
return roadLength;
}
computeRoadLength(923857614, 423692); // 2 + 1 + 2 + 2 + 1 = 8, should return 8
You could take a different approach by using an object of positions of all keypad values and take the absolute delta of the positions.
For adding to movingSequence add one or max two.
function computeRoadLength(keypad, movingSequence) {
const positions = {};
for (let i = 0; i < keypad.length; i++) {
positions[keypad[i]] = [Math.floor(i / 3), i % 3];
}
let roadLength = 0,
last = positions[movingSequence[0]];
for (let i = 1; i < movingSequence.length; i++) {
const
item = positions[movingSequence[i]],
sum = Math.abs(last[0] - item[0]) + Math.abs(last[1] - item[1]);
roadLength += Math.min(sum, 2);
last = item;
}
return roadLength;
}
console.log(computeRoadLength('923857614', '423692')); // 2 + 1 + 2 + 2 + 1 = 8

JavaScript; Counting from 10 to 0 and then again. How to get rid of "undefined" instead of "zero"?

I'm trying to make a countdown click event. I've managed to do it for counting up to 10.
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let btnForward = document.querySelector(".forward");
let btnBackward = document.querySelector(".backward");
let z = 0;
btnForward.addEventListener("click", function () {
let numbersPara = document.getElementById("numbersPara");
z++;
if (z >= numbers.length) z = 0;
numbersPara.innerText = numbers[z];
});
// #### Button backwardwork correctly only partially ######
btnBackward.addEventListener("click", function () {
let numbersPara = document.getElementById("numbersPara");
z--;
if (z < 0) z = 10;
numbersPara.innerText = numbers[z];
});
<div><button class="backward">Backward</button></div>
<div><button class="forward">Forward</button></div>
<div><code id="numbersPara">1</code></div>
I want to count up to 10 when I click the button and when it reaches 10 it should switch to 1 again. It works fine.
However, when I started counting down from 10 to 0, it displays "undefined" instead of switching to 10. How to fix it? Anyone knows?
It looks like you've made a classic error that happens to everyone at some point. In your example, index 0 contains a value of 1.
To fix this, you just need to change this line (in the buttonBackward click event listener):
if (z < 0) z = 10;
to the following.
if (z < 0) z = 9;
However, this could be improved further by changing z = 9 to z = numbers.length - 1 (better practice in case you want to add or remove elements later):
if (z < 0) z = numbers.length - 1; // the last index will be numbers.length - 1
The full code solution (with some html elements provided to show it working):
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const btnForward = document.querySelector(".forward");
const btnBackward = document.querySelector(".backward");
// set a reference to numbersPara to reduce calls to the DOM
const numbersPara = document.getElementById("numbersPara");
let z = 0;
btnForward.addEventListener("click", () => {
z++;
if (z >= numbers.length) z = 0;
numbersPara.innerText = numbers[z];
});
btnBackward.addEventListener("click", () => {
z--;
if (z < 0) z = numbers.length - 1;
numbersPara.innerText = numbers[z];
});
<div><button class="backward">Backward</button></div>
<div><button class="forward">Forward</button></div>
<div><code id="numbersPara">1</code></div>

Getting a array.push to do nothing

Trying to figure out a way that if the results of my loop equals undefined, to have my array.push do nothing. this is my code.
barcodes.sort();
var first = barcodes.slice(0, (barcodes.length + 1) / 2);
var second = barcodes.slice(((barcodes.length + 1) / 2), barcodes.length);
var result = [];
for (var i = 0; i < barcodes.length; i++) {
if (i % 2 === 0) {
result.push(first[i / 2]);
result.push(second[parseInt(i)/2]);
}else {
}
}
getting results when its odd as such: (when even is fine)
array results (12) ["1001", "9003", "3001", "9005", "3002", "9006", "3003", "9007", "9001", "9008", "9002", undefined]
result.push(second[parseInt(i)/2]);
This is undefined if you have an odd number because second.length is one less than half of barcodes. So if barcodes.length == 11, that second push is pushing second[5] when second.length == 5. This doesn't exist since indices start at 0
barcodes = ["1001", "9003", "3001", "9005", "3002", "9006", "3003", "9007", "9001", "9008", "9002"];
barcodes.sort();
var first = barcodes.slice(0, (barcodes.length + 1) / 2);
var second = barcodes.slice(((barcodes.length + 1) / 2), barcodes.length);
var result = [];
for (var i = 0; i < barcodes.length; i++) {
if (i % 2 === 0) {
result.push(first[i / 2]);
if(second[(i / 2)]) {
result.push(second[(i / 2)]);
}
}
}
console.log(result);
You could add this line: if(second[(i / 2)]) to avoid the undefined but again I'm not 100% sure what your end goal is so I'm not sure if this fully answers the question
You could take the barcode array and take an ofset for the second value for pushing.
The adjustment for the length keeps same element groups and add only at the end an undefined.
Examples:
given
barcode 0 1 2 3 4 5 6 7 8
first 0 1 2 3 4
second 5 6 7 8
result
0 5 1 6 2 7 3 8 4 undefined
given
barcode 0 1 2 3 4 5 6 7 8 9
first 0 1 2 3 4
second 5 6 7 8 9
result
0 5 1 6 2 7 3 8 4 9
var barcodes = [0, 1, 2, 3, 4, 5, 6, 7, 8],
result = [],
i,
l = (barcodes.length + 1) >> 1;
for (var i = 0; i < l; i++) {
result.push(barcodes[i], barcodes[i + l]);
}
console.log(result);

How to reverse an algorithm using modulo and bitwise XOR operators on a JavaScript array?

var alphaNumbersStr = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
var hexaString = '0123456789abcdef';
var str32 = '4af27d7ef70b1263da25022af735508b';
var str = 'FoooooBar';
var arr = [];
for (var i = 0; i < str.length; i++) {
arr[i] = alphaNumbersStr.indexOf(str.charAt(i));
}
// --
// Start : arr ==> [ 31, 14, 14, 14, 14, 14, 27, 0, 17 ]
// --
for (var i = 0; i < 10000; i++) {
arr[i % str.length] += hexaString.indexOf(str32.charAt(i % 32)) ^ arr[(i + 1) % str.length] ^ arr[(i + 2) % str.length];
if (arr[i % str.length] > alphaNumbersStr.length - 1) {
arr[i % str.length] %= alphaNumbersStr.length;
}
}
// --
// End : after 10000 iterations : arr ==> [ 38, 8, 32, 4, 18, 24, 2, 48, 22 ]
// --
Given the following snippet, I'm trying to reverse this algorithm so that I could return to the original array state (step 0).
Any idea on how this could be solved?
Just do all steps backwards. The operations performed are in such a way that the modulo operation is possible to revert.
function revert(arr) {
for (let i = 9999; i >= 0; i--) {
//we know this as these values didnt get affected this iteration
let added = hexaString.indexOf(str32.charAt(i % 32)) ^ arr[(i + 1) % str.length] ^ arr[(i + 2) % str.length];
//the important difference in modulo
let modadd = added % alphaNumbersStr.length;
//single overflow is what we need to predict
//if we went over, we went smaller again
let overflow = modadd > arr[i % str.length];
//we need to undo the modulo
if (overflow) {
let diff = modadd - arr[i % str.length];
arr[i % str.length] = alphaNumbersStr.length - diff;
}
//Not much to do otherwise
else arr[i % str.length] -= modadd;
}
return arr;
}
//Just so it can be run
function change(){var result,value=document.getElementById("a").value;try{result=algorithm(eval(value))}catch(a){result=["error"]}document.getElementById("t").innerHTML="["+result.join(", ")+"]",document.getElementById("i").innerHTML="["+(result[0]==='error' ? result : revert(result)).join(", ")+"]"}function algorithm(a){for(var b=0;b<1e4;b++)a[b%str.length]+=hexaString.indexOf(str32.charAt(b%32))^a[(b+1)%str.length]^a[(b+2)%str.length],a[b%str.length]>alphaNumbersStr.length-1&&(a[b%str.length]%=alphaNumbersStr.length);return a}var alphaNumbersStr="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",hexaString="0123456789abcdef",str32="4af27d7ef70b1263da25022af735508b",str="FoooooBar";change();
Value of <code>arr</code>: <input onblur="change()" id="a" size="50" value="[31, 14, 14, 14, 14, 14, 27, 0, 17]">
<hr>
Through algorithm: <code id="t"></code><br>
Through revert: <code id="i"></code>

How to do this "weird" loop through my array?

I need to loop through a simple array in a "weird" way.
The length of my array is always a odd squared number.
Let's say the length is 49. To make it clearer, my elements are the index of the array. So I have something like:
myArray = [0, 1, 2, 3, 4 ... 47, 48]
So, you can imagine the following square matrix:
0 7 14 21 28 35 42
1 8 15 22 29 36 43
2 9 16 23 30 37 44
3 10 17 24 31 38 45
4 11 18 25 32 39 46
5 12 19 26 33 40 47
6 13 20 27 34 41 48
I have to start with the center of this matrix (i.e. myArray[Math.floor(myArray.length / 2)])
In my example: 24
Then I have to alternate between left and right numbers until I pass through all the row.
In my example, for the first iteration : 17, 31, 10, 38, 3, 45
Once a row is done, I alternate between up then bottom numbers an reiterate the left/right logic for the given row.
In my example, for myArray as input I should loop in the following order:
24, 17, 31, 10, 38, 3, 45,
23, 16, 30, 9, 37, 2, 44,
25, 18, 32, 11, 39, 4, 46,
22, 15, 29, 8, 36, 1, 43,
26, 19, 33, 12, 40, 5, 47,
21, 14, 28, 7, 35, 42, 0,
27, 20, 34, 13, 41, 6, 48
Could you help me the achieved it properly?
Here is what I did so far: https://jsfiddle.net/6qzkk2zx/
I recommend nesting two ES6 generators:
for (let y of outwards(7)) {
for (let x of outwards(7)) {
var i = y*7+x;
use(arr[i]); // for one-dimensional array
use(arr[x][y]) // for two-dimensional array
}
}
function* outwards(n) {
console.assert(n%2 == 1);
var x = (n-1)/2; // starting in the middle
yield x;
for (var i=1; i<n;) {
x -= i++; // jumping to the left
yield x;
x += i++; // and right
yield x;
}
}
Starting from that, you could either manually translate it back to an equivalent ES5 construct, or just let a transpiler do the work for you: Demo.
I think I have it:
https://jsfiddle.net/2dbj68t3/2/
var start = (array.length - 1) / 2;
var square = Math.sqrt(array.length);
newArray.push(array[start]);
for (j = 1; j <= Math.floor((square / 2)); j++) {
newArray.push((array[start - (j * square)]));
newArray.push((array[start + (j * square)]));
}
for (i = 1; i <= Math.floor((square / 2)); i++) {
newArray.push((array[start - i]));
for (j = 1; j <= Math.floor((square / 2)); j++) {
newArray.push((array[start - i - (j * square)]));
newArray.push((array[start - i + (j * square)]));
}
newArray.push((array[start + i]));
for (j = 1; j <= Math.floor((square / 2)); j++) {
newArray.push((array[start + i - (j * square)]));
newArray.push((array[start + i + (j * square)]));
}
}
Another option:
// Define number of elements
var n = 49;
// Calculate center
var start = Math.floor(n / 2);
// Calculate solution
var result = [get_row(start, n)];
for (var l = 1; l < Math.sqrt(n) / 2; l++) {
result.push(get_row(start - l, n));
result.push(get_row(start + l, n));
}
// Print solution
for (var k = 0; k < result.length; k++) {
console.log(result[k]);
}
///////////////////////////////////////////////
function get_row(c, size) {
var a = [];
a.push(c);
for (var i = 1; i < Math.sqrt(size) / 2; i++) {
a.push(c - i * Math.sqrt(size));
a.push(c + i * Math.sqrt(size));
}
return a;
}
Here's another approach using nested loops, single resulting array.
JSfiddle Demo
var num = 7,
middleElement = Math.floor(num * num / 2); // Square number and get the center number
var result = []; // To store resulting array
for(var j = 1; j <= num; j++) {
// This will be the middle element, i.e. 24, 23, 25, 22, 26, 21, 27
// Will be calculated dynamically
element = j % 2 ? middleElement + Math.floor(j / 2) : middleElement - Math.floor(j / 2);
result.push(element); // Add middle element in the resulting array
for(var i = 1; i < num; i++) {
// For next six elements
// Get the number from current number
element = i % 2 ? element - num * i : element + num * i;
result.push(element);
}
}
var num = 7,
middleElement = Math.floor(num * num / 2); // Square number and get the center number
var result = []; // To store resulting array
for(var j = 1; j <= num; j++) {
// This will be the middle element, i.e. 24, 23, 25, 22, 26, 21, 27
// Will be calculated dynamically
element = j % 2 ? middleElement + Math.floor(j / 2) : middleElement - Math.floor(j / 2);
result.push(element); // Add middle element in the resulting array
for(var i = 1; i < num; i++) {
// For next six elements
// Get the number from current number
element = i % 2 ? element - num * i : element + num * i;
result.push(element);
}
}
console.log(result);
Another approach, with an array for the position of the numbers:
var array = [], // 3 2 4 1 5 0 6
length = 7,
lower = 0, upper = length - 1,
result;
while (lower < upper) { // generate array
array.unshift(upper--);
array.unshift(lower++);
}
lower === upper && array.unshift(upper);
result = Array.apply(null, { length: length }).map(function (_, j) {
return Array.apply(null, { length: length }).map(function (_, i) {
return array[i] * length + array[j];
});
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Numbers that follows the one you are processing (let's say 24) are always some subtraction of your number (24) by some multiple of the length of the matrix (in your example, this length is 7).
Let subject be the number you are processing and hop the length of the matrix.
So, iterate through the rows, two per iteration, always filling two cells at a time, the first with subject - hop * <counter of iteration>, and the second cell with subject + hop * <counter of iteration>
I hope I understand your algorithm, but this ought to work:
If the length is always an odd square, then your index minima are 0 and maxima are Sqrt(n+1)-1.
var verticalup=false;
var horizontalforward=false;
var initial=myArray[Math.floor(myArray.length / 2)];
var maximum=Math.sqrt(myArray.length+1);
var current={vertical:initial,horizontal:initial};
var continue=true;
while (continue) {
//do something here with the current selection
if (current.horizontal===0) {
verticalup=!verticalup;
current.vertical+=(verticalup?1:-1);
}
horizontalforward=!horizontalforward;
current.horizontal+=(horizontalforward?1:-1);
continue=current.vertical>=0 && current.vertical<maxima && current.horizontal>=0 && current.horizontal<maximum;
}
I think something in the lines of...
var center = Math.floor(myArray.length / 2;
var parity = function(p){
return (p%2)*2-1; //if the number is even, returns -1 otherwise 1
}
//adds to cetner location half on index, signed with its parity, so we get an alternating effect each time index grows bigger
//for 0,1,2,3,4,5,6... will return 0,1,-1,2,-2,3,-3...
var step = function(index){
return (Math.floor((index+1)/2))*parity(index);
}
for (var i=0;i<size;i++){
for (var j=0;j<size;j++){
a[center-step(i)][center-step(j)];
}
}
Basically it utilizes the parity of i and j to determine whether to go up or down, and or left or right from the (center, center) point.

Categories

Resources