2

I am trying to create a table with non repeating random letters (uppercase only) using JavaScript. Someone posted an answer, but it was deleted before I got a chance to ask: 1) Why is there a var x and a var y instead of having only a var x? 2)Why do you put i-1 in return letters[i-1]?

HTML5:

<table class="bingo">
    <tr>
        <td id="square0"></td>
        <td id="square1"></td>
        <td id="square2"></td>
    </tr>
    <tr>
        <td id="square3"></td>
        <td id="square4"></td>
        <td id="square5"></td>
    </tr>
    <tr>
        <td id="square6"></td>
        <td id="square7"></td>
        <td id="square8"></td>
   </tr>
 </table>

JS

//Create capital letters A - Z array
var letters = [];
    for (var i = 65; i < 91; i++) {
      letters.push(String.fromCharCode(i));
}

//Confuse about why there is a var x and a var y?
    for (var i = 0; i < 26; i++) {
       var x = Math.floor(Math.random() * 26);
       var y = Math.floor(Math.random() * 26);
       var temp = letters[x];
       letters[x] = letters[y];
       letters[y] = temp;
 }

 var rLetter = function(i) {
  return letters[i-1];
};

window.onload = function () {
  //calls the function  
  $("square0").innerHTML = rLetter(1);
  $("square1").innerHTML = rLetter(2);
  $("square2").innerHTML = rLetter(3);
  $("square3").innerHTML = rLetter(4);
  $("square4").innerHTML = rLetter(5);
  $("square5").innerHTML = rLetter(6);
  $("square6").innerHTML = rLetter(7);
  $("square7").innerHTML = rLetter(8);
  $("square8").innerHTML = rLetter(9);

}

user5117220
  • 89
  • 3
  • 12
  • You need the X and Y because it's [randomizing](http://stackoverflow.com/a/2450976/502613) the array of letters. Re-using variables is bad practice. You don't really need `i - 1` but it'll let you start at `1` in the `onload` function instead of `0`. – Jorg Aug 12 '15 at 00:52

3 Answers3

0
var letters = [];
for (var i = 65; i < 91; i++) {
  letters.push(String.fromCharCode(i));
}

The code above is creating an array with characters from A to Z in alphabetical, non-random order.

for (var i = 0; i < 26; i++) {
  var x = Math.floor(Math.random() * 26);
  var y = Math.floor(Math.random() * 26);
  var temp = letters[x];
  letters[x] = letters[y];
  letters[y] = temp;
}

Answering your first question, what this code is doing is creating two random numbers (x and y) and a variable named temp to hold the contents of letters[x]. Then, the function assigns letters[x] to be whatever letters[y] was, then assigning letters[x] to be whatever letters[y] was. The point of this is to make the letters array randomized.

Let's say that x = 1 and y = 2:

var temp = 'B';     // because letters[1] = B
letters[1] = 'C';   // because letters[2] = C
letters[2] = 'B';   // because temp = B

So now, the letters array looks like:

letters[0] = A
letters[1] = C
letters[2] = B
// etc...

It's basically just randomizing the entire array.

Lastly, answering your second question, the reason you put [i-1] is because the letters array index starts at 0. So when you call rLEtters(1), it is actually grabbing 0 (1-1 = 0) from the letters array.

Wes Foster
  • 8,770
  • 5
  • 42
  • 62
  • Unfortunately, the result of this isn't actually random - it's biased. Jeff Atwood has written an exellent [blog post](http://blog.codinghorror.com/the-danger-of-naivete/) explaining why. – Gerrat Aug 12 '15 at 01:30
  • @WesFoster Thank you for the explanation. Trying to understand your example, a little confuse about the B,C,B
    var temp = letters[x];
    letters[x] = letters[y];
    letters[y] = temp;
    so x = 1, y = 2
    var temp = letter[1]; // because letters[1] = B
    letters[1] = letter[2]'; // because letters[2] = C
    letters[2] = letter[1]; // because temp = B
    – user5117220 Aug 13 '15 at 07:31
  • @user5117220 Has this helped you? – Wes Foster Sep 29 '15 at 21:01
0

1) Why is there a var x and a var y instead of having only a var x?

It looks like this code creates an array of all capital letters, then "randomizes" them by switching the location of 2 letters 26 times. 2 variables need to be created to hold the position of each of the 2 letters that are being switched.

2)Why do you put i-1 in return letters[i-1]?

The array is zero-indexed meaning the first value in the array is at letters[0]. Using i-1 allows you to get the 1st value in the array by using rLetter(1), rather than getting the 2nd value.

I would have personally done it like this:

var usedLetters = [];

var rLetter = function(i) {
  var alreadyUsed = 0;
  var letter;
  while(alreadyUsed >= 0) {
    var x = Math.floor(Math.random() * 26);
    letter = String.fromCharCode(65 + x);
    alreadyUsed = usedLetters.indexOf(letter);
  }
  usedLetters.push(letter);
  return letter;
};


window.onload = function () {
  //calls the function  
  $("square0").innerHTML = rLetter(1);
  $("square1").innerHTML = rLetter(2);
  $("square2").innerHTML = rLetter(3);
  $("square3").innerHTML = rLetter(4);
  $("square4").innerHTML = rLetter(5);
  $("square5").innerHTML = rLetter(6);
  $("square6").innerHTML = rLetter(7);
  $("square7").innerHTML = rLetter(8);
  $("square8").innerHTML = rLetter(9);

}

Sorry for any code errors. I have very little experience in JS.

MisterEman22
  • 238
  • 2
  • 10
0

If you actually want a random shuffle (at least algorithmically), you can't just do 26 random swaps of letters (as another answer did).

The result of that is biased - see Implementation errors in Fisher-Yates shuffle & also Jeff Atwood's post on naïveté.

Below, I've used Mike Bostock's implementation of the Fisher-Yates shuffle to produce an unbiased random ordering of letters (up to the limits of javascript's random number generator anyway).

//  create array of uppercase letters
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');

// implentation of the Fischer-Yeates shuffle
// as written by Mike Bostock (http://bost.ocks.org/mike/shuffle/)
function shuffle(array) {
  var m = array.length, t, i;

  // While there remain elements to shuffle…
  while (m) {

    // Pick a remaining element…
    i = Math.floor(Math.random() * m--);

    // And swap it with the current element.
    t = array[m];
    array[m] = array[i];
    array[i] = t;
  }

  return array;
}

window.onload = function () {

    var shuffled = shuffle(letters);

    for (var i=0; i<9; i++) {
        $("#square" + i).html(shuffled[i]);
    }

}

Codepen here.

Gerrat
  • 28,863
  • 9
  • 73
  • 101