## JavaScript Minesweeper - Opening whole mine-free area at once not working properly (flood-fill) - javascript

### A customized swap fails in bubbleSort

```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;
}
background : #2d2d47;
}
button {
border : 3px solid #29293a;
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;
margin-left : .2rem;
color : #5f5fc2;
}
<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>
<div id="moving-bars"></div>```

### How to display XML content in HTML file with Javascript

```This is my xml code . I want to display the contents in a html page with Javascript.
<Price>265000</Price>
<catalogueDescription>Extremely profitable (Sales £500k, GP £182k) business</catalogueDescription>
<keyfeature1>
</keyfeature1>
<keyfeature2>
Consistently high levels of turnover and profitability over last 5 years
</keyfeature2>
<broker bfsRef="1771" ref="003">Birmingham South, Wolverhampton & West Midlands</broker>
<tenure>freehold</tenure>
<Price>1200000</Price>
<reasonForSale>This is a genuine retirement sale.</reasonForSale>
<turnoverperiod>Annual</turnoverperiod>
<established>28</established>
<catalogueDescription>This well-located and long-established serviced office</catalogueDescription>
<underOffer>No</underOffer>
<keyfeature1>other connections</keyfeature1>
<keyfeature2> Investment Opportunity</keyfeature2>
<keyfeature3>Over 6,000 sq.ft.</keyfeature3>
<keyfeature4>Well-maintained </keyfeature4>
<keyfeature5>In-house services & IT provided</keyfeature5>
This is the original xml file https://alpha.business-sale.com/bfs.xml I have just took a short portion to describe the situation.
Requirements
Print a row for every <business> element
For every <business> pick some specific child element and print column only for those element.( Not all ). For an example in this case I only want to print the value for <advertHeader> ; <Price> and <description> and want to ignore other elements.
Only print the row those <business> where value of <Price> is > 10000 . if it is then less than 10000 do not print that row
pagination after every 10 row
This is the html table
<table id="MainTable"><tbody id="BodyRows"></tbody></table>
And this is the javascript code that i have tried .
getRows();
});
function getRows() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("get", "2l.xml", true);
if (this.readyState == 4 && this.status == 200) {
showResult(this);
}
};
xmlhttp.send(null);
}
function showResult(xmlhttp) {
var xmlDoc = xmlhttp.responseXML.documentElement;
removeWhitespace(xmlDoc);
var outputResult = document.getElementById("BodyRows");
}
var theTable = tableNode.parentNode;
var newRow, newCell, i;
console.log ("Number of nodes: " + xmlNodes.length);
for (i=0; i<xmlNodes.length; i++) {
newRow = tableNode.insertRow(i);
newRow.className = (i%2) ? "OddRow" : "EvenRow";
for (j=0; j<xmlNodes[i].childNodes.length; j++) {
newCell = newRow.insertCell(newRow.cells.length);
if (xmlNodes[i].childNodes[j].firstChild) {
newCell.innerHTML = xmlNodes[i].childNodes[j].firstChild.nodeValue;
} else {
newCell.innerHTML = "-";
}
console.log("cell: " + newCell);
}
}
theTable.appendChild(tableNode);
}
function removeWhitespace(xml) {
var loopIndex;
for (loopIndex = 0; loopIndex < xml.childNodes.length; loopIndex++)
{
var currentNode = xml.childNodes[loopIndex];
if (currentNode.nodeType == 1)
{
removeWhitespace(currentNode);
}
if (!(/\S/.test(currentNode.nodeValue)) && (currentNode.nodeType == 3))
{
xml.removeChild(xml.childNodes[loopIndex--]);
}
}
}
But this code prints columns for all the nodes under <business> element. And the number of child elements under <business> are different . So the result comes like this
I dont want that. I want to only display the value of specific nodes under <business> element (in this case only include <advertHeader> ; <Price> and <description> ) so that the number of columns are equal in every row. How to do that?
```
```Try finding the <business>-element with the most values and build your table around that. Here's an example snippet that does that for the data you presented.
{
const xml = new DOMParser()
.parseFromString(getData(), `text/xml`);
// the nodeNames will be the header. While we're at it,
// we can count the number of headers (len) for later use
[...v.querySelectorAll(`*`)]
.map( v => v.nodeName) )
.map( v => ( {len: v.length, headers: v} )
);
// now determine the longest header using a reducer
.reduce( (acc, v) => v.len > acc.len ? v : acc, {len: 0});
// utility to create a tablecell/header and append it to a row
const createCell = (rowToAppendTo, cellType, value) => {
const cell = document.createElement(cellType);
cell.innerHTML = value;
rowToAppendTo.appendChild(cell);
}
// utility to create a datarow and append it to a table
const createDataRow = (tableToAppendTo, businessElem) => {
const row = document.createElement(`tr`);
const rowValues = [];
// create values using the businessElemWithMostNodes order
rowValues.push(valueElem ? valueElem.innerHTML : `-`);
});
rowValues.forEach( v => createCell(row, `td`, v) );
tableToAppendTo.appendChild(row);
};
// now we know enough to create the table
const table = document.createElement(`table`);
// next create and append the rows
// finally, append the table to document.body
document.body.appendChild(table);
function getData() {
return `
<Price>265000</Price>
<catalogueDescription>Extremely profitable (Sales £500k, GP £182k) business</catalogueDescription>
<keyfeature1>
</keyfeature1>
<keyfeature2>
Consistently high levels of turnover and profitability over last 5 years
</keyfeature2>
<broker bfsRef="1771" ref="003">Birmingham South, Wolverhampton & West Midlands</broker>
<tenure>freehold</tenure>
<Price>1200000</Price>
<reasonForSale>This is a genuine retirement sale.</reasonForSale>
<turnoverperiod>Annual</turnoverperiod>
<established>28</established>
<catalogueDescription>This well-located and long-established serviced office</catalogueDescription>
<underOffer>No</underOffer>
<keyfeature1>other connections</keyfeature1>
<keyfeature2> Investment Opportunity</keyfeature2>
<keyfeature3>Over 6,000 sq.ft.</keyfeature3>
<keyfeature4>Well-maintained </keyfeature4>
<keyfeature5>In-house services & IT provided</keyfeature5>
}
}
body {
margin: 1rem;
font: 12px/15px normal consolas, verdana, arial;
}
.hidden {
display: none;
}
th {
background-color: black;
color: white;
border: 1px solid transparent;
text-align: left;
}
td {
border: 1px solid #c0c0c0;
vertical-align: top;
}```

### Checking function for sliding puzzle javascript

```I created a sliding puzzle with different formats like: 3x3, 3x4, 4x3 and 4x4. When you run my code you can see on the right side a selection box where you can choose the 4 formats. The slidingpuzzle is almost done. But I need a function which checks after every move if the puzzle is solved and if that is the case it should give out a line like "Congrantulations you solved it!" or "You won!". Any idea how to make that work?
In the javascript code you can see the first function loadFunc() is to replace every piece with the blank one and the functions after that are to select a format and change the format into it. The function Shiftpuzzlepieces makes it so that you can move each piece into the blank space. Function shuffle randomizes every pieces position. If you have any more question or understanding issues just feel free to ask in the comments. Many thanks in advance.
Since I don't have enough reputation I will post a link to the images here: http://imgur.com/a/2nMlt . These images are just placeholders right now.
Here is the jsfiddle:
http://jsfiddle.net/Cuttingtheaces/vkyxgwo6/19/
```
```As always, there is a "hacky", easy way to do this, and then there is more elegant but one that requires significant changes to your code.
Hacky way
To accomplish this as fast and dirty as possible, I would go with parsing id-s of pieces to check if they are in correct order, because they have this handy pattern "position" + it's expected index or "blank":
function isFinished() {
var puzzleEl = document.getElementById('slidingpuzzleContainer').children[0];
// convert a live list of child elements into regular array
var pieces = [].slice.call(puzzleEl.children);
return pieces
.map(function (piece) {
return piece.id.substr(8); // strip "position" prefix
})
.every(function (id, index, arr) {
if (arr.length - 1 == index) {
// last peace, check if it's blank
return id == "blank";
}
// check that every piece has an index that matches its expected position
return index == parseInt(id);
});
}
Now we need to check it somewhere, and naturally the best place would be after each move, so shiftPuzzlepieces() should be updated to call isFinished() function, and show the finishing message if it returns true:
function shiftPuzzlepieces(el) {
// ...
if (isFinished()) {
}
}
And voilà: live version.
How would I implement this game
For me, the proper way of implementing this would be to track current positions of pieces in some data structure and check it in similar way, but without traversing DOM or checking node's id-s. Also, it would allow to implement something like React.js application: onclick handler would mutate current game's state and then just render it into the DOM.
Here how I would implement the game:
/**
* Provides an initial state of the game
* with default size 4x4
*/
function initialState() {
return {
x: 4,
y: 4,
started: false,
finished: false
};
}
/**
* Inits a game
*/
function initGame() {
var gameContainer = document.querySelector("#slidingpuzzleContainer");
var gameState = initialState();
initFormatControl(gameContainer, gameState);
initGameControls(gameContainer, gameState);
// kick-off rendering
render(gameContainer, gameState);
}
/**
* Handles clicks on the container element
*/
function initGameControls(gameContainer, gameState) {
if (!gameState.started || gameState.finished) {
// game didn't started yet or already finished, ignore clicks
return;
}
if (event.target.className.indexOf("piece") == -1) {
// click somewhere not on the piece (like, margins between them)
return;
}
// try to move piece somewhere
movePiece(gameState, parseInt(event.target.dataset.index));
// check if we're done here
checkFinish(gameState);
// render the state of game
render(gameContainer, gameState);
event.stopPropagation();
return false;
});
}
/**
* Checks whether game is finished
*/
function checkFinish(gameState) {
gameState.finished = gameState.pieces.every(function(id, index, arr) {
if (arr.length - 1 == index) {
// last peace, check if it's blank
return id == "blank";
}
// check that every piece has an index that matches its expected position
return index == id;
});
}
/**
* Moves target piece around if there's blank somewhere near it
*/
function movePiece(gameState, targetIndex) {
if (isBlank(targetIndex)) {
// ignore clicks on the "blank" piece
return;
}
var blankPiece = findBlankAround();
if (blankPiece == null) {
// nowhere to go :(
return;
}
swap(targetIndex, blankPiece);
function findBlankAround() {
var up = targetIndex - gameState.x;
if (targetIndex >= gameState.x && isBlank(up)) {
return up;
}
var down = targetIndex + gameState.x;
if (targetIndex < ((gameState.y - 1) * gameState.x) && isBlank(down)) {
return down;
}
var left = targetIndex - 1;
if ((targetIndex % gameState.x) > 0 && isBlank(left)) {
return left;
}
var right = targetIndex + 1;
if ((targetIndex % gameState.x) < (gameState.x - 1) && isBlank(right)) {
return right;
}
}
function isBlank(index) {
return gameState.pieces[index] == "blank";
}
function swap(i1, i2) {
var t = gameState.pieces[i1];
gameState.pieces[i1] = gameState.pieces[i2];
gameState.pieces[i2] = t;
}
}
/**
* Handles form for selecting and starting the game
*/
function initFormatControl(gameContainer, state) {
var formatContainer = document.querySelector("#formatContainer");
var formatSelect = formatContainer.querySelector("select");
var formatApply = formatContainer.querySelector("button");
formatApply.disabled = false;
});
var rawValue = event.target.format.value;
var value = rawValue.split("x");
// update state
state.x = parseInt(value[0], 10);
state.y = parseInt(value[1], 10);
state.started = true;
state.pieces = generatePuzzle(state.x * state.y);
// render game
render(gameContainer, state);
event.preventDefault();
return false;
});
}
/**
* Renders game's state into container element
*/
function render(container, state) {
var numberOfPieces = state.x * state.y;
updateClass(container, state.x, state.y);
clear(container);
var containerHTML = "";
if (!state.started) {
for (var i = 0; i < numberOfPieces; i++) {
containerHTML += renderPiece("", i) + "\n";
}
} else if (state.finished) {
containerHTML = "<div class='congratulation'><h2 >You won!</h2><p>Press 'Play!' to start again.</p></div>";
} else {
containerHTML = state.pieces.map(renderPiece).join("\n");
}
container.innerHTML = containerHTML;
function renderPiece(id, index) {
return "<div class='piece' data-index='" + index + "'>" + id + "</div>";
}
function updateClass(container, x, y) {
container.className = "slidingpuzzleContainer" + x + "x" + y;
}
function clear(container) {
container.innerHTML = "";
}
}
/**
* Generates a shuffled array of id-s ready to be rendered
*/
function generatePuzzle(n) {
var pieces = ["blank"];
for (var i = 0; i < n - 1; i++) {
pieces.push(i);
}
return shuffleArray(pieces);
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
}
body {
font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Helvetica, Arial, sans-serif;
font-size: 12px;
color: #000;
}
#formatContainer {
position: absolute;
top: 50px;
left: 500px;
}
#formatContainer label {
display: inline-block;
max-width: 100%;
margin-bottom: 5px;
}
#formatContainer select {
display: block;
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
}
#formatContainer button {
display: inline-block;
width: 100%;
}
.piece {
width: 96px;
height: 96px;
margin: 1px;
float: left;
border: 1px solid black;
}
.slidingpuzzleContainer3x3,
.slidingpuzzleContainer3x4,
.slidingpuzzleContainer4x3,
.slidingpuzzleContainer4x4 {
position: absolute;
top: 50px;
left: 50px;
border: 10px solid black;
}
.slidingpuzzleContainer3x3 {
width: 300px;
height: 300px;
}
.slidingpuzzleContainer3x4 {
width: 300px;
height: 400px;
}
.slidingpuzzleContainer4x3 {
width: 400px;
height: 300px;
}
.slidingpuzzleContainer4x4 {
width: 400px;
height: 400px;
}
.congratulation {
margin: 10px;
}
}
<div id="slidingpuzzleContainer"></div>
<form id="formatContainer">
<label for="format">select format:</label>
<select name="format" id="format" size="1">
<option value="" selected="true" disabled="true"></option>
<option value="3x3">Format 3 x 3</option>
<option value="3x4">Format 3 x 4</option>
<option value="4x3">Format 4 x 3</option>
<option value="4x4">Format 4 x 4</option>
</select>
<button type="submit" disabled="true">Play!</button>
</form>
</body>
Here we have the initGame() function that starts everything. When called it will create an initial state of the game (we have default size and state properties to care about there), add listeners on the controls and call render() function with the current state.
initGameControls() sets up a listener for clicks on the field that will 1) call movePiece() which will try to move clicked piece on the blank spot if the former is somewhere around, 2) check if after move game is finished with checkFinish(), 3) call render() with updated state.
Now render() is a pretty simple function: it just gets the state and updates the DOM on the page accordingly.
Utility function initFormatControl() handles clicks and updates on the form for field size selection, and when the 'Play!' button is pressed will generate initial order of the pieces on the field and call render() with new state.
The main benefit of this approach is that almost all functions are decoupled from one another: you can tweak logic for finding blank space around target piece, to allow, for example, to swap pieces with adjacent ids, and even then functions for rendering, initialization and click handling will stay the same.
```
```\$(document).on('click','.puzzlepiece', function(){
var count = 0;
var imgarray = [];
var test =[0,1,2,3,4,5,6,7,8,'blank']
\$('#slidingpuzzleContainer img').each(function(i){
var imgalt = \$(this).attr('alt');
imgarray[i] = imgalt;
count++;
});
var is_same = (imgarray.length == test.length) && imgarray.every(function(element, index) {
return element === array2[index];
});
console.log(is_same); ///it will true if two array is same
});
try this... this is for only 3*3.. you pass the parameter and makethe array value as dynamically..```

### javascript game ( 3 in line ) line check logic

```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>
<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;
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>
<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) {
return false;
} else
if (cell[0].innerHTML == cell[3].innerHTML && cell[3].innerHTML == cell[6].innerHTML) {
return false;
}
},
checkMiddle: function () {
// check vertical and horizontal lines from the center
},
checkLast: function () {
// check last horizontal and right edge vertical
}
};
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))
{
}
// Check for vertical matches
if (isVerticalFirstCell
&& bruno.checkCells(
cells, i,
(i + 7), 3))
{
}
// Check for diagonal matches
if (isTopLeftCorner
&& bruno.checkCells(
cells, i,
(i + 9), 4))
{
}
if (isTopRightCorner
&& bruno.checkCells(
cells, i,
(i + 5), 2))
{
}
}
},
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;
}
};```

### Wrapping Sentences within <p> Tags with <span>'s, But Keep Other Tags

```To give you an idea of what I need, I have been using the below code to parse content within tags and wrap each sentence within tags so I can then interact with sentences on a page.
\$('p').each(function() {
var sentences = \$(this)
.text()
.replace(/(((?![.!?]['"]?\s).)*[.!?]['"]?)(\s|\$)/g,
'<span class="sentence">\$1</span>\$3');
\$(this).html(sentences);
});
However, the following line demonstrates my problem:
<p>This is a link and it is removed with the above code! Here is another sentence.</p>
Nested tags such as <a>, <img> etc...within <p> tags that I'm searching through are removed with the code that I'm using. I need to keep these tags intact, so the content stays the same within the <p> tags.
I need:
<p><span class="sentence">This is a link and it is removed with the above code!</sentence><sentence>Here is another sentence.</sentence></p>
After reading this barn-burner about parsing HTML with regex, I've concluded that I need to use a combo of an HTML parser of some sort to traverse through sub-tags within a <p> tag, and then use a regex to find the sentences. I think the regex I have listed above should work for most of my uses, if that helps.
So: how should I do it?
```
```It is really difficult to tokenise language, reliably, into sentences and that is without the added complexity of throwing html into the equation. There are some applications etc out there that attempt to deal with Natural Language Processing, an example would be the Stanford Tokenizer with runs on Java (not Javascript)
And as people keep mentioning, a regex is not the solution to this problem, language is not regular so don't expect a Regular Expression only solution.
There is a question here on SO, Basic NLP in CoffeeScript or JavaScript — Punkt tokenizaton, simple trained Bayes models — where to start? Which I think summarises things fairly simply for Javascript.
Anyway, to at least give you a little something that you could play with, I knocked up a little code for you. This works reasonable well until the markup/language begins to resemble anything slightly complex or different, but ultimately fails the mark by a long way. But, it may be enough for what you need, I don't know.
CSS
.emphasis {
font-style: italic;
}
.bold {
font-weight: bold;
}
.emphasis.bold {
font-style: italic;
font-weight: bold;
}
.unidentified {
background-color: pink;
}
.sentence0 {
background-color: yellow;
}
.sentence1 {
background-color: green;
}
.sentence2 {
background-color: red;
}
.whitespace {
white-space: pre;
background-color: blue;
}
Javascript
/*jslint maxerr: 50, indent: 4, browser: true */
(function () {
"use strict";
var rxOpen = new RegExp("<[^\\/].+?>"),
rxClose = new RegExp("<\\/.+?>"),
rxWhitespace = new RegExp("^\\s+?"),
rxSupStart = new RegExp("^<sup\\b[^>]*>"),
rxSupEnd = new RegExp("<\/sup>"),
sentenceEnd = [],
color = 0,
rxIndex;
sentenceEnd.push(new RegExp("[^\\d][\\.!\\?]+"));
sentenceEnd.push(new RegExp("(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*?\$)"));
sentenceEnd.push(new RegExp("(?![^\\(]*?\\))"));
sentenceEnd.push(new RegExp("(?![^\\[]*?\\])"));
sentenceEnd.push(new RegExp("(?![^\\{]*?\\})"));
sentenceEnd.push(new RegExp("(?![^\\|]*?\\|)"));
//sentenceEnd.push(new RegExp("(?![^\\\\]*?\\\\)"));
//sentenceEnd.push(new RegExp("(?![^\\/.]*\\/)")); // all could be a problem, but this one is problematic
rxIndex = new RegExp(sentenceEnd.reduce(function (previousValue, currentValue) {
return previousValue + currentValue.source;
}, ""));
function indexSentenceEnd(html) {
var index = html.search(rxIndex);
if (index !== -1) {
index += html.match(rxIndex)[0].length - 1;
}
return index;
}
function pushSpan(array, className, string, classNameOpt) {
if (className === "sentence") {
className += color % 2;
if (classNameOpt) {
className += " " + classNameOpt;
}
color += 1;
}
array.push('<span class="' + className + '">' + string + '</span>');
}
var sup = html.search(rxSupStart),
end = 0,
last;
if (sup !== -1) {
end = html.search(rxSupEnd);
if (end !== -1) {
last = array.pop();
end = end + 6;
array.push(last.slice(0, -7) + html.slice(0, end) + last.slice(-7));
}
}
return html.slice(end);
}
var whitespace = html.search(rxWhitespace),
count = 0;
if (whitespace !== -1) {
count = html.match(rxWhitespace)[0].length;
pushSpan(array, "whitespace", html.slice(0, count));
}
return html.slice(count);
}
function paragraphIsSentence(html, array) {
var index = indexSentenceEnd(html);
if (index === -1 || index === html.length) {
pushSpan(array, "sentence", html, "paragraphIsSentence");
html = "";
}
return html;
}
function paragraphNoMarkup(html, array) {
var open = html.search(rxOpen),
index = 0;
if (open === -1) {
index = indexSentenceEnd(html);
if (index === -1) {
index = html.length;
}
pushSpan(array, "sentence", html.slice(0, index += 1), "paragraphNoMarkup");
}
return html.slice(index);
}
function sentenceUncontained(html, array) {
var open = html.search(rxOpen),
index = 0,
close;
if (open !== -1) {
index = indexSentenceEnd(html);
if (index === -1) {
index = html.length;
}
close = html.search(rxClose);
if (index < open || index > close) {
pushSpan(array, "sentence", html.slice(0, index += 1), "sentenceUncontained");
} else {
index = 0;
}
}
return html.slice(index);
}
function sentenceContained(html, array) {
var open = html.search(rxOpen),
index = 0,
close,
count;
if (open !== -1) {
index = indexSentenceEnd(html);
if (index === -1) {
index = html.length;
}
close = html.search(rxClose);
if (index > open && index < close) {
count = html.match(rxClose)[0].length;
pushSpan(array, "sentence", html.slice(0, close + count), "sentenceContained");
index = close + count;
} else {
index = 0;
}
}
return html.slice(index);
}
function anythingElse(html, array) {
pushSpan(array, "sentence2", html, "anythingElse");
return "";
}
function guessSenetences() {
var paragraphs = document.getElementsByTagName("p");
Array.prototype.forEach.call(paragraphs, function (paragraph) {
var html = paragraph.innerHTML,
length = html.length,
array = [],
safety = 100;
while (length && safety) {
if (html.length === length) {
if (html.length === length) {
html = paragraphIsSentence(html, array);
if (html.length === length) {
html = paragraphNoMarkup(html, array);
if (html.length === length) {
html = sentenceUncontained(html, array);
if (html.length === length) {
html = sentenceContained(html, array);
if (html.length === length) {
html = anythingElse(html, array);
}
}
}
}
}
}
length = html.length;
safety -= 1;
}
paragraph.innerHTML = array.join("");
});
}
guessSenetences();
}());
On jsfiddle
```
```you need to use .html() instead of .text() if you want to keep tags intact.
Check below code and let me know if it doesn't work out.
DEMO
\$('p').each(function() {
var sentences = \$(this)
.html()
.replace(/(((?![.!?]['"]?\s).)*[.!?]['"]?)(\s|\$)/g,
'<span class="sentence">\$1</span>\$3');
\$(this).html(sentences);
});```