I am attempting to create a grid that contains one letter in each box (like a Word Find puzzle).
I have successfully created a grid that shows w/ the determined number of cols/rows, but when I attempt to put one letter in each box, I get the following ten times in each box instead of a single letter:
[object
Object]
Here is the JavaScript:
$(function() {
var letters = [
'rzeabppssgcddrvddydtjrkei', // 1
'cezcqubhniittonieqerbiuvm', // 2
'jqcjnasionsncvbsrwtabddsu', // 3
'olselesitneagittrjanreinv', // 4
'nqnaisdenmeibvurellsnrioc', // 5
'ydnlevrnyeaidrwifkufmsuis', // 6
'dcccjeeaogsemudbeemefaptn', // 7
'evonsqpdepislsnudnurwjbpo', // 8
'grytiunnafsexattmtclaimoi', // 9
'pnqrhocbiieeinoitacilppat', // 10
];
var letter = [];
function splitRows(arr, arr2) {
for (let i=0; i < arr.length; i++) {
arr[i].split();
for (let j=0; j < arr.length; j++) {
arr2[j] = arr[i][j];
}
}
}
splitRows(letters, letter);
function* gen(arr) {
for(i=0; i < arr.length; i++) {
yield arr[i];
}
}
function generateGrid(rows, cols, arr) {
var grid = "<table>";
for(row = 1; row <= rows; row++) {
grid += "<tr>";
for(col = 1; col <= cols; col++) {
grid += "<td>";
for(let i=0; i < arr.length; i++) {
grid += gen(arr).next(); // not sure if the .next() generator works yet
}
grid += "</td>"; // 'letters' needs to input the next letter in letters each time it is called
}
grid += "</tr>";
}
return grid;
}
$("#tableContainer").append(generateGrid(26, 22, letter));
});
The first function is intended to take rows and split them into singular letters (eventually taking rows as an input, but for testing purposes I have them in an array)
The second function is a generator to insert into the generateGrid() function that is used to generate the next letter in the sequence each time a box is created.
You should convert your string data to a matrix first then you can run the matrix through a table.
The following jQuery plugin clears the table and replaces it with rows and columns based on the data.
Note: I also added in tag name validation, in the case where the element the plugin was being invoked upon was not a <table> element.
var DEBUG_EXPERIMENTAL = false;
initializePlugins(); // Forward Declaration of jQuery plugins
let rawStringData = `
rzeabppssgcddrvddydtjrkei
cezcqubhniittonieqerbiuvm
jqcjnasionsncvbsrwtabddsu
olselesitneagittrjanreinv
nqnaisdenmeibvurellsnrioc
ydnlevrnyeaidrwifkufmsuis
dcccjeeaogsemudbeemefaptn
evonsqpdepislsnudnurwjbpo
grytiunnafsexattmtclaimoi
pnqrhocbiieeinoitacilppat
`;
$('.word-search').buildWordSearch(rawStringData, 'letter');
$('.letter').enableHighliting('highlight');
function initializePlugins() {
(($) => {
$.stringToMatrix = function(str) {
return str.trim().split('\n').map(row => row.trim().split(''));
};
$.fn.buildWordSearch = function(stringData, cellClass) {
this.throwErrorIfNotType('TABLE');
return this.append($('<tbody>')
.append($.stringToMatrix(stringData).map(row => {
return $('<tr>').append(row.map(col => {
return $('<td>').addClass(cellClass).text(col);
}));
})));
};
$.fn.throwErrorIfNotType = function(expectedTagName) {
let actualTagName = this.prop('tagName');
if (actualTagName !== expectedTagName) {
throw Error(`Element '${actualTagName}' is not a '${expectedTagName}'!`);
}
};
$.fn.getCell = function(x, y) {
return this.find(`tr:nth-child(${y + 1}) td:nth-child(${x + 1})`);
};
$.fn.enableHighliting = function(cls) {
return this.each(() => {
this.on({
mouseover: function() {
let $table = $(this).closest('table');
let $row = $(this).closest('tr');
let rowIndex = $row.index();
let colIndex = $(this).index();
let rowCount = $table.find('tbody tr').length;
let colCount = $row.find('td').length;
// Hightlights diagonals.
if (DEBUG_EXPERIMENTAL) {
let limit = rowCount;
let xNeg = colIndex - 1;
let xPos = colIndex + 1;
let yNeg = rowIndex - 1;
let yPos = rowIndex + 1;
while (limit > 0) {
if (xNeg > -1 && yNeg > -1) {
$table.getCell(xNeg, yNeg).addClass(cls);
}
if (xPos < colCount && yNeg > -1) {
$table.getCell(xPos, yNeg).addClass(cls);
}
if (xNeg > -1 && yPos < rowCount) {
$table.getCell(xNeg, yPos).addClass(cls);
}
if (xPos < colCount && yPos < rowCount) {
$table.getCell(xPos, yPos).addClass(cls);
}
xNeg--;
xPos++;
yNeg--;
yPos++;
limit--;
}
}
$row.addClass(cls);
$table.find(`td:nth-child(${colIndex + 1})`).addClass(cls);
},
mouseout: function() {
let $table = $(this).closest('table');
let $row = $(this).closest('tr');
let rowIndex = $row.index();
let colIndex = $(this).index();
let rowCount = $table.find('tbody tr').length;
let colCount = $row.find('td').length;
// Un-hightlights diagonals.
if (DEBUG_EXPERIMENTAL) {
let limit = rowCount;
let xNeg = colIndex - 1;
let xPos = colIndex + 1;
let yNeg = rowIndex - 1;
let yPos = rowIndex + 1;
while (limit > 0) {
if (xNeg > -1 && yNeg > -1) {
$table.getCell(xNeg, yNeg).removeClass(cls);
}
if (xPos < colCount && yNeg > -1) {
$table.getCell(xPos, yNeg).removeClass(cls);
}
if (xNeg > -1 && yPos < rowCount) {
$table.getCell(xNeg, yPos).removeClass(cls);
}
if (xPos < colCount && yPos < rowCount) {
$table.getCell(xPos, yPos).removeClass(cls);
}
xNeg--;
xPos++;
yNeg--;
yPos++;
limit--;
}
}
$row.removeClass(cls);
$table.find(`td:nth-child(${colIndex + 1})`).removeClass(cls);
}
});
});
};
})(jQuery);
}
.word-search {
border: 2px solid #000;
border-collapse: collapse;
}
.word-search td {
width: 1.25em;
height: 1.25em;
line-height: 1.25em;
text-align: center;
}
.highlight {
background: #FFD;
}
.letter.highlight:hover {
background: #FF0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="word-search"></table>
Related
I would like to add a second <tr> to the footer of my datatable in order to display the grand total (after doing some sums).
All the calculations are already working, I just want to inject the value of rowSum when j >= 12 in the 2nd row of the footer.
Concept of the desired result (cropped image):
This is what I've tried:
✓ Adding a second <tr> to the datatable (working)
✗ Inject the value of rowSum to the last column of the second row of the footer (I guess I am doing something wrong here)
And this is the part of the code that I think is wrong:
$('#example > tfoot > tr').each(function(index, tr) {
var rowSum = 0;
for (let j = 0; j < 12; j++) {
if (j >= 2) {
var tdCellValue = numberFromString(tr.cells[j].innerText);
rowSum = rowSum + tdCellValue;
}
if (j >= 11) {
tr.cells[12].innerText = rowSum;
tr[1].cells[12].innerText = rowSum;
}
}
});
Here I tried to access to the second row of the footer: tr[1].cells[12].innerText = rowSum; and I think this is where I made the mistake.
DEMO JS BIN
Does anyone know how can I access the second row of the datatable footer and inject the value properly?
Just replace your JS code with the following. Here is Demo of the working file.
<script>
$(document).ready(function() {
var DT1 = $('#example').DataTable({
columnDefs: [{
orderable: false,
className: 'select-checkbox',
targets: 0,
}],
select: {
style: 'os',
selector: 'td:first-child'
},
order: [
[1, 'asc']
],
"language": {
"info": "Showing _START_ to _END_ of _TOTAL_ Projects",
"infoEmpty": "Showing 0 to 0 of 0 Projects",
"infoFiltered": "(filtered from _MAX_ total Projects)"
},
"pagingType": "numbers",
dom: 'rtip',
initComplete: function(settings, json) {
// calculate the sum when table is first created:
doSum();
}
});
$('#example').on('draw.dt', function() {
// re-calculate the sum whenever the table is re-displayed:
doSum();
});
$(".selectAll").on("click", function(e) {
if ($(this).is(":checked")) {
DT1.rows().select();
} else {
DT1.rows().deselect();
}
});
// This provides the sum of all records:
function doSum() {
// get the DataTables API object:
var table = $('#example').DataTable();
// set up the initial (unsummed) data array for the footer row:
var totals = ['', 'Total:', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// iterate all rows - use table.rows( {search: 'applied'} ).data()
// if you want to sum only filtered (visible) rows:
totals = table.rows().data()
// sum the amounts:
.reduce(function(sum, record) {
for (let i = 2; i <= 12; i++) {
sum[i] = sum[i] + numberFromString(record[i]);
}
return sum;
}, totals);
// place the sum in the relevant footer cell:
for (let i = 1; i <= 12; i++) {
var column = table.column(i);
$(column.footer()).html(formatNumber(totals[i]));
}
$('#example > tbody > tr').each(function(index, tr) {
var rowSum=0;
for(let j=0; j<12; j++)
{
if(j>=2){
var tdCellValue= numberFromString(tr.cells[j].innerText);
rowSum=rowSum+tdCellValue;
}
if(j >=11){
tr.cells[12].innerText=rowSum;
}
}
});
var grandTotal=0;
$('#example > tfoot > tr').each(function(index, tr) {
if(index<1){
grandTotal=0;
var rowSum = 0;
for (let j = 0; j < 12; j++) {
if (j >= 2) {
var tdCellValue = numberFromString(tr.cells[j].innerText);
rowSum = rowSum + tdCellValue;
}
if (j >= 11) {
tr.cells[12].innerText = rowSum;
grandTotal=rowSum;
}
}
}else{
tr.cells[11].innerText = "Grand Total";
tr.cells[12].innerText = grandTotal;
}
});
}
function numberFromString(s) {
return typeof s === 'string' ?
s.replace(/[\$,]/g, '') * 1 :
typeof s === 'number' ?
s : 0;
}
function formatNumber(n) {
return n.toLocaleString(); // or whatever you prefer here
}
});
</script>
If you want to calculator value of last column, you need get sum of all cells in this row ( not 2 rows with $('#example > tfoot > tr').each -> in html , you have 2 tr )
$('#example > tfoot > tr').each(function(index, tr) {
if (index == 0) {
var rowSum = 0;
for (let j = 0; j < totalCol; j++) {
if (j >= 2 && j < 12) {
var tdCellValue = numberFromString(tr.cells[j].innerText);
rowSum = rowSum + tdCellValue;
}
if (j >= 12) {
tr.cells[12].innerText = rowSum;
// tr[1].cells[12].innerText = rowSum;
}
}
}
});
I have a maze game ( making player and end goal later) and im trying to make a span that will show up once the game is completed. so far its doing nothing.
Ive tried this
var mazeComplete = document.getElementById("mazeComplete");
var gameComplete = false;
function checkGameFinished() {
if(gameComplete = false){
mazeComplete.style.visibility = 'hidden'
} else if (gameComplete = true) {
mazeComplete.style.visibility = 'visible'
}
}
but with all my code its not working at all. just wanted to see if i could hide the text.
html:
<head>
<title>Maze</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="mazegenerator.js"></script>
<script type="text/javascript" src="Maze.js"></script>
<style type="text/css">
#maze {
border-collapse: collapse;
}
#maze td {
width: 20px;
height: 20px;
}
canvas {
position: absolute;
}
</style>
</head>
<body>
<table id="maze">
<tbody></tbody>
</table>
<script>
var disp = newMaze(20,20);
for (var i = 0; i < disp.length; i++) {
$('#maze > tbody').append("");
for (var j = 0; j < disp[i].length; j++) {
var selector = i+"-"+j;
$('#maze > tbody').append("<td id='"+selector+"'> </td>");
if (disp[i][j][0] == 0) { $('#'+selector).css('border-top', '2px solid black'); }
if (disp[i][j][1] == 0) { $('#'+selector).css('border-right', '2px solid black'); }
if (disp[i][j][2] == 0) { $('#'+selector).css('border-bottom', '2px solid black'); }
if (disp[i][j][3] == 0) { $('#'+selector).css('border-left', '2px solid black'); }
}
$('#maze > tbody').append("");
}
</script>
<br>
<span id="mazeComplete">Maze complete <button id="resetMaze" onclick="mazeReset()">New Maze</button> </span>
Completed <span id="mazeCompletions">0</span>
</body>
</html>
Javascript:
function newMaze(x, y) {
// Establish variables and starting grid
var totalCells = x*y;
var cells = new Array();
var unvis = new Array();
for (var i = 0; i < y; i++) {
cells[i] = new Array();
unvis[i] = new Array();
for (var j = 0; j < x; j++) {
cells[i][j] = [0,0,0,0];
unvis[i][j] = true;
}
}
// Set a random position to start from
var currentCell = [Math.floor(Math.random()*y), Math.floor(Math.random()*x)];
var path = [currentCell];
unvis[currentCell[0]][currentCell[1]] = false;
var visited = 1;
// Loop through all available cell positions
while (visited < totalCells) {
// Determine neighboring cells
var pot = [[currentCell[0]-1, currentCell[1], 0, 2],
[currentCell[0], currentCell[1]+1, 1, 3],
[currentCell[0]+1, currentCell[1], 2, 0],
[currentCell[0], currentCell[1]-1, 3, 1]];
var neighbors = new Array();
// Determine if each neighboring cell is in game grid, and whether it has already been checked
for (var l = 0; l < 4; l++) {
if (pot[l][0] > -1 && pot[l][0] < y && pot[l][1] > -1 && pot[l][1] < x && unvis[pot[l][0]][pot[l][1]]) { neighbors.push(pot[l]); }
}
// If at least one active neighboring cell has been found
if (neighbors.length) {
// Choose one of the neighbors at random
next = neighbors[Math.floor(Math.random()*neighbors.length)];
// Remove the wall between the current cell and the chosen neighboring cell
cells[currentCell[0]][currentCell[1]][next[2]] = 1;
cells[next[0]][next[1]][next[3]] = 1;
// Mark the neighbor as visited, and set it as the current cell
unvis[next[0]][next[1]] = false;
visited++;
currentCell = [next[0], next[1]];
path.push(currentCell);
}
// Otherwise go back up a step and keep going
else {
currentCell = path.pop();
}
}
return cells;
}
function mazeReset(){
document.location.reload()
}
var mazeComplete = document.getElementById("mazeComplete");
var gameComplete = false;
function checkGameFinished() {
if(gameComplete = false){
mazeComplete.style.visibility = 'hidden'
} else if (gameComplete = true) {
mazeComplete.style.visibility = 'visible'
}
}
I expect when game is launched for
<span id="mazeComplete">Maze complete <button id="resetMaze" onclick="mazeReset()">New Maze</button> </span>
to be hidden until gamecomplete becomes true. but at the moment its not hidden at all.
js fiddle:
https://jsfiddle.net/pma17sfq/3/
There are several things wrong with your code:
You are never calling checkGameFinished(), so the check and the hiding are never performed
By the time your script is executed, the element #mazeComplete does not exist yet. Move your script to the end of the body.
In your if conditions, gameComplete = false and gameComplete = true are not comparing the value, but setting it! Change the operator to === to perform a type-safe comparison.
var disp = newMaze(20, 20);
for (var i = 0; i < disp.length; i++) {
$('#maze > tbody').append("<tr>");
for (var j = 0; j < disp[i].length; j++) {
var selector = i + "-" + j;
$('#maze > tbody').append("<td id='" + selector + "'> </td>");
if (disp[i][j][0] == 0) {
$('#' + selector).css('border-top', '2px solid black');
}
if (disp[i][j][1] == 0) {
$('#' + selector).css('border-right', '2px solid black');
}
if (disp[i][j][2] == 0) {
$('#' + selector).css('border-bottom', '2px solid black');
}
if (disp[i][j][3] == 0) {
$('#' + selector).css('border-left', '2px solid black');
}
}
$('#maze > tbody').append("<tr>");
}
function newMaze(x, y) {
// Establish variables and starting grid
var totalCells = x * y;
var cells = new Array();
var unvis = new Array();
for (var i = 0; i < y; i++) {
cells[i] = new Array();
unvis[i] = new Array();
for (var j = 0; j < x; j++) {
cells[i][j] = [0, 0, 0, 0];
unvis[i][j] = true;
}
}
// Set a random position to start from
var currentCell = [Math.floor(Math.random() * y), Math.floor(Math.random() * x)];
var path = [currentCell];
unvis[currentCell[0]][currentCell[1]] = false;
var visited = 1;
// Loop through all available cell positions
while (visited < totalCells) {
// Determine neighboring cells
var pot = [
[currentCell[0] - 1, currentCell[1], 0, 2],
[currentCell[0], currentCell[1] + 1, 1, 3],
[currentCell[0] + 1, currentCell[1], 2, 0],
[currentCell[0], currentCell[1] - 1, 3, 1]
];
var neighbors = new Array();
// Determine if each neighboring cell is in game grid, and whether it has already been checked
for (var l = 0; l < 4; l++) {
if (pot[l][0] > -1 && pot[l][0] < y && pot[l][1] > -1 && pot[l][1] < x && unvis[pot[l][0]][pot[l][1]]) {
neighbors.push(pot[l]);
}
}
// If at least one active neighboring cell has been found
if (neighbors.length) {
// Choose one of the neighbors at random
next = neighbors[Math.floor(Math.random() * neighbors.length)];
// Remove the wall between the current cell and the chosen neighboring cell
cells[currentCell[0]][currentCell[1]][next[2]] = 1;
cells[next[0]][next[1]][next[3]] = 1;
// Mark the neighbor as visited, and set it as the current cell
unvis[next[0]][next[1]] = false;
visited++;
currentCell = [next[0], next[1]];
path.push(currentCell);
}
// Otherwise go back up a step and keep going
else {
currentCell = path.pop();
}
}
return cells;
}
function mazeReset() {
document.location.reload()
}
var gameComplete = false;
var mazeComplete = document.getElementById("mazeComplete");
function checkGameFinished() {
if (gameComplete === false) {
mazeComplete.style.visibility = 'hidden'
} else if (gameComplete === true) {
mazeComplete.style.visibility = 'visible'
}
}
checkGameFinished();
#maze {
border-collapse: collapse;
}
#maze td {
width: 20px;
height: 20px;
}
canvas {
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="maze">
<tbody></tbody>
</table>
<br>
<span id="mazeComplete">Maze complete <button id="resetMaze" onclick="mazeReset()">New Maze</button> </span> Completed <span id="mazeCompletions">0</span>
I agree with #Constantin in general but your most "immediate" problem you have, where "the span is always visible" is because, in your fiddle at least, the <span> is not hidden at start.. you have to make it like:
`<span hidden id="mazeComplete">`
Then later on when the time comes you will set its visibility property like you do.
I am trying to append enemy_1 and enemy_2 in the <td> tags on my 6x7 table randomly.
I don't know how to solve this with random method or any other way.
// target -> all <td>
$('table').find('td');
// two individual enemies
var enemy_1 = $('<span>enemy_1</span>');
var enemy_2 = $('<span>enemy_2</span>');
here is my table
for (var i = 0; i < 7; i++) {
$("table").append("<tr></tr>");
}
for (var i = 0; i < 6; i++) {
$("table tr").append("<td style='background:#DDDDDD;height:50px;width:50px;'></td>");
}
$('table').prepend('<div>Start</div');
$('table').append('<div>End</div');
$('table div:last-child').css({
position :'absolute',
right: '0'
});
Here is a logic using Math.random() which will generate a random number, then we multiply it by 100 and round it, then if its a multiple of 2, we will get enemy_1 span else enemy_2.
Random logic taken from the below link.
SO Answer
// target -> all <td>
// $('table').find('td');
// two individual enemies
var enemy_1 = '<span>enemy_1</span>';
var enemy_2 = '<span>enemy_2</span>';
for (var i = 0; i < 7; i++) {
$("table").append("<tr></tr>");
}
for (var i = 0; i < 6; i++) {
$("table tr").append("<td style='background:#DDDDDD;height:50px;width:50px;'></td>");
}
$('table').prepend('<div>Start</div');
$('table').append('<div>End</div');
$('table div:last-child').css({
position: 'absolute',
right: '0'
});
//generate random number 1
var numberOne = 1,
numberTwo = 1;
do {
numberOne = Math.floor(Math.random() * 42) + 1;
} while (numberOne === numberTwo);
do {
numberTwo = Math.floor(Math.random() * 42) + 1;
} while (numberTwo === numberOne);
$('td').each(function(index) {
if (index === numberOne) {
$(this).append(enemy_1);
}
if (index === numberTwo) {
$(this).append(enemy_2);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table></table>
For some reason when I put use .innerHTML to change the text of the cell, the code never stops and stays within the last statement. How do I get the code to run how it's supposed to run and not stop within the last if statement.
w3.filterHTML = function(id, sel, filter) {
var a, b, c, i, ii, iii, hit;
var searchItem = document.getElementById('search-list');
var row = searchItem.insertRow(0);
var rows = searchItem.rows.length;
var cell = row.insertCell(0);
a = w3.getElements(id);
for (i = 0; i < a.length; i++) {
b = w3.getElements(sel);
for (ii = 0; ii < b.length; ii++) {
hit = 0;
if (b[ii].innerHTML.toUpperCase().indexOf(filter.toUpperCase()) > -1) {
hit = 1;
}
c = b[ii].getElementsByTagName("*");
for (iii = 0; iii < c.length; iii++) {
if (c[iii].innerHTML.toUpperCase().indexOf(filter.toUpperCase()) > -1) {
hit = 1;
}
}
//Here is what you need to edit.
if (hit == 1) {
// b[ii].style.display = "";
console.log(filter);
var row = searchItem.insertRow(0);
var cell = row.insertCell(0);
document.getElementById("search-list").insertRow(0).insertCell(0).innerHTML = '<a class="list-group-item" href="#">Hello</a>';
} else {
// searchItem.b[ii].style.display = "none";
}
}
}
};
`
I copied the code from W3Schools (the filterHTML function).
Im having an arbitrary 2d array and each field has an id and a teamid (here illustrated as colors 1).
I want for every neighborhood an array with the ids
in it.
A neighborhood consists of fields with neighbors with the same teamid horizontally and vertically (not diagonally)
e.g.:
This is what i have:
array[0][0] = {id:1,teamId:1}
array[1][0] = {id:2,teamId:1}
array[2][0] = {id:3,teamId:0}
array[3][0] = {id:4,teamId:2}
array[4][0] = {id:5,teamId:2}
array[5][0] = {id:6,teamId:0}
array[0][1] = {id:7,teamId:1}
array[1][1] = {id:8,teamId:1}
array[2][1] = {id:9,teamId:1}
array[3][1] = {id:10,teamId:2}
array[4][1] = {id:11,teamId:2}
array[5][1] = {id:12,teamId:0}
//and so on..
This is what i want:
neighborhood[1] = [1,2,7,8,9,13,14]
neighborhood[2] = [4,5,10,11]
neighborhood[3] = [16,22,23,24,29,30]
neighborhood[4] = [25,31,32,37,38]
neighborhood[5] = [35,41]
I am not searching for the images, but for the array
neighborhood
thanks in advance!
You can use the logic from dots and block games. A block belongs to a player if he has surrounded it with the walls. So, you need for each cell also 4 walls except for the outer cells. To test if a cell is closed you can use 4 class variables:
var Block = function() {
this.isclosed=0;
this.left=0;
this.top=0;
this.right=0;
this.bottom=0;
return this;
}
Block.prototype = {
isClosed : function () {
if (this.isclosed==true) {
return false;
} else if (this.left && this.top && this.right && this.bottom) {
this.isclosed=true;
return true;
} else {
return this.left && this.top && this.right && this.bottom;
}
}
}
You can try my implementations of dots and blocks game # https://dotsgame.codeplex.com/.
The method for solving this issue is refered as Connected Component Labelling
A similar question was asked once before from which i have my solution:
// matrix dimensions
var row_count = 20;
var col_count = 20;
var numOfTeams = 2;
// the input matrix
var m = [];
// the labels, 0 means unlabeled
var label = [];
var source = document.getElementById("source");
for (var i = 0; i < row_count; i++) {
var row = source.insertRow(0);
m[i] = [];
label[i] = [];
for (var j = 0; j < col_count; j++) {
//m[i][j] = Math.round(Math.random());
m[i][j] = getRandomInt(0, numOfTeams + 1);
label[i][j] = 0;
var cell1 = row.insertCell(0);
cell1.innerHTML = m[i][j];
}
}
// direction vectors
var dx = [1, 0, -1, 0];
var dy = [0, 1, 0, -1];
function dfs(x, y, current_label, team) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y] || team != m[x][y]) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// recursively mark the neighbors
for (var direction = 0; direction < 4; ++direction) {
dfs(x + dx[direction], y + dy[direction], current_label, team);
}
}
function find_components() {
var component = 0;
for (var i = 0; i < row_count; ++i) {
for (var j = 0; j < col_count; ++j) {
if (!label[i][j] && m[i][j]) dfs(i, j, ++component, m[i][j]);
}
}
}
find_components();
var result = document.getElementById("result");
for (var i in label) {
var string = ""
var row = result.insertRow(0);
for (var j in label[i]) {
string += label[i][j] + " "
var cell1 = row.insertCell(0);
cell1.innerHTML = label[i][j];
}
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
table tr td {
min-width: 14px
}
<div style="float:left">
<table id="source"></table>
</div>
<div style="float:right">
<table id="result"></table>
</div>