I can move left, right, up, down - no diagonal movement is allowed.
Can only travel to cells that contain 1s, not 0s.
Start in upper left cell (0,0)
End in lower right cell (2,3)
Last cell is undefined, should be (2,3).
let visited = [[false, false, false, false],
[false, false, false, false],
[false, false, false, false]]
function shortestPath(arr, c, r) {
if (arr.length === c + 1 && arr[0].length === r + 1) {
if (arr[c][r] === 1) {
return true;
}
else { return false }
}
if (c === arr.length || r === arr[0].length || c < 0 || r < 0) { return }
console.log(r, c)
if (arr[c][r] === 0) { return }
if (visited[c][r]) { return }
visited[c][r] = true
shortestPath(arr, c, r + 1)
shortestPath(arr, c + 1, r)
shortestPath(arr, c, r - 1)
shortestPath(arr, c - 1, r)
}
let a = [[1, 1, 1, 0],
[1, 1, 0, 1],
[1, 1, 1, 1]]
console.log(shortestPath(a, 0, 0))
Output:
0 0
1 0
2 0
3 0
2 1
1 0
1 1
2 1
1 2
2 2
1 2
2 1
0 2
1 2
0 1
1 1
0 2
0 0
1 1
0 1
1 0
0 0
0 1
undefined
There you go:
https://jsfiddle.net/vanowm/j0dxqy7h/
function shortestPath(arr, start, end)
{
arr = arr.map(a => [...a]); //clone matrix, so we can re-use it by updating which coordinates we've visited
if (!start)
start = [0, 0];
if (!end)
end = [arr[0].length-1, arr.length-1];
arr[start[1]][start[0]] = 0; //set start position as unavailable
const paths = [[start]];
while (paths.length)
{
const path = paths.shift(), //remove first path out of all paths (we'll add it back to the end if it's not a dead end)
cur = path[path.length-1], //get last coordinates from the path
next = [ //next coordinates from current position
[cur[0], cur[1] + 1],
[cur[0] + 1, cur[1]],
[cur[0], cur[1] - 1],
[cur[0] - 1, cur[1]],
];
for (let i = 0, pos; i < next.length; i++)
{
pos = next[i];
if (pos[0] == end[0] && pos[1] == end[1])
return path.concat([end]); //found end position
if (pos[0] < 0 || pos[0] >= arr[0].length || //check boundaries for x
pos[1] < 0 || pos[1] >= arr.length || //check boundaries for y
!arr[pos[1]][pos[0]]) //position available?
{
continue;
}
arr[pos[1]][pos[0]] = 0; //mark position unavailable
paths.push(path.concat([pos])); //add position to the path
}
}
return [start]; //return start coordinates if no path found
}
showMatrix([
[1, 1, 1, 0],
[1, 1, 0, 1],
[1, 1, 1, 1]
]);
custom([
[1,1,0,1,1,1,1,0],
[1,0,1,1,0,0,1,1],
[1,0,1,0,1,1,0,1],
[1,0,1,1,0,1,1,1],
[1,0,0,1,0,1,0,0],
[1,1,0,1,0,1,1,1],
[1,0,1,1,1,0,0,1],
[1,1,0,0,1,0,1,1],
[0,1,1,1,1,0,1,1]
], [1,0],[6,7]);
function showMatrix(matrix, start, end, _box)
{
if (!start || start[0] >= matrix[0].length || start[1] >= matrix.length)
start = [0, 0];
if (!end || end[0] >= matrix[0].length || end[1] >= matrix.length)
end = [matrix[0].length-1, matrix.length-1];
const path = shortestPath(matrix, start, end);
console.log("matrix:", JSON.stringify(matrix));
console.log("path:", path.join("|"));
path.forEach(b => matrix[b[1]][b[0]] = 2); //merge path into matrix
matrix[start[1]][start[0]] = 3; //identify start
matrix[end[1]][end[0]] = 4; //identify end
let div = document.createElement("div");
const box = _box || div.cloneNode();
box.className = "matrix";
box.innerHTML = "";
box.style.gridTemplateColumns = "1fr ".repeat(matrix[0].length);
const pathPos = {};
path.forEach((a,i) => pathPos[a.join("x")] = i);
matrix.forEach((r, y) => r.forEach((t, x) =>
{
div = div.cloneNode(false);
div.className = "t" + t;
div.setAttribute("p", pathPos[x+"x"+y]!==undefined ? pathPos[x+"x"+y] : "");
div._xy = [x,y];
box.appendChild(div);
}));
if (!_box)
return document.body.appendChild(box);
box._matrix = matrix;
box._start = start;
box._end = end;
box.onmouseup = e =>
{
if (!e.target._xy)
return;
if (e.button)
{
if ((e.button == 2 && !(e.ctrlKey || e.shiftKey)) ||
(e.button != 2 && (e.ctrlKey || e.shiftKey)))
end = e.target._xy;
else
start = e.target._xy;
}
else
matrix[e.target._xy[1]][e.target._xy[0]] = ~~!matrix[e.target._xy[1]][e.target._xy[0]];
matrix = matrix.map(r => r.map(t => t ? 1 : 0));
showMatrix(matrix, start, end, box);
}
box.oncontextmenu = e => e.preventDefault();
}
function custom(matrix, start, end)
{
if (matrix)
{
document.getElementById("columns").value = matrix[0].length;
document.getElementById("rows").value = matrix.length;
}
const cols = ~~document.getElementById("columns").value,
rows = ~~document.getElementById("rows").value,
box = document.getElementById("custom");
if (start)
box._start = start;
if (end)
box._end = end;
matrix = matrix || box._matrix || [[]];
if (cols > matrix[0].length)
matrix.forEach((a,i) => matrix[i] = a.concat(Array(cols-a.length).fill(3)));
else if (cols < matrix[0].length)
matrix.forEach(a => a.splice(cols, a.length - cols));
if (rows > matrix.length)
matrix = matrix.concat([...Array(rows-matrix.length)].map(e => Array(cols).fill(1)));
else if (rows < matrix.length)
matrix.splice(rows, matrix.length - rows);
matrix = matrix.map(r => r.map(t => t ? 1 : 0));
showMatrix(matrix, box._start, box._end, box);
}
function random()
{
let matrix,
cols = ~~document.getElementById("columns").value,
rows = ~~document.getElementById("rows").value,
box = document.getElementById("custom"),
date = new Date();
do
{
matrix = [...Array(rows)].map(e => [...Array(cols)].map( e=> Math.round(Math.random()*1.4))); //generate less dense matrix
path = shortestPath(matrix, box._start, box._end);
}
while(path.length<2 && new Date - date < 10000) //10 sec max
matrix = matrix.map(r=>r.map(a=>Math.round(Math.random()*a*0.9))); //fake more density
path.forEach(a=>matrix[a[1]][a[0]]=1); //clear the path
custom(matrix);
}
.matrix:not(:empty)
{
display: inline-grid;
grid-gap: 1px;
border: 1px solid black;
margin: 0.5em;
width: fit-content;
}
.matrix *
{
width: 2em;
height: 2em;
background-color: grey;
outline: 1px solid black;
}
.matrix .t1
{
background-color: white;
}
.matrix .t2
{
background-color: lightgreen;
}
.matrix *:before
{
content: attr(p);
position: absolute;
width: 2em;
height: 2em;
line-height: 2em;
text-align: center;
font-size: 1em;
}
.matrix .t3
{
background-color: green;
}
.matrix .t4
{
background-color: red;
}
.custom .matrix
{
}
.custom .matrix :hover
{
opacity: 0.8;
box-shadow: 0 0 5px 1px black;
z-index: 1;
}
.custom .matrix :hover:after
{
content: "";
display: block;
width: 100%;
height: 100%;
box-shadow: 0 0 5px 1px black inset;
}
.custom .matrix .t1:hover
{
background-color: #CCC;
}
input
{
width: 3em;
}
.custom
{
display: inline-grid;
vertical-align: top;
padding: 0.5em;
padding-bottom: 3em;
}
.as-console-wrapper
{
max-height: 3em !important;
}
<span class="custom">
<div>
Width: <input id="columns" type="number" min="3" max="100" oninput="custom()">
Height: <input id="rows" type="number" min="3" max="100" oninput="custom()">
<button onclick="random()">random</button>
</div>
<div>Middle Click = set start position</div>
<div>Right Click = set end position</div>
<div id="custom"></div>
</span>
Related
So basically, I put buttons on each tile and update the tile locations using the "transform: translateY(x%);" CSS style, it updates the locations for each frame, which I set to 60 FPS, and loop through the function each frame using setInterval(). There is a onclick event which triggers "Incorrect()"/"Correct()" function on the buttons, but they do not work until I typed "clearInterval(mainLoop)" from the console.
const fps = 60
let current_frame = 0
let ingame = false
let speed = 0.25
let score = 0
let total_tiles = 0
const current_tiles = [
[],
[],
[],
[]
]
const GetElement = id => {
return document.getElementById(id)
}
const RNG = (min, max) => {
return Math.round(Math.random() * (max - min) + min)
}
const mainLoop = setInterval(MainLoop, (1000 / fps))
function Initialize() {
speed = 0.25
ingame = true
}
function GenerateAnswers() {
const data = all_questions
let answers = ["", "", "", ""]
let correct_tile_index
let questions = data.grammar
let chosen_question = questions[Math.floor(Math.random() * (questions.length - 0.001))]
let options = ["", "", "", ""]
correct_tile_index = Math.floor(Math.random() * 3.999)
for (let i = 0; i <= chosen_question.options.length - 1; i++) {
options[i] = chosen_question.options[i]
}
answers[correct_tile_index] = options[chosen_question.correct_index]
options.splice(chosen_question.correct_index, 1)
for (let i = 0; i <= answers.length - 1; i++) {
if (answers[i] == "") {
const chosen_index = Math.floor(Math.random() * (options.length - 0.001))
answers[i] = options[chosen_index]
options.splice(chosen_index, 1)
}
continue
}
console.log(answers, chosen_question.question)
return [answers, correct_tile_index]
}
function GenerateTiles() {
if (current_tiles[0].length < 1) {
const returns = GenerateAnswers()
const answers = returns[0]
const correct_tile_index = returns[1]
total_tiles++
current_tiles[0].push([-400, "Black", total_tiles, answers[0], (correct_tile_index == 0 ? "Correct" : "Incorrect")])
total_tiles++
current_tiles[1].push([-400, "Black", total_tiles, answers[1], (correct_tile_index == 1 ? "Correct" : "Incorrect")])
total_tiles++
current_tiles[2].push([-400, "Black", total_tiles, answers[2], (correct_tile_index == 2 ? "Correct" : "Incorrect")])
total_tiles++
current_tiles[3].push([-400, "Black", total_tiles, answers[3], (correct_tile_index == 3 ? "Correct" : "Incorrect")])
return UpdateTiles()
}
const highest_tile_location = current_tiles[0][current_tiles[0].length - 1][0]
const returns = GenerateAnswers()
const answers = returns[0]
const correct_tile_index = returns[1]
total_tiles++
current_tiles[0].push([highest_tile_location - 200, "Grey", total_tiles, answers[0], (correct_tile_index == 0 ? "Correct" : "Incorrect")])
total_tiles++
current_tiles[1].push([highest_tile_location - 200, "Grey", total_tiles, answers[1], (correct_tile_index == 1 ? "Correct" : "Incorrect")])
total_tiles++
current_tiles[2].push([highest_tile_location - 200, "Grey", total_tiles, answers[2], (correct_tile_index == 2 ? "Correct" : "Incorrect")])
total_tiles++
current_tiles[3].push([highest_tile_location - 200, "Grey", total_tiles, answers[3], (correct_tile_index == 3 ? "Correct" : "Incorrect")])
UpdateTiles()
}
function UpdateTiles() {
const format_translate_position = (percentage, tile) => {
const index = tile - 1
return (percentage + (current_tiles[index].length - 1) * 50)
}
let tempHTML
// First row
tempHTML = ""
for (let i = 0; i <= current_tiles[0].length - 1; i++) {
tempHTML += `<div class="Answer${current_tiles[0][i][1]}" id="tile${current_tiles[0][i][2]}" style="transform: translateY(${format_translate_position(current_tiles[0][i][0], 1)}%);">${current_tiles[0][i][3]}<br><button onclick="${current_tiles[0][i][4]}()"></button></div>`
}
GetElement("Answer1").innerHTML = tempHTML
// Second row
tempHTML = ""
for (let i = 0; i <= current_tiles[1].length - 1; i++) {
tempHTML += `<div class="Answer${current_tiles[1][i][1]}" id="tile${current_tiles[1][i][2]}" style="transform: translateY(${format_translate_position(current_tiles[1][i][0], 2)}%);">${current_tiles[1][i][3]}<button onclick="${current_tiles[1][i][4]}()"></button></div>`
}
GetElement("Answer2").innerHTML = tempHTML
// Third row
tempHTML = ""
for (let i = 0; i <= current_tiles[2].length - 1; i++) {
tempHTML += `<div class="Answer${current_tiles[2][i][1]}" id="tile${current_tiles[2][i][2]}" style="transform: translateY(${format_translate_position(current_tiles[2][i][0], 3)}%);">${current_tiles[2][i][3]}<button onclick="${current_tiles[2][i][4]}()"></button></div>`
}
GetElement("Answer3").innerHTML = tempHTML
// Fourth row
tempHTML = ""
for (let i = 0; i <= current_tiles[3].length - 1; i++) {
tempHTML += `<div class="Answer${current_tiles[3][i][1]}" id="tile${current_tiles[3][i][2]}" style="transform: translateY(${format_translate_position(current_tiles[3][i][0], 4)}%);">${current_tiles[3][i][3]}<button onclick="${current_tiles[3][i][4]}()"></button></div>`
}
GetElement("Answer4").innerHTML = tempHTML
}
function MainLoop() {
current_frame++
speed = 0.25 + score * 0.00125
GetElement("ScoreDisplay").innerHTML = `Score: ${score}`
if (current_tiles[0].length < 1) GenerateTiles()
if (current_tiles[0][current_tiles[0].length - 1][0] >= -(Math.log2(current_frame) * 1000)) GenerateTiles()
for (let i = 0; i <= current_tiles.length - 1; i++) {
for (let j = 0; j <= current_tiles[i].length - 1; j++) {
current_tiles[i][j][0] += speed
}
}
UpdateTiles()
}
function Correct() {
console.log("Correct")
score++
}
function Incorrect() {
console.log("Incorrect")
}
Initialize()
html {
overflow: hidden;
transform: translateX(-1.25%)
}
center {
text-align: center;
height: 100%
}
table {
width: 100%;
height: 85%
}
td {
width: 25%;
overflow-y: hidden
}
html,
body {
width: 100%;
height: 100%;
font-family: "Fredoka One";
background-color: aqua
}
question {
height: 9%;
font-size: 30px;
color: red
}
score {
height: 6%;
font-size: 20px;
color: red
}
div.AnswerBlack {
width: 100%;
height: 23.5%;
background-color: black;
color: red;
font-size: 10%
}
div.AnswerGrey {
width: 100%;
height: 23.5%;
background-color: rgba(1, 1, 1, 0.4);
color: red;
font-size: 0%
}
div.AnswerTransparent {
width: 100%;
height: 23.5%;
color: red;
font-size: 0%
}
button {
/* used to fill a tile with the button /*
width: 100%;
height: 100%;
transform: translateY(-11.2%)
}
<link href="https://fonts.googleapis.com/css?family=Fredoka One" rel="stylesheet">
<center>
<question>
Question
</question>
<br>
<score id="ScoreDisplay">
Score: 0
</score>
<br>
<table>
<tr>
<td id="Answer1">
</td>
<td id="Answer2">
</td>
<td id="Answer3">
</td>
<td id="Answer4">
</td>
</tr>
</table>
</center>
<noscript>
Please enable JavaScript support in order for the application/game to work
</noscript>
<script type="text/javascript" src="assets/questions/main.js"></script> USED FOR CHOOSING QUESTIONS WHICH DOES WORK AND I'M NOT GOING TO INCLUDE IT HERE
It seems like the problem is that your MainLoop function, which is responsible for updating the positions of the tiles, is running indefinitely until it is manually stopped using clearInterval(mainLoop) in the console. This can cause issues with button click events not being registered until the setInterval is stopped.
One way to fix this issue is to add a check at the beginning of your MainLoop function to ensure that the game is still in progress. You have a variable called ingame that you can use for this purpose. If ingame is false, you can stop the setInterval using clearInterval(mainLoop).
Here's an example of what the updated MainLoop function could look like:
function MainLoop() {
if (!ingame) {
clearInterval(mainLoop);
return;
}
current_frame++;
if (current_frame >= fps) {
current_frame = 0;
GenerateTiles();
speed += 0.0025;
}
for (let i = 0; i <= current_tiles.length - 1; i++) {
for (let j = 0; j <= current_tiles[i].length - 1; j++) {
current_tiles[i][j][0] += speed;
}
}
UpdateTiles();
}
In this updated MainLoop function, the first check ensures that the loop only runs while ingame is true. If ingame is false, the setInterval is stopped using clearInterval(mainLoop). If ingame is true, the rest of the loop runs as usual.
I wrote such a swap function for bubbleSort:
function swap(a, b) {
tmp = a;
a = b;
b = tmp;
}
then encapsulate it in the bubbleSort:
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - 1; j++) {
// swap the elements
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]); // use swap here.
}
}
}
}
And test it with:
arr = [34, 87, 21, 0, -11];
bubbleSort(arr)
but it stay unchanged, what's the problem?
The swap function takes a copy of the number instead of the pointer.. welcome to javascript?
Either way, you would need the array and the indexes to do a swap because objects are pointers, numbers are not
Here's an example
//working swap function
function swap(arr, a, b){
var tmp=arr[a]
arr[a]=b
arr[b]=tmp
}
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - 1; j++) {
// swap the elements
if (arr[j] > arr[j + 1]) {
swap(arr, j, j+1); // use swap here.
}
}
}
return arr //because why not
}
arr = [34, 87, 21, 0, -11];
console.log(bubbleSort(arr))
my 2 cents...
function bubbleSort(arr) // original algorythm
{
for ( let i=arr.length ; --i > 0 ; )
for ( let j=0, k=1 ; j < i ; j++, k++ )
if (arr[j] > arr[k])
[arr[j],arr[k]] = [arr[k],arr[j]];
}
const myArr = [33, 103, 3, 726, 200, 984, 198, 764, 9];
bubbleSort(myArr)
document.write( JSON.stringify(myArr) )
function bubbleSort(arr) // optimised algorythm
{
for (let i=arr.length, noSwap; --i>0;) // go reverse, important!
{
noSwap = true
for (let j=0, k=1; j<i; j++,k++)
if (arr[j] > arr[k])
{
[arr[j],arr[k]] = [arr[k],arr[j]];
noSwap = false
}
if (noSwap) break
} }
For those who wonder why in the BubbleSort algorithm the first index must necessarily start from the right to go up to the left
while the following clues go in the other direction, I made this animation to visualize its logic.
the idea of Bubble Sort is to push the highest value to the right, much like air bubbles in a liquid.
this code also makes it possible to realize why the performance of this type of sorting is poor, unless, by chance, the elements are close to the correct order (which is still hazardous).
const
btSort = document.querySelector('#bt-sort')
, btGener = document.querySelector('#bt-gen')
, movinBars = document.querySelector('#moving-bars')
, arrLen = document.querySelector('#arr-len')
, delay = ms => new Promise( r => setTimeout(r, ms))
;
// input range HTML system to get future length of the arr to sort
arrLen.value = arrLen.closest('label').dataset.val;
arrLen.oninput =_=>{ arrLen.closest('label').dataset.val = arrLen.value }
const
arrBars = (()=> // => { set size, setBarLeft(), setBarClass() }
{
let
len = 0
, Keys = [] // array keys on Bars
, Bars = [] // Bars elements
;
const
shuffleKeys =_=>
{
let X = len, Y;
while (X)
{
Y = (Math.random() * X--) | 0;
[Keys[X], Keys[Y]] = [ Keys[Y], Keys[X]];
}
}
, genBars =_=>
{
let xHeight= 0, szMin = (240/len)|0, szMax = (53.7143 -(len*(4/7)))|0;
let hg = [];
Bars = new Array(len);
for (let i=0;i<len;i++)
{
xHeight += szMin + ((Math.random() *szMax)|0);
hg.push( xHeight )
}
for (let i=0;i<len;i++)
{
Bars[i] = document.createElement('div')
Bars[i].style.height = `${hg[Keys[i]]}px`
Bars[i].style.left = `${i *17}px`
movinBars.appendChild(Bars[i])
}
}
, Obj =
{ set size( length )
{
if ( len !== length ) { Keys = [...Array(length).keys()] };
for( let i=0;i<len;i++) { delete Bars[i]; };
while (movinBars.firstChild) { movinBars.removeChild(movinBars.lastChild) };
len = length;
shuffleKeys();
genBars();
}
, bubbleSort: function* () // optimuzed version
{
let noSwap;
for (let i=len; --i>0 ;)
{
noSwap = true;
for (let j=0, k=1, j$=Keys[j], k$=Keys[k]; j<i; j$=Keys[++j], k$=Keys[++k] )
{
if ( j$>k$ )
{
Keys[j] = k$;
Keys[k] = j$;
noSwap = false;
yield ([ j, k, true ]);
}
else
yield ([ j, k, false ]);
}
if (noSwap) break;
}
}
, setBarLeft: (indx, vLeft ) => new Promise( r =>
{
let bar = Bars[indx];
bar.ontransitionend =_=>
{
bar.ontransitionend = null
r()
}
bar.style.left = `${vLeft *17}px`
})
, setBarsClass( x, y, onOff, doSwapp )
{
Bars[x].classList.toggle('Mov1',onOff)
Bars[y].classList.toggle('Mov2',onOff)
if (!onOff && doSwapp)
{
Bars[x].classList.remove('Mov1')
Bars[y].classList.remove('Mov2')
let hg_x = Bars[x].style.height
, lf_x = Bars[x].style.left
;
Bars[x].style.height = Bars[y].style.height
Bars[x].style.left = Bars[y].style.left
Bars[y].style.height = hg_x
Bars[y].style.left = lf_x
}
}
}
;
return Obj;
})();
/***************************** main part ***********/
btSort.disabled = true;
btGener.onclick =_=>
{
btGener.disabled = true;
arrLen.disabled = true;
arrBars.size = arrLen.valueAsNumber;
btSort.disabled = false;
}
btSort.onclick = async () =>
{
btSort.disabled = true;
for await (let [ x,y, doSwapp ] of arrBars.bubbleSort())
{
arrBars.setBarsClass( x, y, true, doSwapp )
if (doSwapp)
{
await arrBars.setBarLeft( x, y )
await arrBars.setBarLeft( y, x )
}
else
await delay(80);
arrBars.setBarsClass( x, y, false, doSwapp )
await delay(90)
}
btGener.disabled = false;
arrLen.disabled = false;
}
body {
background : #14141f;
margin : 0;
font-family : Arial, Helvetica, sans-serif;
font-size : 18px;
}
header {
background : #2d2d47;
padding : 1.3rem 0;
}
button {
border : 3px solid #29293a;
border-radius : .8rem;
background-color : #5b5b8d;
color : black;
font-size : 1.2rem;
width : 7.6rem;
vertical-align : middle;
margin : 0 0 0 1.5rem;
}
button:not(:disabled):hover {
background-color : #67678a;
color : whitesmoke;
cursor : pointer;
}
button:disabled {
background-color : #5b5b8d;
border-color : darkslategrey;
color : #29293a;
}
#moving-bars {
position : relative;
margin : 20px 0 0 20px;
}
#moving-bars > div {
position : absolute;
background : #3e3e50;
width : 10px;
top : 0;
}
#moving-bars > div.Mov1 {
transition : left .3s ease-in-out;
background : crimson;
}
#moving-bars > div.Mov2 {
transition : left .3s ease-in-out;
background : #ffff0088;
}
/******************************/
label.rg {
display : inline-block;
height : 1.8rem;
padding : .3rem .5rem 0 1rem;
color : black;
}
label.rg input {
vertical-align : middle;
width : 18rem;
}
label.rg::before {
display : inline-block;
content : attr(data-lib);
font-weight : bold;
color : #5f5fc2;
}
label.rg::after {
content : attr(data-val);
display : inline-block;
font-size : 1.2rem;
vertical-align : middle;
border : 1px solid #5b5b8d;
width : 2.8rem;
text-align : center;
border-radius : .6rem;
padding : .2rem 0;
margin-left : .2rem;
color : #5f5fc2;
}
<header>
<button id="bt-sort" > Sort </button>
<button id="bt-gen" > Generate </button>
<label class="rg" data-val="12" data-lib="Len: "> <input type="range" id="arr-len" min="9" max="40" step="1" ></label>
</header>
<div id="moving-bars"></div>
I making a swipable slider using touch events, when remains one visible element of visible elements I want to load new elements, for that I'm using this method:
initInteractionWithItems(elementsToMakeVisible) {
let totalMargin = 0 //the items are stacked and in the loop, the margin gradually gets bigger
let indexZ = 0 //the indexZ also gets bigger in the loop (is the z-index for the stacked elems)
const sizeItems = this.items.length
let styleElement = document.createElement("style")
document.head.appendChild(styleElement)
if (elementsToMakeVisible) {
firstInTheList.style.zIndex = "" + (elementsToMakeVisible + 1) * 1000
} else {
elementsToMakeVisible = this.itemsVisibleLength
}
totalMargin = this.marginTopFactor * elementsToMakeVisible
indexZ = elementsToMakeVisible * 1000
//while the list have elements, I show a portion of those
while ((elementsToMakeVisible !== 0) && (this.elementsCount < sizeItems)) {
let rule = ".swipeItem-" + this.elementsCount + "{ opacity: " + "1;" + "margin-top:" + totalMargin + "px;" + "z-index:" + indexZ + ";}"
this.items[this.elementsCount].classList.add("swipeItem-" + this.elementsCount)
totalMargin -= this.marginTopFactor
indexZ -= 1000
elementsToMakeVisible--
this.elementsCount++
styleElement.sheet.insertRule(rule)
}
}
}
The method do the job of show the elements, this same method I use when the page loads and I need
to show the first elements. but when I have to show more elements when the slider have only one element
the page gets slow, the element I removed (because I swipe it) gets stuck and lates to hide totally. finally the elements that I want load are show.
When I have to delete an element because was selected I use this method:
function sendTarget(event) {
if (event.cancelable) {
canSlide = false
event.preventDefault()
if (!has_option_selected) { //if a element has been selected
event.target.offsetParent.style.transform = "rotateZ(0deg)"
} else {
firstInTheList.remove()
firstInTheList = iteratorItems.next().value
countElements--
if (countElements === 1) { //if in the slider remains only one element
swipeReference.initInteractionWithItems(2)
}
}
}
}
Only the first element have the touch events, and every time an element gets selected I removed that element and the first element will be the next in the array I use for have the elements I want to show, for that I use this generator function:
function* getFirstItem(arrayElements) {
for (let i = 0; i < arrayElements.length; i++) {
arrayElements[i].addEventListener("touchstart", getCoords, true)
arrayElements[i].addEventListener("touchmove", slideTarget, true)
arrayElements[i].addEventListener("touchend", sendTarget, true)
yield arrayElements[i]
}
}
When I remove an element and I don't have to show new elements the sendTarget method works fine. the trouble is when I have to show new elements and I have to inkove initInteractionWithItems again.
How can I fix that?, what approach can I do for solve this performance trouble?
The full project:
let has_option_selected = false
let canSlide = false
let firstTime = true
let current_coord_x
let current_coord_y
let firstInTheList = null
let swipeItsClassName
let countElements = 3
let swipeReference = null
let iteratorItems = null
function getCoords(event) {
if (event.target.offsetParent.classList.contains("swipeItem") && event.cancelable) {
event.preventDefault()
canSlide = true
current_coord_x = event.changedTouches[0].clientX
current_coord_y = event.changedTouches[0].clientY
} else {
current_coord_x = event.clientX
current_coord_y = event.clientY
}
}
function calcRotation(translateXValue, element) {
let rotateValue = translateXValue * 0.10
if (rotateValue <= -15) {
notifySelection(element, 1)
return -15
} else if (rotateValue >= 15) {
notifySelection(element, -1)
return 15
} else {
notifySelection(element, 0)
return rotateValue
}
}
function moveTarget(event, target) {
let translateX = (event.changedTouches[0].clientX - current_coord_x)
let translateY = (event.changedTouches[0].clientY - current_coord_y)
if (event instanceof TouchEvent) {
if (firstTime) {
translateY += 100
}
target.style.transform = "translateX(" + translateX + "px" + ")" + " " + "translateY(" + translateY + "px)" + " " + "rotateZ(" + calcRotation(translateX, target) + "deg)"
}
}
function notifySelection(target, state) {
if (state === 1) {
//target.offsetParent.style.color = "green"
has_option_selected = true
} else if (state === -1) {
//target.offsetParent.style.color = "red"
has_option_selected = true
} else {
// target.offsetParent.style.color = "yellow"
has_option_selected = false
}
}
function sendTarget(event) {
if (event.cancelable) {
canSlide = false
event.preventDefault()
if (!has_option_selected) {
event.target.offsetParent.style.transform = "rotateZ(0deg)"
} else {
firstInTheList.remove()
firstInTheList = iteratorItems.next().value
countElements--
if (countElements === 1) {
swipeReference.initInteractionWithItems(2)
}
}
}
}
function slideTarget(e) {
let parentTarget = e.target.offsetParent
let hasClassItem = parentTarget.classList.contains("swipeItem")
if ((canSlide && e.cancelable && hasClassItem) && (firstInTheList === parentTarget)) {
e.preventDefault()
moveTarget(e, parentTarget)
}
}
function* getFirstItem(arrayElements) {
for (let i = 0; i < arrayElements.length; i++) {
arrayElements[i].addEventListener("touchstart", getCoords, true)
arrayElements[i].addEventListener("touchmove", slideTarget, true)
arrayElements[i].addEventListener("touchend", sendTarget, true)
yield arrayElements[i]
}
}
class SwipeSlider {
constructor(swipeItems, marginTopFactor = 30, itemsVisibleLenght = 3) {
//swipeItsClassName = swipeItemsClassName
swipeReference = this
this.items = swipeItems
iteratorItems = getFirstItem(this.items)
firstInTheList = iteratorItems.next().value
this.itemsVisibleLength = itemsVisibleLenght
this.marginTopFactor = marginTopFactor
this.totalMarginSize = (this.marginTopFactor * itemsVisibleLenght)
this.elementsCount = 0
}
initInteractionWithItems(elementsToMakeVisible) {
let totalMargin = 0
let indexZ = 0
const sizeItems = this.items.length
let styleElement = document.createElement("style")
document.head.appendChild(styleElement)
if (elementsToMakeVisible) {
firstInTheList.style.zIndex = "" + (elementsToMakeVisible + 1) * 1000
} else {
elementsToMakeVisible = this.itemsVisibleLength
}
totalMargin = this.marginTopFactor * elementsToMakeVisible
indexZ = elementsToMakeVisible * 1000
while ((elementsToMakeVisible !== 0) && (this.elementsCount < sizeItems)) {
let rule = ".swipeItem-" + this.elementsCount + "{ opacity: " + "1;" + "margin-top:" + totalMargin + "px;" + "z-index:" + indexZ + ";}"
this.items[this.elementsCount].classList.add("swipeItem-" + this.elementsCount)
totalMargin -= this.marginTopFactor
indexZ -= 1000
elementsToMakeVisible--
this.elementsCount++
styleElement.sheet.insertRule(rule)
}
}
}
function getArrayElements(elements) {
let array = []
for (let i = 0; i < 6; i++) {
array.push(elements[i])
}
return array
}
let arrayElements = getArrayElements(document.querySelectorAll(".swipeItem"))
let slider = new SwipeSlider(arrayElements)
slider.initInteractionWithItems()
#import url('https://fonts.googleapis.com/css?family=Solway&display=swap');
:root{
--fontHeadingProspect: 25px;
}
*{
box-sizing: border-box;
padding: 0;
margin: 0;
}
.swipeImg{
width: 100%;
height: 300px;
grid-row: 1;
grid-column: 1;
object-fit: cover;
object-position: center;
border-radius: 15px;
}
.swipeContainer{
position: relative;
display: grid;
min-height: 100vh;
justify-content: center;
align-content: center;
align-items: center;
justify-items: center;
grid-template-rows: minmax(300px,auto);
}
.gridSwipeItem{
display: grid;
}
.swipeItem{
background-color: rgb(252, 237, 223);
position: relative;
max-width: 270px;
grid-column: 1 ;
grid-row: 1;
opacity: 0;
font-family: 'Solway', serif;
box-shadow: 0px 0px 5px rgb(233, 209, 130);
border-radius: 15px;
transition: opacity 0.5s;
z-index: 0;
}
.headingProspect{
grid-row: 1;
grid-column: 1;
font-size: var(--fontHeadingProspect);
color: white;
z-index: 1;
align-self: end;
margin-left: 15px;
margin-bottom: 15px;
}
.headingProspectSection{
writing-mode: vertical-rl;
grid-column: 1 / 2;
justify-self: start;
transform: rotateZ(180deg);
margin-left: 30px;
font-size: 34px;
font-family: 'Solway', serif;
text-align: center;
text-transform: uppercase;
color: #f74040;
}
.selection-zone{
background-image: rgb(255, 225, 169);
}
.visibleTarget{
opacity: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<section class="selection-zone">
<div class="swipeContainer" id="swipeContainer">
<article class="swipeItem gridSwipeItem" id="swipeItem">
<img src="http://lorempixel.com/1200/1200" class="swipeImg">
<h1 id="prospectState" class="headingProspect">Rose Ann, 19</h1>
</article>
<article class="swipeItem gridSwipeItem">
<img src="http://lorempixel.com/1200/1200" class="swipeImg">
<h1 id="prospectState" class="headingProspect">Mary Wolfstoncraft, 24</h1>
</article>
<article class="swipeItem gridSwipeItem">
<img src="http://lorempixel.com/1200/1200" class="swipeImg">
<h1 id="prospectState" class="headingProspect">Rose Doe, 34</h1>
</article>
<article class="swipeItem gridSwipeItem">
<img src="http://lorempixel.com/1200/1200" class="swipeImg">
<h1 id="prospectState" class="headingProspect">Joane Smith, 34</h1>
</article>
<article class="swipeItem gridSwipeItem">
<img src="http://lorempixel.com/1200/1200" class="swipeImg">
<h1 id="prospectState" class="headingProspect">Mary Wolfstoncraft, 24</h1>
</article>
</div>
</section>
<script src="script.js"></script>
</body>
</html>
I am making Mean Stack App in which I need to print barcode, I am using an angular js directive for generating code 128 barcode, and it is generating well, but when I click print button (javascript:window.print()) it is not showing the barcode in printing window neither in PDF,
Here is my directive,
.directive('barcodeGenerator', [function() {
var Barcode = (function () {
var barcode = {
settings: {
barWidth: 1,
barHeight: 50,
moduleSize: 5,
showHRI: false,
addQuietZone: true,
marginHRI: 5,
bgColor: "#FFFFFF",
color: "#000000",
fontSize: 10,
posX: 0,
posY: 0
},
intval: function(val) {
var type = typeof(val);
if ( type == 'string' ) {
val = val.replace(/[^0-9-.]/g, "");
val = parseInt(val * 1, 10);
return isNaN(val) || !isFinite(val)? 0: val;
}
return type == 'number' && isFinite(val)? Math.floor(val): 0;
},
code128: {
encoding:[
"11011001100", "11001101100", "11001100110", "10010011000",
"10010001100", "10001001100", "10011001000", "10011000100",
"10001100100", "11001001000", "11001000100", "11000100100",
"10110011100", "10011011100", "10011001110", "10111001100",
"10011101100", "10011100110", "11001110010", "11001011100",
"11001001110", "11011100100", "11001110100", "11101101110",
"11101001100", "11100101100", "11100100110", "11101100100",
"11100110100", "11100110010", "11011011000", "11011000110",
"11000110110", "10100011000", "10001011000", "10001000110",
"10110001000", "10001101000", "10001100010", "11010001000",
"11000101000", "11000100010", "10110111000", "10110001110",
"10001101110", "10111011000", "10111000110", "10001110110",
"11101110110", "11010001110", "11000101110", "11011101000",
"11011100010", "11011101110", "11101011000", "11101000110",
"11100010110", "11101101000", "11101100010", "11100011010",
"11101111010", "11001000010", "11110001010", "10100110000",
"10100001100", "10010110000", "10010000110", "10000101100",
"10000100110", "10110010000", "10110000100", "10011010000",
"10011000010", "10000110100", "10000110010", "11000010010",
"11001010000", "11110111010", "11000010100", "10001111010",
"10100111100", "10010111100", "10010011110", "10111100100",
"10011110100", "10011110010", "11110100100", "11110010100",
"11110010010", "11011011110", "11011110110", "11110110110",
"10101111000", "10100011110", "10001011110", "10111101000",
"10111100010", "11110101000", "11110100010", "10111011110",
"10111101110", "11101011110", "11110101110", "11010000100",
"11010010000", "11010011100", "11000111010"
],
getDigit: function(code) {
var tableB = " !\"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var result = "";
var sum = 0;
var isum = 0;
var i = 0;
var j = 0;
var value = 0;
// check each characters
for(i=0; i<code.length; i++){
if (tableB.indexOf(code.charAt(i)) == -1){
return("");
}
}
// check firsts characters : start with C table only if enought numeric
var tableCActivated = code.length > 1;
var c = '';
for (i=0; i<3 && i<code.length; i++) {
c = code.charAt(i);
tableCActivated &= c >= '0' && c <= '9';
}
sum = tableCActivated ? 105 : 104;
// start : [105] : C table or [104] : B table
result = this.encoding[ sum ];
i = 0;
while ( i < code.length ) {
if ( !tableCActivated) {
j = 0;
// check next character to activate C table if interresting
while ( (i + j < code.length) && (code.charAt(i+j) >= '0') && (code.charAt(i+j) <= '9') ) {
j++;
}
// 6 min everywhere or 4 mini at the end
tableCActivated = (j > 5) || ((i + j - 1 == code.length) && (j > 3));
if ( tableCActivated ){
result += this.encoding[ 99 ]; // C table
sum += ++isum * 99;
} // 2 min for table C so need table B
} else if ( (i == code.length) || (code.charAt(i) < '0') || (code.charAt(i) > '9') || (code.charAt(i+1) < '0') || (code.charAt(i+1) > '9') ) {
tableCActivated = false;
result += this.encoding[ 100 ]; // B table
sum += ++isum * 100;
}
if ( tableCActivated ) {
value = barcode.intval(code.charAt(i) + code.charAt(i+1)); // Add two characters (numeric)
i += 2;
} else {
value = tableB.indexOf( code.charAt(i) ); // Add one character
i += 1;
}
result += this.encoding[ value ];
sum += ++isum * value;
}
result += this.encoding[sum % 103];// Add CRC
result += this.encoding[106];// Stop
result += "11";// Termination bar
return(result);
}
},
bitStringTo2DArray: function( digit) {//convert a bit string to an array of array of bit char
var d = [];
d[0] = [];
for ( var i=0; i<digit.length; i++) {
d[0][i] = digit.charAt(i);
}
return(d);
},
digitToCssRenderer: function( $container, settings, digit, hri, mw, mh, type) {// css barcode renderer
var lines = digit.length;
var columns = digit[0].length;
var content = "";
var len, current;
var bar0 = "<div class='w w%s' ></div>";
var bar1 = "<div class='b b%s' ></div>";
for ( var y=0, x; y<lines; y++) {
len = 0;
current = digit[y][0];
for ( x=0; x<columns; x++){
if ( current == digit[y][x] ) {
len++;
} else {
content += (current == '0'? bar0: bar1).replace("%s", len * mw);
current = digit[y][x];
len=1;
}
}
if ( len > 0) {
content += (current == '0'? bar0: bar1).replace("%s", len * mw);
}
}
if ( settings.showHRI) {
content += "<div style=\"clear:both; width: 100%; background-color: " + settings.bgColor + "; color: " + settings.color + "; text-align: center; font-size: " + settings.fontSize + "px; margin-top: " + settings.marginHRI + "px;\">"+hri+"</div>";
}
var div = document.createElement('DIV');
div.innerHTML = content;
div.className = 'barcode '+ type +' clearfix-child';
return div;
},
digitToCss: function($container, settings, digit, hri, type) {// css 1D barcode renderer
var w = barcode.intval(settings.barWidth);
var h = barcode.intval(settings.barHeight);
return this.digitToCssRenderer($container, settings, this.bitStringTo2DArray(digit), hri, w, h, type);
}
};
var generate = function(datas, type, settings) {
var
digit = "",
hri = "",
code = "",
crc = true,
rect = false,
b2d = false
;
if ( typeof(datas) == "string") {
code = datas;
} else if (typeof(datas) == "object") {
code = typeof(datas.code) == "string" ? datas.code : "";
crc = typeof(datas.crc) != "undefined" ? datas.crc : true;
rect = typeof(datas.rect) != "undefined" ? datas.rect : false;
}
if (code == "") {
return(false);
}
if (typeof(settings) == "undefined") {
settings = [];
}
for( var name in barcode.settings) {
if ( settings[name] == undefined) {
settings[name] = barcode.settings[name];
}
}
switch (type) {
case "std25":
case "int25": {
digit = barcode.i25.getDigit(code, crc, type);
hri = barcode.i25.compute(code, crc, type);
break;
}
case "ean8":
case "ean13": {
digit = barcode.ean.getDigit(code, type);
hri = barcode.ean.compute(code, type);
break;
}
case "upc": {
digit = barcode.upc.getDigit(code);
hri = barcode.upc.compute(code);
break;
}
case "code11": {
digit = barcode.code11.getDigit(code);
hri = code;
break;
}
case "code39": {
digit = barcode.code39.getDigit(code);
hri = code;
break;
}
case "code93": {
digit = barcode.code93.getDigit(code, crc);
hri = code;
break;
}
case "code128": {
digit = barcode.code128.getDigit(code);
hri = code;
break;
}
case "codabar": {
digit = barcode.codabar.getDigit(code);
hri = code;
break;
}
case "msi": {
digit = barcode.msi.getDigit(code, crc);
hri = barcode.msi.compute(code, crc);
break;
}
case "datamatrix": {
digit = barcode.datamatrix.getDigit(code, rect);
hri = code;
b2d = true;
break;
}
}
if ( digit.length == 0) {
return this;
}
if ( !b2d && settings.addQuietZone) {
digit = "0000000000" + digit + "0000000000";
}
var fname = 'digitToCss' + (b2d ? '2D' : '');
return barcode[fname](this, settings, digit, hri, type);
};
return generate;
}());
return {
link: function(scope, element, attrs) {
attrs.$observe('barcodeGenerator', function(value){
var code = Barcode(value, "code128",{barWidth:2}),
code_wrapper = angular.element("<div class='barcode code128'></div>")
code_wrapper.append(code);
angular.element(element).html('').append(code_wrapper);
});
}
}
And here is barcode generating code,
<div ng-model='myInput' barcode-generator="{{myInput}}" style="height:208px;">
</div>
Here are the screenshots
It shows barcode on the page
But not shows up while printing
It's because some browsers has turned off rendering background-color in print mode by default. You won't force all users to mess up with browser settings, but you can replace background-color with border-width like this:
<style type="text/css" media="print">
.barcode.code128 > div.b {
border-style: solid !important;
border-color: #000000 !important;
}
.barcode.code128 .b1 {
width: 0px !important;
border-width: 0px 0px 0px 1px !important;
}
.barcode.code128 .b2 {
width: 0px !important;
border-width: 0px 0px 0px 2px !important;
}
.barcode.code128 .b3 {
width: 0px !important;
border-width: 0px 0px 0px 3px !important;
}
.barcode.code128 .b4 {
width: 0px !important;
border-width: 0px 0px 0px 4px !important;
}
.barcode.code128 .b5 {
width: 0px !important;
border-width: 0px 0px 0px 5px !important;
}
.barcode.code128 .b6 {
width: 0px !important;
border-width: 0px 0px 0px 6px !important;
}
.barcode.code128 .b7 {
width: 0px !important;
border-width: 0px 0px 0px 7px !important;
}
.barcode.code128 .b8 {
width: 0px !important;
border-width: 0px 0px 0px 8px !important;
}
.barcode.code128 .b9 {
width: 0px !important;
border-width: 0px 0px 0px 9px !important;
}
.barcode.code128 .b10 {
width: 0px !important;
border-width: 0px 0px 0px 10px !important;
}
i've been in a battle to sort this problem since yesterday and i fear that i've gotten tunnel vision.
The game:
first player to make a line of 3 of a kind (xxx or 000) wins.
http://jsfiddle.net/brunobliss/YANAW/
The catch:
Only the first horizontal line is working!!! I can make it all work using a lot of IFS but repeating the same code over and over again is often a good indicator that i'm doing somethin wrong
The problem:
bruno.checkWin(); will check if there's a line or not, the guy who presented me this game chalenge told me that it is possible to check the lines with a for loop and that i should use it instead of IFS. I can't solve this without IFS unfortunately...
<!doctype html>
<html>
<head>
<meta charset="iso-8859-1">
<title> </title>
<style>
#jogo {
border: #000 1px solid;
width: 150px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -75px;
margin-top: -75px;
}
#jogo div {
display: inline-block;
vertical-align: top;
width: 28px;
height: 28px;
padding: 10px;
font-size: 20px;
border: #000 1px solid;
border-collapse: collapse;
text-align: center;
}
#reset {
font-family: Verdana;
width: 153px;
height: 30px;
background-color: black;
color: white;
text-align: center;
cursor: pointer;
left: 50%;
top: 50%;
position: absolute;
margin-left: -76px;
margin-top: 100px;
}
</style>
<script> </script>
</head>
<body>
<div id="jogo"> </div>
<div id="reset"> RESET </div>
<script>
var ultimo = "0";
var reset = document.getElementById('reset');
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
var bruno = {
init: function () {
var jogo = document.getElementById('jogo');
for ( i = 0 ; i < 9 ; i++ ) {
var cell = document.createElement('div');
cell.onclick = function () {
// variavel publica dentro do obj?
ultimo = (ultimo == "x") ? 0 : "x";
this.innerHTML = ultimo;
bruno.checkWin();
};
jogo.appendChild(cell);
}
},
checkWin: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
// as diagonais nao verificar por loop
for ( i = 0 ; i < cell.length ; i=i+4 ) {
switch(i) {
case 0:
if (cell[0].innerHTML != '') {
bruno.checkFirst();
}
case 4:
if (cell[4].innerHTML != '') {
bruno.checkFirst();
}
case 8:
if (cell[8].innerHTML != '') {
bruno.checkFirst();
}
}
/*
} else
if (i == 4 && cell[4].innerHTML != '') {
bruno.checkCenter();
} else
if (i == 8 && cell[8].innerHTML != '') {
bruno.checkLast();
}*/
}
},
reset: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
for ( j = 0 ; j < cell.length ; j++ ) {
cell[j].innerHTML = "";
}
},
checkFirst: function () {
if (cell[0].innerHTML == cell[1].innerHTML && cell[1].innerHTML == cell[2].innerHTML) {
alert("linha horizontal");
return false;
} else
if (cell[0].innerHTML == cell[3].innerHTML && cell[3].innerHTML == cell[6].innerHTML) {
alert("linha vertical");
return false;
}
},
checkMiddle: function () {
// check vertical and horizontal lines from the center
},
checkLast: function () {
// check last horizontal and right edge vertical
}
};
window.onload = function () {
bruno.init();
};
reset.onclick = function () {
bruno.reset();
};
</script>
</body>
</html>
I came up with a more 'compact' version of your code. No switch statements. Have a look:
http://jsfiddle.net/YANAW/1/
Here's the code, for those who prefer to read it here. Important/updated functions are checkWin() and checkCells().
var bruno = {
init: function () {
var jogo = document.getElementById('jogo');
for ( i = 0 ; i < 9 ; i++ ) {
var cell = document.createElement('div');
cell.onclick = function () {
// variavel publica dentro do obj?
ultimo = (ultimo == "x") ? 0 : "x";
this.innerHTML = ultimo;
bruno.checkWin();
};
jogo.appendChild(cell);
}
},
checkWin: function () {
var jogo = document.getElementById('jogo');
var cells = jogo.getElementsByTagName('div');
// Scan through every cell
var numRows = 3;
var numColumns = 3;
for (var i = 0; i < cells.length; i++)
{
// Determine cell's position
var isHorizontalFirstCell = ((i % numColumns) === 0);
var isVerticalFirstCell = (i < numColumns);
var isTopLeftCorner = (i == 0);
var isTopRightCorner = (i == 2);
// Check for horizontal matches
if (isHorizontalFirstCell
&& bruno.checkCells(
cells, i,
(i + 3), 1))
{
alert('Horizontal');
}
// Check for vertical matches
if (isVerticalFirstCell
&& bruno.checkCells(
cells, i,
(i + 7), 3))
{
alert('Vertical');
}
// Check for diagonal matches
if (isTopLeftCorner
&& bruno.checkCells(
cells, i,
(i + 9), 4))
{
alert('Diagonal');
}
if (isTopRightCorner
&& bruno.checkCells(
cells, i,
(i + 5), 2))
{
alert('Diagonal');
}
}
},
reset: function () {
var jogo = document.getElementById('jogo');
var cell = jogo.getElementsByTagName('div');
for ( j = 0 ; j < cell.length ; j++ ) {
cell[j].innerHTML = "";
}
},
checkCells: function(cells, index, limit, step) {
var sequenceChar = null;
for (var i = index; i < limit; i += step)
{
// Return false immediately if one
// of the cells in the sequence is empty
if (!cells[i].innerHTML)
return false;
// If this is the first cell we're checking,
// store the character(s) it holds.
if (sequenceChar === null)
sequenceChar = cells[i].innerHTML;
// Otherwise, confirm that this cell holds
// the same character(s) as the previous cell(s).
else if (cells[i].innerHTML !== sequenceChar)
return false;
}
// If we reached this point, the entire sequence
// of cells hold the same character(s).
return true;
}
};