I want to randomize elements on pageload - and just show 4 of them regardless on how many there are.
The closest I come is this:
$(document).ready(function() {
$(".itembox.newcenterbox").hide();
var elements = $(".itembox.newcenterbox");
var elementCount = elements.size();
var elementsToShow = 4;
var alreadyChoosen = ",";
var i = 0;
while (i < elementsToShow) {
var rand = Math.floor(Math.random() * elementCount);
if (alreadyChoosen.indexOf("," + rand + ",") < 0) {
alreadyChoosen += rand + ",";
elements.eq(rand).show();
++i;
}
}
});
It works for me on my local site - but it chrashes my live site.and I can't figure out why.
Is there a better way to do this?
Maybe your elementCount is less than elementsToShow? In this case, you will always get rand value between 0 and 3, and it will lead to an infinite loop.
Try the code below. Also I removed unnecessary loop iterations when you check the rand index.
$(document).ready(function() {
var elements = $(".itembox.newcenterbox");
var elementsToShow = 4;
var i = 0;
if(elements.length < elementsToShow) return;
for (i = 0; i < elementsToShow; i++) {
elements.splice(Math.floor(Math.random() * elements.length), 1);
}
elements.hide();
});
Related
NEWB question. Be patient.
As an exercise I am trying to create a grid simply by appending to innerHTML.
I cannot get the loop to repeat beyond its first iteration. I'm sure it's something basic but I have to start somewhere.
I've tried "let" instead of "var", console.log instead of document..., hours of googling.....
var originalSize = 8;
var sizeGrid = 0;
var heightGrid = 0;
var switchChar = 2;
var switchCharTwo = 1;
var charOne = "x";
var charTwo = "#";
while (heightGrid <= originalSize){
document.getElementById("el").innerHTML+="<br>";
if (switchChar % 2 === 0){
switchCharTwo = 1;
}
else {
switchCharTwo = 2;
}
while (sizeGrid <= originalSize){
if (switchCharTwo % 2 === 0){
document.getElementById("el").innerHTML+=charOne;
}
else {
document.getElementById("el").innerHTML+=charTwo;
}
sizeGrid = sizeGrid + 1;
switchCharTwo = switchCharTwo + 1;
}
heightGrid = heightGrid + 1;
switchChar = switchChar + 1;
}
<html>
<body>
<p id="el"></p>
</body>
</html>
What I want is:
#*#*#*#*#
*#*#*#*#*
#*#*#*#*#
etc. depending on the size of the grid.
All I get is one line of the above.
The problem is in the sizeGrid which is stopping the inner loop by doing this it will work fine.
while (heightGrid <= originalSize){
sizeGrid = 0;
document.getElementById("el").innerHTML+="<br>";
if (switchChar % 2 === 0){
switchCharTwo = 1;
}
else {
switchCharTwo = 2;
}
while (sizeGrid <= originalSize){
if (switchCharTwo % 2 === 0){
document.getElementById("el").innerHTML+=charOne;
}
else {
document.getElementById("el").innerHTML+=charTwo;
}
sizeGrid = sizeGrid + 1;
switchCharTwo = switchCharTwo + 1;
}
heightGrid = heightGrid + 1;
switchChar = switchChar + 1;
}
Your code contains two loops with one nested inside of the other.
Your nested loop is going to run on the first iteration while it meets the given condition, sizeGrid <= originalSize. On all subsequent iterations of the main loop however, the given condition has already been met. The value wasn't reset between loops therefore the nested loop doesn't run again.
This could be resolved with a quick update by moving the sizeGrid variable declaration within the main loop:
while (heightGrid <= originalSize) {
var sizeGrid = 0;
Given what you're looking to achieve however, you could condense this down with a different loop type.
You've essentially manually written a for loop. You set the starting counter value, run the loop, and then increment your counter. Here's the approach I'd suggest:
for (let heightGrid = 0; heightGrid <= originalSize; heightGrid++) {
... logic here
// nested loop
for (let sizeGrid = 0; sizeGrid <= originalSize; sizeGrid++) {
// nested logic
}
}
You'll have to be careful with the comparisons however. Your original loop iterates 10 times despite originalSize being 8. The for loop above will actually run 9 times which seems to match the output you're looking for. I'd be inclined to adjust your numbering so that it's clearer though.
Here's a rough approach I came up with:
const gridSize = 9;
const gridChars = ['x', '#'];
let gridCharCounter = 0;
for (let rows = 0; rows < gridSize; rows++) {
for (let columns = 0; columns < gridSize; columns++) {
const charKey = gridCharCounter % gridChars.length;
document.getElementById("el").innerHTML += gridChars[ charKey ];
gridCharCounter++;
}
document.getElementById("el").innerHTML += '<br />';
}
<div id='passarr'>1572 4528 3564 8921 4521</div>
I need to create a new random integer (4 digits), unique regarding the above content.
js
var content = $('#passarr').text();
var passarr = content.split(' ');
var pass = Math.floor(Math.random() * 9000) + 1000;
var i = 0;
while (i == 0) {
if (jQuery.inArray(pass, passarr) > -1) {
var pass = Math.floor(Math.random() * 9000) + 1000;
i = 1;
}
}
seems it works, but not sure this is the right and shortest way.
any suggestion?
Your code is the way to go. However, you can eliminate a few smaller mistakes ( an unneccessary i and non working code in < 0.00001%) :
var content = $('#passarr').text();
var passarr = content.split(' ');
do {
var pass = Math.floor(Math.random() * 9000) + 1000;
} while (jQuery.inArray(pass, passarr) > -1);
console.log(pass);
Can someone tell me why this bit of JavaScript is buggy?
I have HTML also, but I don't want to make this a massive code dump.
<script type = 'text/javascript'>
var playerCards = [];
var dealerCards = [];
function deal() {
var newCard = Math.random() % 12;
var newCard2 = Math.random() % 12;
playerCards += newCard;
playerCards += newCard2;
var counter = 0;
for (var i = 0; i < playerCards.length; ++i) {
counter += i;
}
document.getElementById("playerTotal").innerHTML = counter;
var dCounter = 0;
for (var j = 0; j < playerCards.length; ++j) {
dCounter += j;
}
document.getElementById("dealerTotal").innerHTML = dCounter;
}
</script>
I'm gonna assume this is a silly syntax error someplace, but I can't find it.
I'm guessing that this isn't doing what you expect it to:
playerCards += newCard;
playerCards += newCard2;
Try this instead:
playerCards.push(newCard);
playerCards.push(newCard2);
The first snippet is trying to "add" a number to an array, which doesn't exactly make sense. Through some arcane JavaScript rules, this turns the result into a string.
I'm guessing that you want to concatenate to an array instead.
Math.random returns a number between 0 and 1 - so Math.random() % 12 will probably be zero
var playerCards = [];
playerCards += newCard; //
what are you even trying to do there?
var counter = 0;
for (var i = 0; i < playerCards.length; ++i) {
counter += i;
}
if playerCards had a length, this loop would result in counter having value of 0, 1, 3, 6, 10 .. n(n+1) / 2 - probably not what you intended, but who knows
I'm doing "fifteen puzzle" game. I'm only a beginner, so I chose this project to implement. My problem is shuffle algorithm :
function shuffle() {
$('td').empty();
var p = 0;
var f = 0;
do {
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var rand = arr[Math.floor(Math.random() * arr.length)];
if ($('#' + rand).is(':empty')) {
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
} else {}
} while (f < 15)
That works cool, but I've heard that almost 50% of all random shuffle like mine is unsolvable. So I found math formula at wikipedia.org for this game, explaining how you can avoid that.
Here's modified algorithm that doesn't work either. The way I know it is alert stuff: it launches only 2 times instead of 31.
array = [];
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
array[i] = new Array();
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array[i].push(j)
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
The question is the same:
What's wrong? Two-dimensional array doesn't work.If you've got any questions - ask.
Just to make it clear: 2 for loops with i and j should make a 2-dimensional array like this [ this is " var i" -->[1,3,4,5,7], this is "var i" too-->[5,7,9,14,15]]. Inside each i there's j. The for loop with var a should count the number of js inside each i. if the number of js is even, the code is finished and shuffle's accomplished, otherwise shuffle should be made once again.
var nextId = cerIdNum + j;
in that fiddle, I don't see this cerIdNum declared & defined neither as local nor as global variable, I suppose that is curIdNum
Please use the below definition of algorithm and let us know if this works. Basically, the alert messages would come only twice, since there were usages of undefined variables. For the purpose of illustration, I have placed comments at where the problem points occured. Due to these problems, your script would stop executing abruptly thereby resulting in the behavior you described.
Oh and by the way - I did not have time to go through the Wiki link provided - hence you will have to verify your logic is correct. However, I have definitely resolved the errors causing the behavior you observed.
As an aside - consider using jQuery, your code will be a lot cleaner...
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array.push(j) //array[i].push does not make sense
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array.length; //array[1].length does not make sense
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
I found the solution by totally rewriting the code. Thank everyone for help!
Here's what do work:
function shuffle (){
press = 1;
$('td').empty().removeClass();
p=0;
var f;
do {
var arr=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var rand=arr[Math.floor(Math.random()*arr.length)];
if ($('#'+ rand).is(':empty')){
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
}
else{}
}while(f < 15){
winChance();
}
}
function winChance (){
array = [];
for (i=1;i<16;i++){
array[i]= new Array();
var currentId = $('#' + i).attr('id');
var currentIn = $('#' + i).html()
var currentIdNum = parseInt(currentId, 10);
var currentInNum = parseInt(currentIn, 10);
for (j=1;j<16;j++){
var nextId = currentIdNum + j;
if (nextId < 16){
var nextIn = $('#' + nextId).html();
var nextInNum = parseInt(nextIn, 10);
if (currentInNum > nextInNum){
array[i].push(j);
}
}
}
}
checkSum();
}
function checkSum(){
var sum = 0;
for (var a=1; a<16; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){}
else {
shuffle();
}
}
I'm pretty new to programming and javascript/dom. Ultimately, I'm trying to make a sliding puzzle game but to start off with, I'm just trying to get the images loading up in a random order. It's going to be a 4x4 grid of images. The images are named Tree00, 01, 02, 03, 10, etc up to 33. Here's my code so far:
<html>
<head>
<title>Shuffle</title>
</head>
<body>
<script language="JavaScript">
<!--
Pics = new Array();
var Top = 16;
for(i = 0; i < Top; i++) {
document.write("<img><img><img><img><br>");
}
function RandomInt(Min, Max) {
RI = Math.floor(Math.random() * (Max - Min + 1)) + Min;
return(RI);
}
function Shuffle() {
N = RandomInt(0, 1);
this.Image.src=Pics[N];
this.Image.style.left = 220;
}
function ViewerObj(Image, Pics, i) {
this.Image = Image;
this.Image.style.left = 800;
this.Pics = Pics;
this.Shuffle = Shuffle;
this.Image.id = "ID" + i;
}
function Randomise() {
var i;
for(i = 0; i < Top; i++) {
Viewers[i].Shuffle();
Viewers[i].Image.style.left = 200;
}
}
Viewers = new Array();
var i;
for(i = 0; i < 3; i++) {
Pics[i] = "images/Tree" + (i) + (i + 1) + ".jpg";
}
for(i = 0; i < Top; i++) {
document.images[i].src = "images/Blank.jpg";
document.images[i].style.left = 300;
Viewers[i] = new ViewerObj(document.images[i], Pics, i);
}
//-->
</script>
<h1>Shuffle</h1>
<form>
<input type="button" value="Shuffle" onClick="Randomise();"/>
</form>
</body>
</html>
I just can't quite fathom what I need to be changing and how I'd go about it. Any help + explanation would be much appreciated. What I am trying to achieve is it loading every image but just in a random order, but with no duplicates.
Here are a few problems in your script :
first replace
for(i = 0; i < Top; i++) {
document.write("<img><img><img><img><br>");
}
by
for(i = 0; i < Top; i++) {
document.write("<img>");
if ((i+1)%4 == 0) {
document.write("<br>");
}
}
you will get only 16 IMG elements instead of 4*16 in your code
then you will need 16 different names for your images : replace
for(i = 0; i < 3; i++) {
Pics[i] = "images/Tree" + (i) + (i + 1) + ".jpg";
}
by
for(var i = 0; i < 4; i++) {
for(var j = 0; j < 4; j++) {
Pics[j+4*i] = "images/Tree" + (i) + (j) + ".jpg";
}
}
Then you biggest problem is the shuffling. You cannot shuffle the "Viewers" one-by-one because you want to avoid duplicates. Each viewer must randomly select a unique image.
For this you can use the technique in mdarwi's answer : shuffle the Pics table for instance.
check your modified code on jsbin here
If your problem is simply that you'd like the images to be properly shuffled, you can use the following code (taken directly from the Javascript sample code for the Fisher-Yates shuffle on Wikipedia:
var n = a.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
The easiest thing to do would be to rename your images Tree1 to TreeN, and then place N integers in an array and shuffle them using the above algorithm.
(This is a code-comment, not an answer)
Pics = new Array();
The Pics variable should be declared before using. Also, use the shorthand notation []
var Pics = [];
var Top = 16;
for (i = 0; i < Top; i++) {
document.write("<img><img><img><img><br>");
}
The i variable is declared only later in the code. It should be declared at the top of the program.
function RandomInt(Min, Max) {
RI = Math.floor(Math.random() * (Max - Min + 1)) + Min;
return (RI);
}
This is particularly dangerous: the RI variable is not declared inside the function, so it becomes an implicit global property. That should be avoided. Also, the parens in the return statement are superfluous.
function RandomInt(Min, Max) {
return Math.floor(Math.random() * (Max - Min + 1)) + Min;
}
function Shuffle() {
N = RandomInt(0, 1);
this.Image.src = Pics[N];
this.Image.style.left = 220;
}
Again, the N variable should be declared. Also, why is this "method" declared outside of the ViewerObj constructor? Either, put it inside, or - even better - add it to the constructors prototype object. That way, there will only be one Shuffle function object instead of many.
function ViewerObj(Image, Pics, i) {
this.Image = Image;
this.Image.style.left = 800;
this.Pics = Pics;
this.Shuffle = Shuffle;
this.Image.id = "ID" + i;
}
function Randomise() {
var i;
for (i = 0; i < Top; i++) {
Viewers[i].Shuffle();
Viewers[i].Image.style.left = 200;
}
}
Viewers = new Array();
var i;
As mentioned above, the i variable should be declared on top. Also, the Viewers variable should be declared.
var Viewers = [];
for (i = 0; i < 3; i++) {
Pics[i] = "images/Tree" + (i) + (i + 1) + ".jpg";
}
for (i = 0; i < Top; i++) {
document.images[i].src = "images/Blank.jpg";
document.images[i].style.left = 300;
Viewers[i] = new ViewerObj(document.images[i], Pics, i);
}