There are numerous steps involved in achieving the desired outcome. Typically, I wouldn't write code like this on a platform such as Stack Overflow. However, I decided to do so for fun. Also, it's important to note that you shouldn't expect others to develop an entire game for you without any compensation!
For more information, refer to the comments provided within the HTML, CSS, and JS code snippets.
- To create a color selection mechanism, using radio-buttons seems like the most efficient solution. Radio buttons inherently allow only one choice to be selected:
<input type="radio" name="color" value="color-name" id="color-name">
- To ensure that there is always a color selected initially without breaking the game, use the 'checked' attribute with one of the colors:
<input type="radio" ... checked>
- Hide the checkboxes to make them invisible and not take up any space using CSS:
input { display: none; }
- Add the color as a visual box by incorporating a
<label>
. Clicking on the label should select the appropriate radio button:
<label for="
color-name">
- Color the label according to your preference. Additionally, assign a CSS class to represent the same color for painting purposes:
label[for=color-name],
.color-name {
background-color: color-name;
}
- Create a grid structure either through JavaScript or hardcode it into the HTML. Since explaining the JavaScript approach would be time-consuming, I opted for the latter. In my case, I utilized a grid-container:
<div class="game-board">
. Subsequently, I added 25 child elements: <div class="card"></div>
. To establish a 5x5 grid, I employed CSS to define 5 columns:
.game-board {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
- As previously mentioned in the comments, buttons don't need to be clickable for JavaScript functionality. The labels of the radio buttons already serve this purpose. You can execute a script upon clicking even if it isn't inherently clickable by utilizing the
EventListener
to detect a click
-event via JavaScript:
element.addEventListener('click', e => {
// statements
});
- To selectively target the grid-cards rather than the container or other content, verify if the clicked element contains a specific class:
if (e.target.classList.contains('card')) {
// statements
}
- If the grid-card already possesses a CSS class representing a color, eliminate any conflicting classes that might interfere with proper functioning:
e.target.className = ''
- Subsequently, re-add the 'card' class after removing potential conflicting classes:
e.target.classList.add('card');
- Implement a cleaner logic using a
switch-case
-statement instead of multiple if/else
clauses. This statement evaluates the selected radio button and applies the corresponding class to the clicked element to paint it with the chosen color:
e.target.classList.add('color-name');
EDIT
To include a counter, you can utilize the JavaScript length
method:
document.querySelectorAll('.game-board .color-name').length
. This function calculates the number of elements containing a specific class.
Display the count using the innerHTML
property:
element.innerHTML = document.querySelectorAll('.game-board .color-name').length
var board = document.querySelector('.game-board')
// eventListener to listen to click events on the game board
board.addEventListener('click', e => {
console.clear();
// checks if a card and not the agme baord itself was clicked on
if (e.target.classList.contains('card')) {
const card = e.target.classList;
// checks which color has been selected
var color = document.querySelector('.color-picker input:checked').value;
// removes all classes from the clicked on element to allow re-painting
e.target.className = '';
// re-adds the "card" class to the clicked element
card.add('card');
// switch statement to add the class with the selected color to paint the grid-card
switch (color) {
case "red":
card.add('red');
break;
case "blue":
card.add('blue');
break;
case "green":
card.add('green');
break;
case "yellow":
card.add('yellow');
break;
case "gray":
card.add('gray');
break;
}
// color-counter
var countRed = document.querySelectorAll('.game-board .red').length,
countBlue = document.querySelectorAll('.game-board .blue').length,
countGreen = document.querySelectorAll('.game-board .green').length,
countYellow = document.querySelectorAll('.game-board .yellow').length,
countGray = document.querySelectorAll('.game-board .gray').length;
// displaying the counter
var labelRed = document.querySelector('#count-red span'),
labelBlue = document.querySelector('#count-blue span'),
labelGreen = document.querySelector('#count-green span'),
labelYellow = document.querySelector('#count-yellow span'),
labelGray = document.querySelector('#count-gray span');
labelRed.innerHTML = countRed;
labelBlue.innerHTML = countBlue;
labelGreen.innerHTML = countGreen;
labelYellow.innerHTML = countYellow;
labelGray.innerHTML = countGray;
}
});
/* aligning the color picker and game board next to each other */
body {
margin: 0;
padding: 10px;
box-sizing: border-box;
display: flex;
gap: 10px;
min-height: 100vh;
}
/* box for the color */
.color-picker {
border: 1px solid black;
display: flex;
flex-direction: column;
padding: 5px 30px;
gap: 10px;
}
/* hides the radio button */
.color-picker > input {
display: none;
}
/* creatign a visual border to see what color has been selected */
input:checked + label {
border: 3px solid black;
}
/* setting a "color-box" to the radio-button */
.color-picker > label {
display: block;
box-sizing: border-box;
aspect-ratio: 1 / 1;
min-width: 50px;
}
/* settign the color of the color picker and classes for painting */
label[for=red],
.red {
background-color: red;
}
label[for=blue],
.blue {
background-color: blue;
}
label[for=green],
.green {
background-color: green;
}
label[for=yellow],
.yellow {
background-color: yellow;
}
label[for=gray],
.gray {
background-color: gray;
}
/* game board that creates a board of 5x5 with equal dimensions */
.game-board {
flex-grow: 1;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 5px;
}
/* Setting the grid-cards to be squares */
.game-board > .card {
aspect-ratio: 1 / 1;
border: 1px solid red;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
}
/* To make the grid-cards and label appear like buttons on hover */
.color-picker > label:hover,
.card:hover {
cursor: pointer;
}
<!-- Letting you select the color -->
<div class="color-picker">
<input type="radio" name="color" value="red" id="red" checked>
<label for="red"></label>
<div id="count-red">Count: <span>0</span></div>
<input type="radio" name="color" value="blue" id="blue">
<label for="blue"></label>
<div id="count-blue">Count: <span>0</span></div>
<input type="radio" name="color" value="green" id="green">
<label for="green"></label>
<div id="count-green">Count: <span>0</span></div>
<input type="radio" name="color" value="yellow" id="yellow">
<label for="yellow"></label>
<div id="count-yellow">Count: <span>0</span></div>
<input type="radio" name="color" value="gray" id="gray">
<label for="gray"></label>
<div id="count-gray">Count: <span>0</span></div>
</div>
<!-- The game board as a grid -->
<div class="game-board">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>