How can I change the order of the box numbers? - javascript

The order of the numbers in my box is as follows:
function boxNumbers(){
let boxes = document.querySelectorAll('.box')
boxes.forEach((box,i)=>{
if(String(i).length==1 || (String(i).length==2 && Number(String(i)[0]))%2==0){
//box.innerHTML = `${100-i}, i=${i}`
box.innerHTML = 100-i
}
else{
box.innerHTML = String(Number(`${9-Number(String(i)[0])}${String(i)[1]}`)+ 1)
}
})
}
how can I change it to look like this:

You can use this:
function boxNumbers() {
let boxes = document.querySelectorAll('.box');
let n = Math.sqrt(boxes.length);
[...boxes].reverse().forEach((box, i) => {
box.textContent = i % (n * 2) < n ? i + 1 : i + n - 2*(i % n);
})
}
With the assignment to n you make it a bit more generic -- still assuming your table is square. By reversing the iteration, you eliminate the need for the 100- subtraction. What remains is a formula that detects whether we're on a row with a reverse sequence or not, and adapts the number accordingly. The number "1" will always be in the bottom-right corner:
function boxNumbers() {
let boxes = document.querySelectorAll('.box');
let n = Math.sqrt(boxes.length);
[...boxes].reverse().forEach((box, i) => {
box.textContent = i % (n * 2) < n ? i + 1 : i + n - 2*(i % n);
})
}
// Utility to create the table
function fillTable(table, n) {
for (let i = 0; i < n; i++) {
let row = table.insertRow();
for (let j = 0; j < n; j++) {
let cell = row.insertCell();
cell.className = "box";
}
}
}
// Example run with n=5. Adapt as needed
let n = 5
fillTable(document.querySelector('table'), n);
boxNumbers();
table { border-collapse: collapse }
td { border: 1px solid ; width: 20px; height: 20px; text-align: center }
<table></table>

Here is a function which builds a bi-dimensional array and appends it as a table (row/col) to a dom element. You can adapt it to your template as you wish.
Works with any base number, yours is 5
function buildMatrix(baseNumber){
var flip = false;
var countDownNumber = baseNumber * baseNumber;
var currNumber = countDownNumber;
var matrix = "";
for(i = 0; i < baseNumber; i++) {
if(i !== 0){
currNumber = (flip)? countDownNumber + 1 - baseNumber : countDownNumber;
}
matrix += "<tr>";
for(j = 0; j < baseNumber; j++){
matrix += "<td>" + currNumber + "</td>";
// depending on the direction (flip) we increment or decrement
(flip)? currNumber++ : currNumber--;
countDownNumber--;
}
// change direction at the end of a row
flip = !flip;
matrix += "</tr>";
}
return matrix;
}
var baseSquareNumber = 11; // here you put 5
var matrixHtml = buildMatrix(baseSquareNumber);
document.getElementById("matrix").innerHTML = matrixHtml;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<table id="matrix">
</table>
</body>
</html>

Related

Change the colour of cells with prime numbers in a dynamic table created with javascript

So far I have created the code to generate a table that has the number of cells that is defined by the user. In addition to this, the cells which have the prime numbers in it, must be coloured in a different colour. I have also included a function to find the prime numbers, but the approach I took to create the table, doesn't give me an option to implement the function onto the html body.
I would really appreciate any help.
Here's my code..
<html>
<head>
<style>
table{width: 70%;}
</style>
<script>
const numString= window.prompt("What is the loop maximum.? (between 1 and 500)")
let num=parseInt(numString);
if(num<0 || num>500)
{
window.alert("Warning! Must be between 1 and 500. Setting to default
100")
num=100
}
function isPrime(num)
{
for(var i=2; i< num; i++)
if(num % i ===0) return false;
return num>1;
}
</script>
</head>
<body>
<h1>Javascript Loops and Functions</h1><br>
<script>
document.write("<table border=1>");
let rows = num % 10 >= 0 && num % 10 <= 10 ? num / 10 + 1 : num / 10;
let count = 0;
for (row = 1; row <= rows; row++) {
document.write("<tr>");
for (let i = 1; i <= 10; i++) {
if (count >= num+1) break;
document.write("<td>" + count + "</td>");
count++;
}
document.write("</tr>");
}
document.write("</table>");
</script>
</body>
You can use a CSS class to give colors. For instance prime_true could be the class for prime numbers and prime_false for non-primes.
It is not so good practice to use document.write for such a purpose. So I would suggest to have an empty table element in your HTML, and then use loops to populate that table with rows and cells:
function isPrime(num) {
for(var i=2; i< num; i++)
if(num % i ===0) return false;
return num>1;
}
let table = document.querySelector("table");
for (let line = 1; line <= 500; line += 10) {
let row = table.insertRow();
for (let i = line; i < line + 10; i++) {
let td = row.insertCell();
td.textContent = i;
td.className = "prime_" + isPrime(i);
}
}
table { width: 70%; }
td { border: 1px solid; text-align: center }
.prime_true { background: orange }
.prime_false { background: lightgrey }
<h1>Javascript Loops and Functions</h1><br>
<table></table>
NB: this script should be in a script element that is put below the table element.
for (let i = 1; i <= 10; i++) {
if (count >= num+1) break;
if(isPrime(count)){
document.write("<td style='background-color:red'>" + count + "</td>");
} else {
document.write("<td>" + count + "</td>");
}
count++;
}

Appending to DOM after the loop

I would like to know how to append to the DOM just once after these nested loops.
Also, the variable letters is dynamic, so I would need to 'reset' my appended grid when a new string is passed to letters
let letters = "abcdefghijkl"
for (let i = 0; i < letters.length; i++) {
var musicRowID = `${letters.charAt(i)}01`;
$("#music-grid").append(`<div id="music-row-${musicRowID}" class="row no-gutters"></div>`);
for (let j = 1; j <= 12; j++) {
var columnID = letters.charAt(i) + (j < 10 ? "0" : "") + j;
$(`#music-row-${musicRowID}`).append(
`<div class="col-1"><button id="${columnID}" class="btn bar song">${columnID.toUpperCase()}</button></div>`
);
}
}
Thank you in advance!
EDIT
After the answer from T.J. Crowder I tried to incorporate my code to be able to populate my grid from the inputs, but when I unselect one of the inputs, that row isn't cleared.
let letters = 'abcdefghijkl';
let html = "";
$(".list-checkbox-item").change(function() {
let chosenLetters = $(this).val();
if ($(this).is(":checked")) {
arrayOfChoices.push(chosenLetters);
} else {
arrayOfChoices.splice($.inArray(chosenLetters, arrayOfChoices), 1);
}
letters = arrayOfChoices.sort().join(""); // Gives me a string with chosen letters ordered alphabetically
console.log(
`This is my string in var 'letters' ordered alphabetically (Need to clear grid after each instantiation or append after the loop): %c${letters}`,
"color: red; font-weight: bold; font-size: 16px"
);
for (let i = 0; i < letters.length; i++) {
var musicRowID = `${letters.charAt(i)}01`;
html += `<div id="music-row-${musicRowID}" class="row no-gutters">`; // *** No `</div>` yet
for (let j = 1; j <= 12; j++) {
var columnID = letters.charAt(i) + (j < 10 ? "0" : "") + j;
html += `<div class="col-1"><button id="${columnID}" class="btn bar song">${columnID.toUpperCase()}</button></div>`;
}
html += "</div>";
}
$("#music-grid").html(html);
});
What am I doing wrong?
Assuming #music-grid is empty before you run this code the first time, build up the HTML in a string and then use html() to replace the contents of #music-grid rather than appending to it:
let html = "";
for (let i = 0; i < letters.length; i++) {
var musicRowID = `${letters.charAt(i)}01`;
html += `<div id="music-row-${musicRowID}" class="row no-gutters">`; // *** No `</div>` yet
for (let j = 1; j <= 12; j++) {
var columnID = letters.charAt(i) + (j < 10 ? "0" : "") + j;
html +=
`<div class="col-1"><button id="${columnID}" class="btn bar song">${columnID.toUpperCase()}</button></div>`;
}
html += "</div>";
}
$("#music-grid").html(html);
You also see people building up the HTML in an array and using array.join("") at the end to get a single string, but with modern JavaScript engines it's really a wash either way...

Detecting 5 in a row

I am making a game of tic tac toe 5 in a row. I have the grid where whenever you click on a square, it records a "coordinate" of [row,column] in the certain color of the dot. I'm currently not sure how to use the 'coordinates' to detect a five in a row of either color and just prints out a message.
Note: If 5 in a row gets tedious with the copy and pasting of previous code or such, a 3 in a row will also work for me and I will just modify it into a 5 in a row. Also when viewing the code snippet below, use the full screen mode.
Code I have so far:
var white=true;
function generateGrid( rows, cols ) {
var grid = "<table>";
for ( row = 1; row <= rows; row++ ) {
grid += "<tr>";
for ( col = 1; col <= cols; col++ ) {
grid += "<td></td>";
}
grid += "</tr>";
}
return grid;
}
$( "#tableContainer" ).append( generateGrid( 10, 10) );
$( "td" ).click(function() {
$(this).css('cursor','default');
var index = $( "td" ).index( this );
var row = Math.floor( ( index ) / 10) + 1;
var col = ( index % 10) + 1;
var $td = $(this);
if ($td.data('clicked'))
return;
if (white===true){
var whi=[row,col];
console.log("white coord is "+whi);
} else {
var bla=[row,col];
console.log("black coord is "+bla);
}
$td.data('clicked', true);
$td.css('background-color', white ? 'white' : 'black');
white = !white;
});
html{
background-color:#7189ea;
}
td {
border: 1px solid;
width: 25px;
height: 25px;
border-radius:100%;
}
table {
border-collapse: collapse;
}
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="tableContainer"></div>
I've written a function that checks whether the last move wins the game. It basically loops the squares in every direction (and backwards) and looks for 5 in a row (the required length of a line).
var board = new Array();
var boardSize = 5;
var requiredLineLength = 5;
for (var r = 0; r < boardSize; r++) {
board[r] = new Array();
for (var c = 0; c < boardSize; c++) {
board[r][c] = 0;
}
}
var lineDirections = [
[0, 1], //horizontal
[1, 0], //vertical
[1, -1], //diagonal 1
[1, 1] //diagonal 2
];
//example usage:
board[0][0] = 1;
board[1][0] = 1;
board[2][0] = 1;
board[3][0] = 1;
board[4][0] = 1;
console.log(checkWin(1, [0, 0]));
// an empty square is marked with 0
// the players are marked with 1 and 2
// pl is the id of the player: either 1 or 2
// lastMove is an array of size 2, with the coordinates of the last move played, for example: [3, 1]
function checkWin(pl, lastMove) {
var boolWon = false;
for (var i = 0; i < lineDirections.length && !boolWon; i++) {
var shift = lineDirections[i];
var currentSquare = [lastMove[0] + shift[0], lastMove[1] + shift[1]];
var lineLength = 1;
while (lineLength < requiredLineLength && legalSquare(currentSquare) && board[currentSquare[0]][currentSquare[1]] === pl) {
lineLength++;
currentSquare[0] += shift[0];
currentSquare[1] += shift[1];
}
currentSquare = [lastMove[0] - shift[0], lastMove[1] - shift[1]];
while (lineLength < requiredLineLength && legalSquare(currentSquare) && board[currentSquare[0]][currentSquare[1]] === pl) {
lineLength++;
currentSquare[0] -= shift[0];
currentSquare[1] -= shift[1];
}
if (lineLength >= requiredLineLength)
boolWon = true;
}
return boolWon;
}
function legalSquare(square) {
return square[0] < boardSize && square[1] < boardSize && square[0] >= 0 && square[1] >= 0;
}
It's not fully tested so let me know if you encounter any problems or if you need any clarification on how this works.

How to append multiplication result of 2 vars in table cells?

I'm prompting the user to enter a number for row and another for column, then construct a table using the given numbers and numbering each cell accordingly.
However, I want my final result to be displayed as a multiplication table, like the image below:
multiplication table image
And here's what my code looks like so far:
var table = document.getElementById("table");
var temp = "<table border = 1 border-collapse = collapse>";
for (var i = 0; i < row; i++){
temp += "<tr>";
if (i == 0){
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (j+1) + "</td>";
}
} else{
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (i+1) + "</td>";
}
}
temp += "</tr>";
}
temp += "</table>";
table.innerHTML=temp;
That is nearly right already. What you are looking for is to put (i+1)*(j+1) in the second for statement.
I'm not sure how you get your user input. Prompt is not usually a great way to get input but because you said that's what you used the example below uses prompt. The problem with it is that it blocks everything else: not only your own webpage, but the entire browser. If you have not done so already, you might consider getting your user-inputted numbers from an HTML form.
You might also want input checking code. I've included it below in a full HTML/JS solution. It gives the user 3 chances to enter a number for both the row and the column. If the user fails to do so, it outputs an error message.
<html>
<head>
</head>
<body>
<div id='table'></div>
<script>
var table = document.getElementById('table');
var attemptCounter = 0;
var maxAttempts = 2;
var temp='<table border = 1 border-collapse = collapse>';
var row;
var column;
while ((typeof row !=='number' || attemptCounter <= maxAttempts) && isNaN(row) ){
var row = parseInt(prompt("Please enter the number of ROWS for your table:"),10);
if(typeof row ==='number' && !isNaN(row)){break;};
attemptCounter++;
}
if(attemptCounter >= maxAttempts+1){
table.innerHTML = 'Error: expected NUMBER for number of rows';
}
if(attemptCounter < maxAttempts+1){
attemptCounter = 0;
while ((typeof column !=='number' || attemptCounter <= maxAttempts) && isNaN(column) ){
var column = parseInt(prompt("Please enter the number of COLUMNS for your table:"),10);
if(typeof column ==='number' && !isNaN(column)){break;};
attemptCounter++;
}
if(attemptCounter < maxAttempts+1){
for (var i = 0; i < row; i++){
temp += "<tr>";
if (i == 0){
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (j+1) + "</td>";
}
} else {
for (var j = 0; j < column; j++){
temp += "<td height = 20 width = 40>" + (i+1)*(j+1) + "</td>";
}
}
temp += "</tr>";
}
temp += "</table>";
table.innerHTML=temp;
} else {
table.innerHTML = 'Error: expected NUMBER for number of columns';
}
}
</script>
</body>
</html>
Your code nearly works. If you change your (i+1) and (j+1) to (i * j) you'll see that the table created works, except for the first row and first column (as multiplying by 0 will always give 0).
However to deal with the multiplication with 0 in the first column and row there needs to be some conditional that checks if one of the values (either i or j are 0) and then changes the value to 1.
I've only changed what happens in your for loop.
for (var i = 0; i < row; i++){
temp += "<tr>";
for (var j = 0; j < column; j++){
// Here I have split your temp string.
temp += "<td height = 20 width = 40>";
if (i == 0 && j ==0){ // if both i and j are 0 then add a 0 to temp.
temp += 0;
} else {
// Multiply them together changing 0 to 1 (solving the 0's problem)
temp += (i == 0 ? 1 : i) * (j == 0 ? 1 : j);
}
temp += "</td>";
}
temp += "</tr>";
}
temp += "</table>";
table.innerHTML=temp;
i==0?1:i is a ternary operator which is just like a little if statement. It checks if i is 0 and if it evaluates to true it returns 1, otherwise it returns the value of i. Read more about it here
Putting it all together,
temp += (i==0?1:i) * (j==0?1:j) multiplies the values in the table together and also prevents multiplication with 0 in the headings.
Build HTML as string is not bad but it is better to work with DOM model. Here is an example.
<!DOCTYPE html>
<html>
<head>
<title>Build Table</title>
<meta charset="utf-8" />
<style type="text/css">
.tbl{border:solid 1px #ccc}
.tbl tr:first-child td,
.tbl td:first-child{background:#ccc;padding:4px}
</style>
<script type="text/javascript">
'use strict';
function buildTable() {
//get numbers from micro-form
var rows = document.getElementById('rows').value;
var cols = document.getElementById('cols').value;
//create table
var tbl = document.createElement('table');
tbl.className = 'tbl';//it is better then inline style
//note that HTML table has its own DOM model
var tr = tbl.insertRow(-1);//insert new row
//first row is special
tr.insertCell(-1).innerHTML = 'X';
//so treat it accordingly
for (var i = 1; i < cols; i++) {
tr.insertCell(-1).innerHTML = i;//insert new cell and set value inside
}
//remaining rows
for (i = 1; i < rows; i++) {
tr = tbl.insertRow(-1);
//first column is special
tr.insertCell(-1).innerHTML = i;
for (var j = 1; j < cols; j++) {
tr.insertCell(-1).innerHTML = i * j;
}
}
//well done. Place our table in a container
document.getElementById('table').appendChild(tbl);
}
</script>
</head>
<body>
<div>
Rows: <input type="number" id="rows" min="2" max="10" value="10" />
Columns: <input type="number" id="cols" min="2" max="10" value="10" />
<button onclick="buildTable()">Build Table</button>
</div>
<div id="table"></div>
</body>
</html>

Javascript css class based on random number

I have a 4x3 matrix where the class is set to blank (white background). I'm using
var rand = Math.floor(Math.random()*2 + 1);
and if its 1, the class is set to one (red background) and if its 2, the class is set to two (blue background). My code is suppose to make 6 links red and 6 links blue with the newgame function, however, sometimes a few of them are still white or there are not exactly 6 red or blue. You might need to refresh (not click new game button) to see what I mean
here it is live: https://dl.dropbox.com/u/750932/iPhone/risk.html
<!DOCTYPE html>
<html>
<head>
<title>RISK</title>
<style type="text/css" media="screen">
a:link, a:visited {color: #eee;border:3px solid #ccc;display:inline-block;margin:3px;text-decoration:none;padding:26px;}
.blank {background:#fff;}
.one {background: #7B3B3B;}
.two {background: #547980;}
#status {color: #eee;padding:1px;text-align:center}
.current {border:3px solid #000;}
p {margin:0 0 15px;padding:0;}
</style>
<script type="text/javascript" charset="utf-8">
var oneTurn = true;
var gameOver = false;
var numMoves = 0;
function newgame()
{
var status = document.getElementById('status');
var one = 0;
var two = 0;
numMoves = 0;
gameOver = false;
oneTurn = true;
status.innerHTML = 'Player One\'s turn';
for(var x = 0; x < 4; x++)
{
for(var y = 0; y < 3; y++)
{
var rand = Math.floor(Math.random()*2 + 1);
if(rand == 1 && one < 7)
{
document.getElementById('a' + x + '_' + y).setAttribute("class", "one");
one++;
console.log("one");
}
else if(rand == 2 && two < 7)
{
document.getElementById('a' + x + '_' + y).setAttribute("class", "two");
two++;
console.log("two");
}
document.getElementById('a' + x + '_' + y).innerHTML = Math.floor(Math.random()*5 + 1);
}
}
console.log(one);
console.log(two);
}
function current(selected)
{
var status = document.getElementById('status');
var value = selected.value;
}
</script>
<meta name="viewport" content="user-scalable=no, width=device-width" />
</head>
<body onload='newgame();'>
<p id="status" class="one">Player One's turn</p>
<br />
<br />
<br />
<br /><br />
<p><input type="button" id="newgame" value="New Game" onclick="newgame();" /></p>
</body>
</html>
Let me offer you a slightly different approach. Represent the board as an array of 12 integers.
Fill the first half of this array with one's and the second half with two's.
Shuffle the array
Loop through the array and update the DOM elements by converting the array index to the corresponding row and column in the matrix
// initialize the array
var board = [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2];
// shuffle the array
for(var j, x, i = board.length; i; j = parseInt(Math.random() * i),
x = board[--i], board[i] = board[j], board[j] = x);
// At this stage one's and two's will be randomly distributed
var row = -1;
for (var i = 0; i < board.length; i++) {
var class = board[i] == 1 ? 'one' : 'two';
var col = i % 4;
if (col == 0) row++;
var box = document.getElementById('a' + col + '_' + row);
if (box != null) {
box.setAttribute('class', class);
box.innerHTML = 1 + Math.floor(Math.random() * 5);
}
}
Read your code again:
if(rand == 1 && one < 7)
...
else if(rand == 2 && two < 7)
Once you roll a red more than six times, or a blue more than six times, your code just does nothing for that square, this is why you end up with white squares.
Try something like this:
if((rand == 1 && one <= 6) || two > 6)
...
else

Categories