I'm trying to pare two RGB colors in a guessing game. There are 6 squares with 6 different colors. When the user clicks on the color that matches pickedColor
, the result should be 'Correct!'. But I never get that result.
This is my code:
var colors = [
"rgb(255,0,0)",
"rgb(255,255,0)",
"rgb(0,255,0)",
"rgb(0,255,255)",
"rgb(0,0,255)",
"rgb(255,0,255)"
];
var squares = document.querySelectorAll(".square");
var pickedColor = colors[3];
var colorDisplay = document.getElementById("colorDisplay");
colorDisplay.textContent = pickedColor;
for (var i = 0; i < squares.length; i++) {
//add initinal colors to squares
squares[i].style.background = colors[i];
//add the click listener to the squares
squares[i].addEventListener("click", function () {
var clickedColor = this.style.background;
if (clickedColor === pickedColor) alert("Correct!");
else alert("Incorrect!");
});
}
I'm trying to pare two RGB colors in a guessing game. There are 6 squares with 6 different colors. When the user clicks on the color that matches pickedColor
, the result should be 'Correct!'. But I never get that result.
This is my code:
var colors = [
"rgb(255,0,0)",
"rgb(255,255,0)",
"rgb(0,255,0)",
"rgb(0,255,255)",
"rgb(0,0,255)",
"rgb(255,0,255)"
];
var squares = document.querySelectorAll(".square");
var pickedColor = colors[3];
var colorDisplay = document.getElementById("colorDisplay");
colorDisplay.textContent = pickedColor;
for (var i = 0; i < squares.length; i++) {
//add initinal colors to squares
squares[i].style.background = colors[i];
//add the click listener to the squares
squares[i].addEventListener("click", function () {
var clickedColor = this.style.background;
if (clickedColor === pickedColor) alert("Correct!");
else alert("Incorrect!");
});
}
Share
Improve this question
edited Dec 25, 2015 at 0:17
Michael Laszlo
12.2k2 gold badges32 silver badges47 bronze badges
asked Dec 24, 2015 at 23:37
Luis MartinezLuis Martinez
271 silver badge8 bronze badges
3
- what do you mean by "it always alerts the second option" – Pabs123 Commented Dec 24, 2015 at 23:41
- And did you log the returned color to the console? Most browsers use RGBA these days, and there's no guarantee that the browser will return a string looking like the ones you have, old browsers could return hex, new browsers could return HSL, who knows – adeneo Commented Dec 24, 2015 at 23:41
- 2 @Pabs123 I think that he means that clickedColor === pickedColor always returns false (else is the 2nd statement) – Nike Sprite Commented Dec 24, 2015 at 23:41
4 Answers
Reset to default 4Ok so I set up an example here and it looks like the problem is that your initial set of colours don't have spaces between the mas:
var colors = [
"rgb(255,0,0)",
"rgb(255,255,0)",
"rgb(0,255,0)",
"rgb(0,255,255)",
"rgb(0,0,255)",
"rgb(255,0,255)"
];
clickedColor has no spaces and the pickedColor does, so changing this to:
var colors = [
"rgb(255, 0, 0)",
"rgb(255, 255, 0)",
"rgb(0, 255, 0)",
"rgb(0, 255, 255)",
"rgb(0, 0, 255)",
"rgb(255, 0, 255)"
];
Should do the trick.
The trouble is that the color expression 'rgb(0,255,255)'
is formatted differently by the browser. In the test clickedColor === pickedColor
, you're paring two strings that no longer look the same even if they represent the same color.
Different browsers can represent an RGB color in different ways, so it's unsafe to pick a particular format. A better approach is to extract the color ponents from the strings and pare the ponent values one by one, as in the code below.
function rgbExtract(s) {
var match = /^\s*rgb\(\s*(\d+),\s*(\d+),\s*(\d+)\)\s*$/.exec(s);
if (match === null) {
return null;
}
return { r: parseInt(match[1], 10),
g: parseInt(match[2], 10),
b: parseInt(match[3], 10) };
}
function rgbMatches(sText, tText) {
var sColor = rgbExtract(sText),
tColor = rgbExtract(tText);
if (sColor === null || tColor === null) {
return false;
}
var ponentNames = [ 'r', 'g', 'b' ];
for (var i = 0; i < ponentNames.length; ++i) {
var name = ponentNames[i];
if (sColor[name] != tColor[name]) {
return false;
}
}
return true;
}
The rgbMatches
function is demonstrated in the following snippet. You'll see that you can now click on the square with the correct color and you'll get the appropriate message even though the underlying RGB strings are formatted differently.
var colors = [
"rgb(255,0,0)",
"rgb(255,255,0)",
"rgb(0,255,0)",
"rgb(0,255,255)",
"rgb(0,0,255)",
"rgb(255,0,255)"
];
var squares = document.querySelectorAll(".square");
var pickedColor = colors[3];
var colorDisplay = document.getElementById("colorDisplay");
colorDisplay.textContent = pickedColor;
function message(s) {
document.getElementById('messageContainer').innerHTML = s;
}
function rgbExtract(s) {
var match = /^\s*rgb\(\s*(\d+),\s*(\d+),\s*(\d+)\)\s*$/.exec(s);
if (match === null) {
return null;
}
return { r: parseInt(match[1], 10),
g: parseInt(match[2], 10),
b: parseInt(match[3], 10) };
}
function rgbMatches(sText, tText) {
var sColor = rgbExtract(sText),
tColor = rgbExtract(tText);
if (sColor === null || tColor === null) {
return false;
}
var ponentNames = [ 'r', 'g', 'b' ];
for (var i = 0; i < ponentNames.length; ++i) {
var name = ponentNames[i];
if (sColor[name] != tColor[name]) {
return false;
}
}
return true;
}
for (var i = 0; i < squares.length; ++i) {
var square = squares[i];
square.style.background = colors[i];
square.addEventListener("click", function () {
var clickedColor = this.style.background;
if (rgbMatches(clickedColor, pickedColor)) {
message('Correct! ' + clickedColor + ' matches ' + pickedColor);
} else {
message('Incorrect. ' + clickedColor + ' doesn\'t match ' + pickedColor);
}
});
}
body {
font-family: sans-serif;
}
.square {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
border: 1px solid #888;
cursor: pointer;
}
.output {
margin: 10px 5px;
}
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="output" id="colorDisplay"></div>
<div class="output" id="messageContainer"></div>
I would be wary of paring two rgb strings like this. Different browsers may store style background colors differently (as you have already discovered).
I would suggest writing a custom parison function which parses two rgb strings and pares them.
Or you could convert them to hex color values and pare those instead.
Do not trust the color returned by the browser. Different browsers will use different formats.
Instead, use classes or data-*
attributes to set the color, and check that:
var colors = ["red", "yellow", "lime", "cyan", "blue", "fuchsia"],
squares = document.querySelectorAll(".square"),
pickedColor = colors[Math.floor(Math.random()*colors.length)],
message = document.getElementById("messageContainer");
document.getElementById("colorDisplay").textContent = pickedColor;
for (var i = 0; i < squares.length; ++i) {
squares[i].setAttribute('data-color', colors[i]);
squares[i].addEventListener("click", function () {
var clickedColor = this.getAttribute('data-color');
message.textContent = clickedColor === pickedColor
? "Correct!" : "Incorrect!";
});
}
.square {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
border: 1px solid #888;
cursor: pointer;
}
.output {
margin: 10px 5px;
}
[data-color=red] { background: rgb(255,0,0) }
[data-color=yellow] { background: rgb(255,255,0) }
[data-color=lime] { background: rgb(0,255,0) }
[data-color=cyan] { background: rgb(0,255,255) }
[data-color=blue] { background: rgb(0,0,255) }
[data-color=fuchsia] { background: rgb(255,0,255) }
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="output" id="colorDisplay"></div>
<div class="output" id="messageContainer"></div>