1

I'm trying to create a program that assigns a random, unique color to a piece of clothing. I use an array to store already picked colors and try (with for and while) to eliminate duplicate colors.

I know what I have is wrong. It seems that once a color has been found as a non-duplicate it isn't tested again, thus occasionally still resulting in repeats.

Could someone help me get this right? I'd like to avoid fancy library stuff, if possible. I'm awful at coding and want to learn the 'why' and 'how' a bit more clearly.

<!DOCTYPE html>
<html lang="en-us">

<head>

  <!-- the goal is to randomly assign a color to a piece of clothing and have no duplicate colors -->
  <meta charset="utf-8">

  <!-- displays the clothing and color on-screen -->
  shirt: <span id="shirt"></span><br> shorts: <span id="shorts"></span><br> hat: <span id="hat"></span><br> coat: <span id="coat"></span>
  <br><br>

  <!-- testing prints to track what's going on-->
  colorPicked first: <span id="pickedColor"></span><br>

  <br><br> colors so far: <span id="soFar"></span>

</head>

<body>

  <script>
    // establish an array with seven color options
    var colors = ['orange', 'red', 'blue', 'green', 'yellow', 'pink', 'purple'];
    // array to track colors picked so far
    var colorPicked = [];
    // variable to track place in array
    var colorNumber = 0

    // assign a random color to 'shirt'
    var shirtColor = colors[Math.floor(Math.random() * colors.length)];
    colorPicked[colorNumber] = shirtColor;
    document.getElementById('shirt').innerHTML = shirtColor;

    document.getElementById('pickedColor').innerHTML = colorPicked[colorNumber];


    // assign a random color to 'shorts' - a loop (that doesn't quite work right) checks for duplicates
    var shortsColor = colors[Math.floor(Math.random() * colors.length)];


    while (shortsColor == colorPicked[i]) {
      for (var i = 0; i <= colorNumber; i++) {
        document.getElementById('pickedColor').innerHTML = "same";
        document.getElementById('shorts').innerHTML = shortsColor;
        shortsColor = colors[Math.floor(Math.random() * colors.length)];
      }
    }

    if (shortsColor != colorPicked[colorNumber]) {
      document.getElementById('shorts').innerHTML = shortsColor;
      colorNumber = colorNumber + 1;
      colorPicked[colorNumber] = shortsColor;
    }



    // assigns a random, non-repeating color to 'hat'
    var hatColor = colors[Math.floor(Math.random() * colors.length)];

    while (hatColor == colorPicked[i]) {
      for (var i = 0; i <= colorNumber; i++) {
        document.getElementById('pickedColor').innerHTML = "same";
        document.getElementById('hat').innerHTML = hatColor;
        hatColor = colors[Math.floor(Math.random() * colors.length)];
      }
    }

    if (hatColor != colorPicked[colorNumber]) {
      document.getElementById('hat').innerHTML = hatColor;
      colorNumber = colorNumber + 1;
      colorPicked[colorNumber] = hatColor;
    }



    // assigns a random, non-repeating color to 'coat'
    var coatColor = colors[Math.floor(Math.random() * colors.length)];

    while (coatColor == colorPicked[i]) {
      for (var i = 0; i <= colorNumber; i++) {
        document.getElementById('pickedColor').innerHTML = "same";
        document.getElementById('coat').innerHTML = coatColor;
        coatColor = colors[Math.floor(Math.random() * colors.length)];
      }
    }

    if (coatColor != colorPicked[colorNumber]) {
      document.getElementById('coat').innerHTML = coatColor;
      colorNumber = colorNumber + 1;
      colorPicked[colorNumber] = coatColor;
    }

    // show values in the log
    for (var i = 0; i <= colorNumber; i++) {
      //document.getElementById('soFar').innerHTML = colorPicked[i];
      console.log(colorPicked[i]);
    }
  </script>


</body>

</html>
DarkSuniuM
  • 2,523
  • 2
  • 26
  • 43
jsNoob
  • 11
  • 2
  • 1
    One solution is to shuffle the array (by swapping two random elements a few dozen times) then simply pick the first X elements. –  Oct 22 '18 at 23:37
  • Thank you for the idea. Something like this, I'm guessing? https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array – jsNoob Oct 22 '18 at 23:45
  • You don't need some crazy algorithm. Just do what I suggested and "[swap] two random elements a few dozen times". –  Oct 22 '18 at 23:56

1 Answers1

1

An easy solution could be to simply remove the picked color from the array, so that it can't be chosen as a duplicate. Then you also don't need to worry about checking for duplicates.

This code assumes colors is always as long or longer than it needs to be.

let colors = ['red', 'white', 'blue'];
const shirts = [{ name: 'shirt1' }, { name: 'shirt2' }];

const shirtsWithColors = shirts.map((shirt) => {
  // Make a copy of shirt so that we don't modify the one in the `shirts` array
  const newShirt = {...shirt};

  // Pick a color index
  const colorToUseIndex = Math.floor(Math.random() * colors.length);
  const colorToUse = colors[colorToUseIndex];

  // Remove the picked color from the color array
  colors.splice(colorToUseIndex, 1);

  // Assign the color and return
  newShirt.color = colorToUse;
  return newShirt;
});

P.S. if you choose not to use this solution, and to continue with something along the lines you currently have, I do at least recommend that you switch to using a map (object) to see if colors have been used or not. It will make checking a lot simpler:

const colors = ['red', 'white', 'blue'];
const usedColors = {};
...
// When you assign a color:
usedColors[colorIndex] = true;
...
// When checking if the color has been used:
if (usedColors[colorIndex]) {
  // Try picking a different color
}
Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128