I am a very beginner in JavaScript / jQuery and got some difficulties with my code.
I am writing "Guess the word game" and the problem itself is that I have a 6-letters-length shuffled word from array and I need to place only one letter for one of 6 buttons. I have 6 buttons named from Letter1 to Letter6. Please, look through my code and say where is a mistake in placing it, thanks in advance. The code :
String.prototype.shuffle = function () {
var a = this.split(""),
n = a.length;
for (var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return a.join("");
}
$("#start").on('click', function () {
var rand = Math.floor(Math.random() * words.length);
var shuffledWord = words[rand].shuffle();
/*alert (shuffledWord);*/
for (var i = 0; i < shuffledWord.length; i++) {
$('Letter1').text(shuffledWord[i]);
$('Letter2').text(shuffledWord[i]);
$('Letter3').text(shuffledWord[i]);
$('Letter4').text(shuffledWord[i]);
$('Letter5').text(shuffledWord[i]);
$('Letter6').text(shuffledWord[i]);
}
});
The code itself works well, the problem is that I am doing something wrong with Letters.
You probably just need to make it $('#Letter1') etc.--i.e., I think you left off the # in referring to the letter elements.
Related
This is my first ever question, please give me feedback if I suck at this. Thank you
I am trying to create a JavaScript terminal game from a paid course. The game is called 'Find My Hat'.
One section of the problem requires me to create a static method called generateField(). This method generates a field, on the field there are 4 possible characters:
hat = '^';
hole = 'O';
fieldCharacter = '░';
pathCharacter = '*';
The fieldCharacter is the background for the game area. The game area is comprised of nested arrays. I haven't had problems creating the field, but I also want to replace random fieldCharacters with holes. I tried this with Math.random and nested loops to iterate over the nested arrays. I have not been able to figure out how to get this to work.
Here is the code below, sorry if I missed any details, I will try respond to everyone I can.
class Field {
constructor(field) {
this._field = field;
}
print() {
this._field = field.join('\n');
console.log(this._field.replace(/,/g, ''))
}
static generateField(height, width) {
let finalArray = []
for (let i = 0; i < height; i++) {
finalArray.push([fieldCharacter.repeat(width)]);
}
for (let i = 0; i < finalArray.length; i++) {
let randomHole = () => {
let result = Math.random() * width;
return result;
}
for (let j = 0; j < finalArray[i].length; j++) {
if (randomHole() > width - 2) {
finalArray[i][j] = hole;
}
}
}
return finalArray.join('\n').replace(/,/g, '');
}
}
console.log(Field.generateField(5, 10));
One Random Output:
O
O
░░░░░░░░░░
░░░░░░░░░░
O
Example for good output:
░░░░O░░░░░
░░░O░OO░░░
░░O░░░O░░░
░░░░O░░░░░
OO░░░░O░░O
I did some changes to your code and use the stackoverflow snippet to show you how it works
String.prototype.replaceAt = function(index, replacement) {
return this.substr(0, index) + replacement + this.substr(index + replacement.length);
}
hat = '^';
hole = 'O';
fieldCharacter = '░';
pathCharacter = '*';
class Field {
constructor(field) {
this._field = field;
}
print() {
this._field = field.join('\n');
console.log(this._field.replace(/,/g, ''))
}
static generateField(height, width) {
let finalArray = []
for (let i = 0; i < height; i++) {
finalArray.push(fieldCharacter.repeat(width));
}
//i dont know why you did this loop but i changed the inside for marking random holes
for (let i = 0; i < finalArray.length; i++) {
//pick random x and y
let randomHoleX = Math.floor(Math.random() * width);
let randomHoleY = Math.floor(Math.random() * height);
//becouse you save array of strings you need to find the correct array and replace the char at the correct index.
finalArray[randomHoleY] = finalArray[randomHoleY].replaceAt(randomHoleX, hole);
}
return finalArray.join('\n').replace(/,/g, '');
}
}
console.log(Field.generateField(5, 10));
I have written this js code for palindrome, I know there are better and more efficient palindrome methods online but I want to know why I am unable to get my palindrome function to work properly?
CODE:
var pal = function(str) {
var len = str.length;
for (var i = 0; i < len; i++) {
var comp1 = str.substring(i, i + 1);
for (var j = len; j > 0; j--) {
var comp2 = str.substring(j - 1, j);
}
if (comp1 != comp2) {
console.log("not palindrome")
break;
} else {
console.log('palindrome')
}
}
}
pal('maddog');
OUTPUT :
palindrome
not palindrome
There are lot of better algorithms to check Palindrome. Let use the similar algorithm that you are using.
We basically use two pointers - left and right, and move to middle at the same time. In the original question, left pointer and right pointer doesn't move at the same time.
Pointers should move like this -
a b c b a
^ ^
a b c b a
^ ^
a b c b a
^
var isPalindrome = function (str) {
for (var i = 0, j = str.length-1; i < j; i++ , j--) {
if (str[i] != str[j]) {
return false;
}
}
return true;
}
console.log('maddog : ' + isPalindrome('maddog'));
console.log('abcba : ' + isPalindrome('abcba'));
console.log('deed : ' + isPalindrome('deed'));
console.log('a : ' + isPalindrome('a'));
Try the following code. It works by dividing the string length by 2, and then iterating up, checking mirroring characters against each other:
var pal = function(str){
var len = str.length;
for(var i = 0; i < Math.floor(len/2); i++){
if(str[i] != str[(len-1)-i]){
return false;
}
}
return true;
}
console.log(pal("bunny"));
console.log(pal("amoreroma"));
The inner loop is totally unnecessary. It does the same thing every time -- it loops through the whole string, starting from the end, repeatedly setting comp2 to the character; when it's done, comp2 always contains the first character. So your function just tests whether every character in the string is the same as the first character.
To test if something is a palindrome, you need to compare each character with the corresponding character from the other end of the string. You don't need two loops for this. You also only need to loop through the first half of the string, not the whole string.
Finally, you should only echo Palindrome at the end of the loop. Inside the loop you only know that one character matches, not all of them.
var pal = function(str) {
var len = str.length;
var half = Math.floor(len / 2);
var isPal = true;
for (var i = 0; i < half; i++) {
var comp1 = str[i];
var comp2 = str[len - i - 1];
if (comp1 != comp2) {
console.log("not palindrome")
isPal = false;
break;
}
}
if (isPal) {
console.log('palindrome')
}
}
pal('maddog');
pal('maddam');
You don't really need the nested loops, you can just loop backwards through the string to invert the string and then compare it to the original string. I updated the Snippet to work.
Before, your code was not inverting the string but rather just iterating through the characters and assigning them to the comp1 and comp1 variables. You need to concatenate the strings in order to build the new string backwards comp = comp + str.substring(j-1, j);
var pal = function(str) {
var len = str.length;
var comp = '';
for (var j = len; j > 0; j--) {
comp = comp + str.substring(j - 1, j);
}
if (str !== comp) {
console.log("not palindrome")
return;
}
console.log('palindrome')
}
pal('arepera');
Can someone tell me why this bit of JavaScript is buggy?
I have HTML also, but I don't want to make this a massive code dump.
<script type = 'text/javascript'>
var playerCards = [];
var dealerCards = [];
function deal() {
var newCard = Math.random() % 12;
var newCard2 = Math.random() % 12;
playerCards += newCard;
playerCards += newCard2;
var counter = 0;
for (var i = 0; i < playerCards.length; ++i) {
counter += i;
}
document.getElementById("playerTotal").innerHTML = counter;
var dCounter = 0;
for (var j = 0; j < playerCards.length; ++j) {
dCounter += j;
}
document.getElementById("dealerTotal").innerHTML = dCounter;
}
</script>
I'm gonna assume this is a silly syntax error someplace, but I can't find it.
I'm guessing that this isn't doing what you expect it to:
playerCards += newCard;
playerCards += newCard2;
Try this instead:
playerCards.push(newCard);
playerCards.push(newCard2);
The first snippet is trying to "add" a number to an array, which doesn't exactly make sense. Through some arcane JavaScript rules, this turns the result into a string.
I'm guessing that you want to concatenate to an array instead.
Math.random returns a number between 0 and 1 - so Math.random() % 12 will probably be zero
var playerCards = [];
playerCards += newCard; //
what are you even trying to do there?
var counter = 0;
for (var i = 0; i < playerCards.length; ++i) {
counter += i;
}
if playerCards had a length, this loop would result in counter having value of 0, 1, 3, 6, 10 .. n(n+1) / 2 - probably not what you intended, but who knows
I'm doing "fifteen puzzle" game. I'm only a beginner, so I chose this project to implement. My problem is shuffle algorithm :
function shuffle() {
$('td').empty();
var p = 0;
var f = 0;
do {
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var rand = arr[Math.floor(Math.random() * arr.length)];
if ($('#' + rand).is(':empty')) {
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
} else {}
} while (f < 15)
That works cool, but I've heard that almost 50% of all random shuffle like mine is unsolvable. So I found math formula at wikipedia.org for this game, explaining how you can avoid that.
Here's modified algorithm that doesn't work either. The way I know it is alert stuff: it launches only 2 times instead of 31.
array = [];
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
array[i] = new Array();
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array[i].push(j)
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
The question is the same:
What's wrong? Two-dimensional array doesn't work.If you've got any questions - ask.
Just to make it clear: 2 for loops with i and j should make a 2-dimensional array like this [ this is " var i" -->[1,3,4,5,7], this is "var i" too-->[5,7,9,14,15]]. Inside each i there's j. The for loop with var a should count the number of js inside each i. if the number of js is even, the code is finished and shuffle's accomplished, otherwise shuffle should be made once again.
var nextId = cerIdNum + j;
in that fiddle, I don't see this cerIdNum declared & defined neither as local nor as global variable, I suppose that is curIdNum
Please use the below definition of algorithm and let us know if this works. Basically, the alert messages would come only twice, since there were usages of undefined variables. For the purpose of illustration, I have placed comments at where the problem points occured. Due to these problems, your script would stop executing abruptly thereby resulting in the behavior you described.
Oh and by the way - I did not have time to go through the Wiki link provided - hence you will have to verify your logic is correct. However, I have definitely resolved the errors causing the behavior you observed.
As an aside - consider using jQuery, your code will be a lot cleaner...
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array.push(j) //array[i].push does not make sense
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array.length; //array[1].length does not make sense
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
I found the solution by totally rewriting the code. Thank everyone for help!
Here's what do work:
function shuffle (){
press = 1;
$('td').empty().removeClass();
p=0;
var f;
do {
var arr=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var rand=arr[Math.floor(Math.random()*arr.length)];
if ($('#'+ rand).is(':empty')){
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
}
else{}
}while(f < 15){
winChance();
}
}
function winChance (){
array = [];
for (i=1;i<16;i++){
array[i]= new Array();
var currentId = $('#' + i).attr('id');
var currentIn = $('#' + i).html()
var currentIdNum = parseInt(currentId, 10);
var currentInNum = parseInt(currentIn, 10);
for (j=1;j<16;j++){
var nextId = currentIdNum + j;
if (nextId < 16){
var nextIn = $('#' + nextId).html();
var nextInNum = parseInt(nextIn, 10);
if (currentInNum > nextInNum){
array[i].push(j);
}
}
}
}
checkSum();
}
function checkSum(){
var sum = 0;
for (var a=1; a<16; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){}
else {
shuffle();
}
}
var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
alert(swf[i]); // swf[1] >> 2.swf
This case ,Random output One number.
How to Random output two different numbers ?
var swf = ['1.swf', '2.swf', '3.swf'],
// shuffle
swf = swf.sort(function () { return Math.floor(Math.random() * 3) - 1; });
// use swf[0]
// use swf[1]
Even though the above should work fine, for academical correctness and highest performance and compatibility, you may want to shuffle like this instead:
var n = swf.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = swf[i];
swf[i] = swf[j];
swf[j] = tmp;
}
Credits to tvanfosson and Fisher/Yates. :)
You can use splice to remove the chosen element, then simply select another randomly. The following leaves the original array intact, but if that's not necessary you can use the original and omit the copy. Shown using a loop to demonstrate how to select an arbitrary number of times upto the size of the original array.
var swf=["1.swf","2.swf","3.swf"];
var elementsToChoose = 2;
var copy = swf.slice(0);
var chosen = [];
for (var j = 0; j < elementsToChoose && copy.length; ++j) {
var i = Math.floor(Math.random()*copy.length);
chosen.push( copy.splice(i,1) );
}
for (var j = 0, len = chosen.length; j < len; ++j) {
alert(chosen[j]);
}
I would prefer this way as the bounds are known (you are not getting a random number and comparing it what you already have. It could loop 1 or 1000 times).
var swf = ['1.swf', '2.swf', '3.swf'],
length = swf.length,
i = Math.floor(Math.random() * length);
firstRandom = swf[i];
// I originally used `delete` operator here. It doesn't remove the member, just
// set its value to `undefined`. Using `splice` is the correct way to do it.
swf.splice(i, 1);
length--;
var j = Math.floor(Math.random() * length),
secondRandom = swf[j];
alert(firstRandom + ' - ' + secondRandom);
Patrick DW informed me of delete operator just leaving the value as undefined. I did some Googling and came up with this alternate solution.
Be sure to check Tvanfosson's answer or Deceze's answer for cleaner/alternate solutions.
This is what I would do to require two numbers to be different (could be better answer out there)
var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
var j;
do {
j = Math.floor(Math.random()*swf.length);
} while (j === i);
alert(swf[i]);
alert(swf[j]);
Edit: should be j===i