Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Isaac_Kamran_Guess_Who #340

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Project Name

Replace this readme with your own information about your project.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
Time to dig deeper into javascript and focusing on Objects and Arrays through creating the boardgame "Guess Who".

## The problem

Expand Down
12 changes: 11 additions & 1 deletion code/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Project Name</title>
<title>Guess Who</title>
<link rel="stylesheet" href="style.css" />
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
Expand All @@ -26,14 +26,24 @@ <h1>Does the person have</h1>
<optgroup label="hair">
<option value="brown">brown hair</option>
<option value="yellow">yellow hair</option>
<option value="grey">grey hair</option>
<option value="black">black hair</option>
<option value="orange">orange hair</option>
<option value="purple">purple hair</option>
<option value="white">white hair</option>
<option value="hidden">hidden hair</option>
<!-- Add the rest of hair colors as options -->
</optgroup>
<optgroup label="eyes">
<option value="hidden">hidden eyes</option>
<option value="blue">blue eyes</option>
<option value="brown">brown eyes</option>
<option value="green">green eyes</option>
<!-- Add the rest of eye colors as options -->
</optgroup>
<optgroup label="accessories">
<option value="glasses">glasses</option>
<option value="hat">hat</option>
<!-- Add the other accessory option here. (hat) -->
</optgroup>
<optgroup label="other">
Expand Down
72 changes: 66 additions & 6 deletions code/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
const board = document.getElementById('board')
const questions = document.getElementById('questions')
const restartButton = document.getElementById('restart')
const findOutButton = document.getElementById('filter')
const winOrLose = document.getElementById('winOrLose')
const winOrLoseText = document.getElementById('winOrLoseText')
const playAgain = document.getElementById('playAgain')

// Array with all the characters, as objects
const CHARACTERS = [
Expand Down Expand Up @@ -225,13 +229,18 @@ const generateBoard = () => {
// Randomly select a person from the characters array and set as the value of the variable called secret
const setSecret = () => {
secret = charactersInPlay[Math.floor(Math.random() * charactersInPlay.length)]
console.log(secret)
}

// This function to start (and restart) the game
const start = () => {
// Here we're setting charactersInPlay array to be all the characters to start with
charactersInPlay = CHARACTERS
winOrLose.style.display = "none"
board.style.display = "flex"
// What else should happen when we start the game?
generateBoard()
setSecret()
}

// setting the currentQuestion object when you select something in the dropdown
Expand All @@ -240,26 +249,38 @@ const selectQuestion = () => {

// This variable stores what option group (category) the question belongs to.
// We also need a variable that stores the actual value of the question we've selected.
// const value =
const value = questions.value

currentQuestion = {
category: category,
// value: value
value: value
}
console.log(currentQuestion)
}

// This function should be invoked when you click on 'Find Out' button.
const checkQuestion = () => {
const { category, value } = currentQuestion

let keep = false
console.log(category)
console.log(secret)
console.log(secret[category])
// Compare the currentQuestion details with the secret person details in a different manner based on category (hair/eyes or accessories/others).
// See if we should keep or remove people based on that
// Then invoke filterCharacters
if (category === 'hair' || category === 'eyes') {

keep = value === secret[category]
} else if (category === 'accessories' || category === 'other') {

//since accesory and other are arrays we have to find value inside them first and then set keep to true or false depending on if value exist in the array.
const findItem = secret[category].find(item => item === value)
// if findItem exist in the array keep is true else false
if (findItem) {
keep = true
} else {
keep = false
}
}
filterCharacters(keep)
}

// It'll filter the characters array and redraw the game board.
Expand All @@ -268,24 +289,45 @@ const filterCharacters = (keep) => {
// Show the correct alert message for different categories
if (category === 'accessories') {
if (keep) {
charactersInPlay = charactersInPlay.filter((person) => person[category].includes(value))
alert(
`Yes, the person wears ${value}! Keep all people that wears ${value}`
)
} else {
charactersInPlay = charactersInPlay.filter((person) => !person[category].includes(value))
alert(
`No, the person doesn't wear ${value}! Remove all people that wears ${value}`
)
}
} else if (category === 'other') {
// Similar to the one above
if (keep) {
charactersInPlay = charactersInPlay.filter((person) => person[category].includes(value))
alert(
`Yes, the person have ${value}! Keep all people that have ${value}`
)
} else {
charactersInPlay = charactersInPlay.filter((person) => !person[category].includes(value))
alert(
`No, the person doesn't have ${value}! Remove all people that have ${value}`
)
}
} else {
if (keep) {
charactersInPlay = charactersInPlay.filter((person) => person[category] === value)
// alert popup that says something like: "Yes, the person has yellow hair! Keep all people with yellow hair"
alert(
`Yes, the person has ${value} ${category}! Keep all people with ${value} ${category}`
)
} else {
charactersInPlay = charactersInPlay.filter((person) => person[category] !== value)
// alert popup that says something like: "No, the person doesnt have yellow hair! Remove all people with yellow hair"
alert(
`No, the person doesn't have ${value} ${category}! Remove all people with ${value} ${category}`
)
}
}

generateBoard()
// Determine what is the category
// filter by category to keep or remove based on the keep variable.
/*
Expand All @@ -305,13 +347,28 @@ const filterCharacters = (keep) => {

// when clicking guess, the player first have to confirm that they want to make a guess.
const guess = (personToConfirm) => {
if (confirm("Are you sure you want to make a guess?") == true) {
checkMyGuess(personToConfirm)
}

// store the interaction from the player in a variable.
// remember the confirm() ?
// If the player wants to guess, invoke the checkMyGuess function.
}

// If you confirm, this function is invoked
const checkMyGuess = (personToCheck) => {
if (personToCheck === secret["name"]) {
questions.style.display = "flex"
winOrLose.style.display = "flex"
board.style.display = "none"
winOrLoseText.innerHTML = "WOOHOO! YOU WON!"
} else {
questions.style.display = "flex"
winOrLose.style.display = "flex"
board.style.display = "none"
winOrLoseText.innerHTML = "OH NO! YOU LOST!"
}
Comment on lines 360 to +371

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code looks nice. Can you tell me why you use flex? I'm curious because I have it done differently, but I'd like to know what you had in mind when writing this code :)

// 1. Check if the personToCheck is the same as the secret person's name
// 2. Set a Message to show in the win or lose section accordingly
// 3. Show the win or lose section
Expand All @@ -323,3 +380,6 @@ start()

// All the event listeners
restartButton.addEventListener('click', start)
questions.addEventListener("change", selectQuestion )
findOutButton.addEventListener("click", checkQuestion)
playAgain.addEventListener("click", start)
33 changes: 22 additions & 11 deletions instructions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Step 1 - Loading the website
The first thing that happens when you load the website is that the game board should be rendered on the screen. We've set up the function `generateBoard` that you can invoke whenever you need it. Take a look at this function to **see that you understand what is happening in there**. Basically, we're looking at the characters array and looping through that array, creating one 'card' for each person in that array. We're adding that as the innerHTML of the element with the id `board`.

The first thing that happens when you load the website is that the game board should be rendered on the screen. We've set up the function `generateBoard` that you can invoke whenever you need it. Take a look at this function to **see that you understand what is happening in there**. Basically, we're looking at the characters array and looping through that array, creating one 'card' for each person in that array. We're adding that as the innerHTML of the element with the id `board`.

💡 You can also see that all the DOM selectors should be set up on the top of the file, just as we've done with a few of them.

Expand All @@ -8,42 +9,45 @@ Also, take a look at the huge CHARACTERS array that contains a bunch of objects
The `generateBoard` function should be invoked when the website is loaded, but that's not the only thing that should happen at that point. That's why we've created a `start` function. The `start` function is invoked in the end of the Javascript file, that is when the website is loaded. But the `start` function itself is empty, so nothing happens when it's invoked. Make sure to fill up the board with characters here.

## Step 2 - What else should happen when we start the game?

We're playing against "the computer" so there's a need to have a secret person, randomly selected by the opponent. The one that we're guessing on. We need to set this secret when the game starts. We've created a randomizer function to randomly select one character item from the big array of characters. This is done in the `setSecret` function, where we randomly select a character and set that as the value of the global variable named `secret`. Make sure to set a secret person when the game starts.

💡 Read more about how to use `Math.random()` [here](https://www.w3schools.com/js/js_random.asp "here")

## Step 3 - How do we play the game?
First of all, we need to be able to select a question to ask about a person and then based on the answer to that question, filter out the people who match (or don't match) that answer.

For example, if our `secret` person is wearing glasses, and we make a guess that the character is wearing glasses, we want the game to filter out all characters who are *not wearing glasses.* We'll go further into how you might do the filtering in step 4.
First of all, we need to be able to select a question to ask about a person and then based on the answer to that question, filter out the people who match (or don't match) that answer.

For example, if our `secret` person is wearing glasses, and we make a guess that the character is wearing glasses, we want the game to filter out all characters who are _not wearing glasses._ We'll go further into how you might do the filtering in step 4.

There's a `selectQuestion` function declared, but you need to make it work. Also, you need to figure out when it should be invoked.

It's time to use an eventListener that listens to when the player interacts with your website.
It's time to use an eventListener that listens to when the player interacts with your website.

All the `eventListeners` should be set up at the bottom of the file. We've set up the restart button there and made that button listen to a click event. When the click event is triggered, the start function is invoked. Do something similar with the `select` element.

💡 Read more about how to deal with events and selects [here](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event).

Also, make sure to set up the actual select element with all the options to ask about.
Also, make sure to set up the actual select element with all the options to ask about.

We want to store this question in the global variable `currentQuestion`, so that we then can compare the question with the secret person. We need to store the information about what **category** we're asking about and the actual **value** we've chosen. Such as `hair` (**category**) and `yellow` (**value**).

The `currentQuestion` variable should be an object, that you for example would set like this:
The `currentQuestion` variable should be an object, that you for example would set like this:

```jsx
currentQuestion = {
category: 'hair', // <-- Based on the optgroup
value: 'yellow', // <-- Comes from the selected option
}
category: "hair", // <-- Based on the optgroup
value: "yellow", // <-- Comes from the selected option
};
```

We need to set this up with variables `category` and `value` instead of hardcoded values since the actual data will be available to detect thanks to `questions.options[questions.selectedIndex]`.

We've helped you to set up the `category` variable. Make sure to properly create `value` variable!

## Step 4 - Time to find out the answer to your questions!
When clicking on the `'Find out'` button, you should invoke the `checkQuestion` function (using an eventListener). In the `checkQuestion` function, we need to check if the attributes in the `currentQuestion` matches the attributes in the `secret` or not.

When clicking on the `'Find out'` button, you should invoke the `checkQuestion` function (using an eventListener). In the `checkQuestion` function, we need to check if the attributes in the `currentQuestion` matches the attributes in the `secret` or not.

For example, if we're asking: "Does the person have yellow hair" and the person stored in the secret has yellow hair, we want to **keep** all with yellow hair. If not, we want to **remove** all with yellow hair.

Expand All @@ -52,15 +56,17 @@ When we've figured this out, we should call `filterCharacters` function with pro
For example, if we're asking: "Does the person have yellow hair" and the person stored in the secret has yellow hair, we want to call `filterCharacters(true)`.

## Step 5 - Giving the player some feedback and filter the board

So, in the `filterCharacters` function we first want to make sure to give the player some feedback on what's happening. We can do this with a built-in JavaScript method `alert()`. We want the text in the alert to be slightly different depending on if the question is about accessories, other or the color of hair or eyes. So the first step could be to check what category the question is in.

Then we also want to know If the text should say *Yes, the person smokes* or *No, the person doesn't smoke*, for example. This we will check with the `keep` parameter passed in to the function.
Then we also want to know If the text should say _Yes, the person smokes_ or _No, the person doesn't smoke_, for example. This we will check with the `keep` parameter passed in to the function.

Lastly we want to use the `filter()` method to filter out people from the `charactersInPlay` array. There's an example on how to structure this in the code.

💡 Remember that you also need to re render the game board so that only the people still in play is shown.

## Step 6 - Time to make a guess!

At some point, the player wants to make a guess about who the secret person is.

When you hover over the cards you'll see a `'Guess'` button. That button is already connected to the `guess` function via the `onclick` attribute on the card element. You can see this in the `generateBoard` function.
Expand All @@ -79,19 +85,23 @@ Inside the `checkMyGuess` function you should;
- Hide the game board

## Bonus step - Want to restart?

To really finish this up you might want to make sure that the player can restart the game. The only thing you need to do then is to connect the `'Play again'` button (and maybe also the `'Restart'` button) with the `start` function. To start the game over again. You also need to make sure to not show the win/lose screen when the game starts and you want to make sure to actually set the game board to be shown when the game starts. (Since we just did the opposite in step 6)

## Requirements

- The board with characters should be generated when the website is loaded.
- A randomly selected person should be set as the secret when the game starts.
- You should be able to select questions to ask about the people and filter the board based on those questions.
- You should also give the player feedback with alerts
- You should be able to guess the secret person and get an answer if it's correct or not.

## Stretch goals

So you’ve completed the requirements? Great job! Make sure you've committed and pushed a version of your project before starting on the stretch goals. Remember that the stretch goals are optional.

### Intermediate stretch goals

- Check the bonus step
- Change the array of objects:
- Add more information about the people, and with this add the possibility to ask questions and filter the board in regards to these addons.
Expand All @@ -100,6 +110,7 @@ So you’ve completed the requirements? Great job! Make sure you've committed an
- Change the styling to be as you want it!

### Advanced stretch goals

- Create a timer that measures how long time each game takes.
- Add sound effects and/or animations when flipping a card or winning the game.
- Create the possibility to add a player name when starting the game.