I should start off by saying that I am SUPER new to this (not just stack overflow, but also any sort of coding in general). I'm taking a very basic intro course right now, and one of our assignments is to create a tic-tac-toe game in an HTML box.
I searched for answers to this question specifically, but anything I found was extremely difficult for me to comprehend (note: writing this code is the most complex coding I have done so far in my life, so that's what level I'm at).
I understand the dynamics of creating the space (table) for the game, and embedding the buttons into the different cells to give players choices. However, for extra credit they've offered us the choice of making the code determine who the winner is. Any insight on where to start with this would be much appreciated.
I'm not even certain where to start, but I imagine that I need to write another javascript code to add into the game. Here's what I have so far (I have only included one row in order to minimize the length of this post):
function RowOneBoxThreeYButton() {
var x = document.getElementById("Initial_Choice_Row_One_Box_Three");
x.innerHTML = "Y";
x.style.color = "white";
}
function RowOneBoxThreeXButton() {
var x = document.getElementById("Initial_Choice_Row_One_Box_Three");
x.innerHTML = "X";
x.style.color = "white";
}
function RowOneBoxTwoYButton() {
var x = document.getElementById("Initial_Choice_Row_One_Box_Two");
x.innerHTML = "Y";
x.style.color = "white";
}
function RowOneBoxTwoXButton() {
var x = document.getElementById("Initial_Choice_Row_One_Box_Two");
x.innerHTML = "X";
x.style.color = "white";
}
function RowOneBoxOneYButton() {
var x = document.getElementById("Initial_Choice_Row_One_Box_One");
x.innerHTML = "Y";
x.style.color = "white";
}
function RowOneBoxOneXButton() {
var x = document.getElementById("Initial_Choice_Row_One_Box_One");
x.innerHTML = "X";
x.style.color = "white";
}
<html>
<body>
<table style="width:100%; background-color:black" border="2">
<tr>
<td>
<p id="Initial_Choice_Row_One_Box_One" style="color:white">Click a Button to Choose "X" or "Y"</p>
<button onclick="RowOneBoxOneXButton()">Choose X</button>
<button onclick="RowOneBoxOneYButton()">Choose Y</button>
</td>
<td>
<p id="Initial_Choice_Row_One_Box_Two" style="color:white">Click a Button to Choose "X" or "Y"</p>
<button onclick="RowOneBoxTwoXButton()">Choose X</button>
<button onclick="RowOneBoxTwoYButton()">Choose Y</button>
</td>
<td>
<p id="Initial_Choice_Row_One_Box_Three" style="color:white">Click a Button to Choose "X" or "Y"</p>
<button onclick="RowOneBoxThreeXButton()">Choose X</button>
<button onclick="RowOneBoxThreeYButton()">Choose Y</button>
</td>
</tr>
</body>
</html>
Thanks so much everyone! And sorry if my formatting is wrong/I didn't search hard enough or properly for this answer. Happy to improve in all aspects (including formatting my posts here!).
One very important concept in programming is not repeating yourself. You have written essentially the same function six times over. OK, there are some minor differences, like using a different element id each time, and showing either an "X" or a "Y". But the flow of each function is essentially the same.
One thing you want to do is collapse all of those repetitions into one function, but use variables to make that one function behave differently depending on what just happened. You can do that by entering parameters into the function call. In this case, each button click sends different a different row number, box number and letter choice string to the same function.
Note that the row and box numbers start with zero rather than one, even though your id's have names that use "One" as the first "number". Get used to starting to count from 0 instead of 1. It happens a lot in coding.
Use those passed in values to select a different x each time, and to show a different letter each time.
To check if there is a winner, you first of all need to have some way of remembering all the values in the game. One way is to use an array. I don't know if you have learned about arrays yet, but here's a quick lesson:
var myArray = ["A", "B", "C", "D"];
alert(myArray[0]); // shows "A"
alert(myArray[2]); // shows "C"
myArray[2] = "blah blah";
alert(myArray[2]); // shows "blah blah";
Each time someone clicks a button, remember their choice in the array. That way they can be checked. Now, also each time someone clicks a button, check to see whether all the array values are the same as the most recently chosen value. If they are, then you have a winner, at least in this one-dimensional version of tic-tac-toe. Of course, it would be slightly more complicated in a full 3x3 game, but most of the same concepts would apply.
Well, best of luck with your programming...
var textNumbers = ["One", "Two", "Three"]; // this array allows you to recreate the id's using array positions
var choices = ["", "", ""]; // this is where the letter choices will be remembered
function makeMove(row, box, letter) { // this function is called every time any button
// with this 'onclick' handler is clicked
// it will be passed the values seen in each
// button element onclick attribute value
// this single row allows you to recreate all the id's using the values passed in to the function
var x = document.getElementById("Initial_Choice_Row_" + textNumbers[row] + "_Box_" + textNumbers[box]);
// this allows you to pass either "X" or "Y" into the element, depending on which button was clicked
x.innerHTML = letter;
x.style.color = "white";
// remember the choice that was just made by putting the latest letter choice
// into the choices array at the position for this box
choices[box] = letter;
// create a place to hold a message
var msg;
// after each click, check if there is now a winner
// i.e. check if all boxes in this row are the same as the latest choice
if (
(choices[0] === letter) && // if the remembered choice for the first box is the latest choice AND
(choices[1] === letter) && // if the remembered choice for the second box is the latest choice AND
(choices[2] === letter) // if the remembered choice for the third box is the latest choice
) { // ...then announce the new winner
msg = "We have a winner! ===> The '" + letter + "' team!";
} else { // otherwise, continue to say that there is no winner
msg = "No winner yet.";
}
// show the message
var y = document.getElementById("winner");
y.innerHTML = msg;
}
<table style="width:100%; background-color:black" border="2">
<tr>
<td>
<p id="Initial_Choice_Row_One_Box_One" style="color:white">Click a Button to Choose "X" or "Y"</p>
<button onclick="makeMove(0, 0, 'X')">Choose X</button>
<button onclick="makeMove(0, 0, 'Y')">Choose Y</button>
</td>
<td>
<p id="Initial_Choice_Row_One_Box_Two" style="color:white">Click a Button to Choose "X" or "Y"</p>
<button onclick="makeMove(0, 1, 'X')">Choose X</button>
<button onclick="makeMove(0, 1, 'Y')">Choose Y</button>
</td>
<td>
<p id="Initial_Choice_Row_One_Box_Three" style="color:white">Click a Button to Choose "X" or "Y"</p>
<button onclick="makeMove(0, 2, 'X')">Choose X</button>
<button onclick="makeMove(0, 2, 'Y')">Choose Y</button>
</td>
</tr>
</table>
<p id="winner">No winner yet.</p>
Related
I have a table where a user inputs info for the DB. The 2 fields here are
"type" and "name". Type must be either "L" or "S", but it is depicted to user as "Large" or "Small".
Say the user needs a new row for more data. I have 2 buttons, "Large" and "Small", that
fire the same JS function to create a new row. I want the value from the button to be
input into the new row in the type column. How would I accomplish this?
I'd like to do this using the clone.node function somehow, but the HtmlHelpers are throwing me off as well.
<tr id=rowToClone>
<td style="width:30px">
#Html.DropDownList("manifests.Type",
new SelectList(new List<Object>
{
new { value = "L", text = "Large"},
new { value = "S", text = "Small"},
},
"value",
"text"
)
)
</td>
<td>
#Html.TextBox("manifests.Name")
</td>
</tr>
<input type="button" value="Add Large" id="btAddL" style="display: none; float:left" onclick="addRow('L')"/>
<input type="button" value="Add Small" id="btAddS" style="display: none; float: left" onclick="addRow('S')"/>
<script>
function addRow(type) {
document.getElementById("btAddL").style.display = "none";
document.getElementById("btAddS").style.display = "none";
var row = document.getElementById("rowToClone");
var table = document.getElementById("tableToClone");
var clone = row.cloneNode(true);
clone.style.display = "table-row";
/*clone.node.td.type = type;*/
table.appendChild(clone);
}
</script>
This answer is purely from the perspective of the JS, I'm not sure about those ASP.NET helpers at the top...
I think that what you want within the clone you're trying to reach for the <td> cell? is that right?
I imagine this is what you are thinking because you've commented out clone.node.td
Probably you need to find the <td> element itself
var td_element = clone.querySelectorAll('td:first-child')
td_element.type = type; // this line makes no sense as <td> elements do not have types so maybe the line above should select for a kind of an HTML element that has a type
If the thing you want to clone is pretty small it could be easy (and a good exercise) just to create new elements instead of the cloning.
https://javascript.info/searching-elements-dom#querySelectorAll
https://www.w3schools.com/tags/att_type.asp
I am very new to Javascript and I was wondering if anyone could help me for what seems to be quite a simple question to anyone who knows anything about JS. My problem is that I am trying to change the value of my variables after declaring them but everytime I change their values they are set back to what they used to be when they got declared. If anyone could please explain how I could work my way around this problem it would be greatly appreciated, Here's my code if you want to see it:
//Anything before this doesn't matter for my question.
<td>
<p id="first"></p> <--- this prints the "first" var declared in the script bellow but is always equal to 1 even when the button is pressed
</td>
<th class="col-xs-1 align-middle text-center">
<div class="btn-group">
<a class="btn btn-default btn-sm btn-add-all" onclick="value_up(first);"> <--- this is the button that calls the function when pressed
<i class="fa fa-arrow-up"></i>
</a>
</div>
<script>
var first = 1; <--- this is where I declare my variable
document.getElementById("first").innerHTML = first; <--- Here's where I pass my variable to the <p> tags up above
</script>
</tbody>
</table>
</div>
</div>
</div>
<script>
function value_up(x) { <--- this is the function I am calling when I press the up button
x = x - 1;
console.log(x);
return (x);
}
</script>
You're returning x but never setting first to x. As such, first never changes. Values are passed in by value in javascript and so you need to change the value of first directly instead of just passing it in.
You also need to reupdate the value that your HTML element holds. Please check the following example:
let first = 0
document.getElementById("first-val").innerHTML = first;
let increment_first = () =>{
first += 1
document.getElementById("first-val").innerHTML = first;
}
<p> Value of first: <span id="first-val"></span></p>
<button onclick="increment_first()">Increment!</button>
To be slightly more robust pass the id and then get/set using the passed id
var first = 1;
document.getElementById("first").innerHTML = first;
function value_up(id) {
var x = parseInt(document.getElementById(id).textContent)
x+=1 // or whatever operation you want
document.getElementById(id).innerHTML = x
}
<p id="first"></p>
<input type="button" value="UP" onclick="value_up('first');">
I am trying to get the element with the ID 1a, 2a, 3a etc. according to whenever the function is run.
It then compares that elements value (using jQuery) with the value of the input where the function is wrong
It brings up an error saying:
TypeError: var1.toUpperCase is not a function. (in 'var2.toUpperCase()','var1.toUpperCase' is undefined)
Any help would be appreciated.
Thanks
(UPDATE usually there would be text in questionNumber like: 1, 2, 3 etc every time the another function is run.)
EDIT: Every time a different function is run, questionNumber is increased by 1. I save questionNumber's text in a variable called word. I then add the letter a to that variable. Then, I get the element that has ID of the variable word, then compare it's contents to the value of the input, but the comparison is uppercase to avoid problems. If they are equal, the input is replaced with a div with green text. Hope this makes it clearer.
function textVerify(item) {
var word= document.getElementById(($('#questionNumber').text()+'a'));
if (item.value.toUpperCase() === word.toUpperCase()){
item.style.color = "green";
$( item ).replaceWith( "<div style='color:green;'>"+word+"</div>" );
main()
} else {
item.style.color = "black";
}
<span class="ihide" id="questionNumber"></span>
<p id="1a" class="ihide">Seven</p>
<input id="1" name="Seven" type="text" value="" onkeyup="textVerify(this)" autofocus="">
The var word is p tag, so you need to get the inner text of it and compare it with the input text. Also, when replacing it, access the text() property of it. See below. main() is commented out here, but you can keep as per the need.
function textVerify(item) {
var word = document.getElementById(($('#questionNumber').text() + 'a'));
if (item.value.toUpperCase() === $(word).text().toUpperCase()) {
item.style.color = "green";
$(item).replaceWith("<div style='color:green;'>" + $(word).text() + "</div>");
//main()
} else {
item.style.color = "black";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<span class="ihide" id="questionNumber">1</span>
<p id="1a" class="ihide">Seven</p>
<input id="1" name="Seven" type="text" value="" onkeyup="textVerify(this)" autofocus="">
In your code ($('#questionNumber').text()+'a') this part returns just 'a', as text of the id questionNumber is nothing.
And in your HTML there is no such id. I think you need to make this changes to your HTML code:
<span class="ihide" id="questionNumber">1</span>
This should work.
EDIT: Also, can you please share the JS code associated with 'item', there can be an error in that part too.
Im a beginner learning Javascript, and I need some help...
I'm trying to make a game, and I want the user to be able to set his own time.
My code is the following:
HTML:
<div class='wrapper'>
<form id='nameForm'>
<div class='form-uname'>
<lable id='nameLable' for='nameField'>Create a username:</lable>
<input id='nameField' type='text' maxlength='25'></input>
</div>
<div class='form-sub'>
<button id='subButton' type='button'>Print your name!</button>
</div>
</form>
<div>
JavaScript:
function getUserName() {
var nameField = document.getElementById('nameField').value;
alert(nameField);
}
var subButton = document.getElementById('subButton');
subButton.addEventListener('click', getUserName, false);
The alert value is correct! But, when I put my variable nameField in the code below instead of 1000 (see last line), it doesn't work!
var Timer = window.setTimeout;
$shape.onclick = function(){
window.clearTimeout(Timer);
Timer = window.setTimeout(function(){
$gameOverp.innerHTML = "You run out of time :( <br /> GAME OVER!";
passedTime();
$gameOver.style.display = "block";
$shape.style.display = "none";
$gameInfop.innerHTML = "TRY AGAIN!";
$gameInfop.style.marginLeft = "280px";
}, 1000);
I know that I make nameField inside the function, but even when i make it at the beginning of my file, it doesn't work.
When I use x = 3000 and i put x instead of 1000, it works fine.
I hope you guys understand my problem, and if you have any questions I'll be happy to answer them!
What you have here is a problem with data types. The timeout function requires a number data type (3000, for example) and your variable is, by default, a string ("3000" - note the quotes).
You can convert a string to a number using the Number() function, like so:
nameField = Number(nameField);
There's an easier solution, though: you can change the input type from 'text' to 'number', which will validate for numerical entry and register the value as a number data type by default. MDN: HTML number input
More info on data types: MDN Javascript data types
So I got a 3 x 3 table wich looks like this:
<table align=left width="896px" class="tableCategories">
<tr class="trCategories">
<td class="tdCategories"><input type="button" id="P11" onclick="clickE()" value="E" /></td>
<td class="tdCategories"><input type="button" id="P12" onclick="clickS()" value="S" /></td>
<td class="tdCategories"><input type="button" id="P13" onclick="clickB()" value="B" /></td>
....
I just want that if the user clicks on one of the nine boxes all of the boxes changes their background images and the box which was clicked changes itself to a back button which references to the first 9 images. Like a submenu getting opened if one of the boxes being clicked.
So I tried it in my way but it does not work very well. If I click on one of the boxes it triggers both actions which is connected via id. So my thought was to change the id to, but then I thought maybe there is a smarter way to do that. So I wrote my problem here :D
Edit:
The javascript part is looking like this for every of the functions:
function clickE()
{
document.getElementById("P11").value = "Zurück";
document.getElementById("P11").onclick = clickBack;
document.getElementById("P12").value = "Restaurant";
document.getElementById("P12").onclick =clickCategory("restaurant");
document.getElementById("P13").value = "Imbiss";
document.getElementById("P13").onclick =clickCategory("imbiss");
document.getElementById("P21").value = "Bäckerei";
document.getElementById("P21").onclick =clickCategory("baeckerei");
document.getElementById("P22").value = "Fast Food";
document.getElementById("P22").onclick =clickCategory("fast_food");
document.getElementById("P23").value = "Süßes";
document.getElementById("P23").onclick =clickCategory("suesses");
document.getElementById("P31").value = "Cafe";
document.getElementById("P31").onclick =clickCategory("cafe");
document.getElementById("P32").value = "Bar";
document.getElementById("P32").onclick =clickCategory("bar");
document.getElementById("P33").value = "Kneipe";
document.getElementById("P33").onclick =clickCategory("kneipe");
}
I try it first with the labels because I think it will work with images the same way.
Being unsure of the long term application, I may have a starting point. The initial script provided could get a bit unwieldy if you ever want to extend, so there is now a "defineElements" method that could be used to configure your elements. Please note that argument paramaters have been added to the onclick event in the html as well.
The "defineElements" function returns an associative array object (eg key/value pairs), with each key being named after the html element id. The value of each key is also an associative array that contains the element id (eid), label (lbl) and event (evnt).
Short story long... when you click a button, the label for each button is changed and the appropriate click handler is assigned. If you click the button labeled "Back", the default click handler is reassigned to all.
This would also be an excellent candidate for jQuery if that is available to you.
Hopefully this will get you moving in the right direction:
HTML
<table>
<tr class="trCategories">
<tr class="trCategories">
<td class="tdCategories"><input type="button" id="P11" onclick="clickE(this.id)" value="E" /></td>
<td class="tdCategories"><input type="button" id="P12" onclick="clickS(this.id)" value="S" /></td>
<td class="tdCategories"><input type="button" id="P13" onclick="clickB(this.id)" value="B" /></td>
</tr>
</table>
== And the Javascript
function clickE(id){
var elementDef = defineElements(id);
for(var key in elementDef){
var propObj = elementDef[key];
//console.log(propObj);
document.getElementById(propObj.eid).value = propObj.lbl;
if(id == undefined)
document.getElementById(propObj.eid).onclick = function(){ clickE(this.id);} //--reassign default event
else
document.getElementById(propObj.eid).onclick = propObj.evnt;
}
}
function defineElements(id){
var elementArr = ['P11','P12','P13']; //--add your element id's to this array to extend, and then add a case for each within switch below
var definitionObj = {};
for(var i = 0; i < elementArr.length; i++){
switch(elementArr[i].toUpperCase()){
case 'P11':
definitionObj[elementArr[i].toUpperCase()] = { eid:elementArr[i].toUpperCase(), lbl:'Zuruck', evnt: function(){ clickCategory.call(this, "whatever"); } };
break;
case 'P12':
definitionObj[elementArr[i].toUpperCase()] = { eid:elementArr[i].toUpperCase(), lbl:'Restaurant', evnt: function(){ clickCategory.call(this,"restaurant"); } };
break;
case 'P13':
definitionObj[elementArr[i].toUpperCase()] = { eid:elementArr[i].toUpperCase(), lbl:'Imbiss', evnt: function(){ clickCategory.call(this,"imbiss"); } };
break;
}
}
if(id != undefined){
definitionObj[id]['evnt'] = function(){ clickBack.call(this); } //--assign the clickback function to the selected element based on id paramater
definitionObj[id]['lbl'] = 'Back';
}
return definitionObj;
}
function clickCategory(cat){
alert(cat);
}
function clickBack(){
clickE();
}