Я относительно новичок в Javascript и программировании в целом. Сегодня, когда я писал простой симулятор броска тройного кубика, я столкнулся с проблемой, которую решил решить, но до сих пор не понимаю. Вот мой код ...

//                      ROLLING TRIPLES

var diceSides = 6;
var diceOne = Math.floor(Math.random() * diceSides + 1);
var diceTwo = Math.floor(Math.random() * diceSides + 1);
var diceThree = Math.floor(Math.random() * diceSides + 1);
var rolls = 3;

while ((diceOne !== diceTwo) || (diceTwo !== diceThree)) {
    console.log("Dice 1: " + diceOne);
    diceOne = Math.floor(Math.random() * diceSides + 1);
    console.log("Dice 2: " + diceTwo);
    diceTwo = Math.floor(Math.random() * diceSides + 1);
    console.log("Dice 3: " + diceThree);
    diceThree = Math.floor(Math.random() * diceSides + 1);
    console.log("Rolling again");
    rolls += 3;
}
console.log("Dice 1: " + diceOne);
console.log("Dice 2: " + diceTwo);
console.log("Dice 3: " + diceThree);
console.log("Rolled a triple!!!");

console.log(rolls);

Проблема заключается в условии 'while': while ((diceOne! == diceTwo) || (diceTwo! == diceThree))

Использование '||' , программа функционирует должным образом и выходит из цикла while, когда diceOne = diceTwo = diceThree, то есть вы бросаете тройку. Однако для меня это не имеет смысла ... Использование '||' может показаться, что цикл while завершится, условие будет ложным, и только ДВА кубика будут равны ...

Например он вернет результат вроде:

Dice 1: 4
Dice 2: 4
Dice 3: 6
Rolled a triple!!!

Потому что в этом случае diceOne ДЕЙСТВУЕТ равняется diceTwo, даже если diceTwo не равно diceThree. В этом случае, используя '||' оператора, я бы ожидал, что цикл while остановится, потому что кажется, что условие было выполнено ... Но это не так, он вернет:

Dice 1: 4
Dice 2: 4
Dice 3: 6
Rolling again

... То, что я ожидал бы от оператора '&&: За исключением оператора '&&', код возвращает то, что я ожидал с помощью '||' оператор:

Dice 1: 4
Dice 2: 4
Dice 3: 6
Rolled a triple!!!

Код завершается, даже если тройка не была выброшена. Вот как это звучит у меня в голове с оператором '&&' ...

«Если diceOne и diceTwo И diceThree равны, вы выбросили тройку».

С "||" оператор ...

«Если diceOne и diceTwo равны, ИЛИ diceTwo и diceThree равны, вы выбросили тройку».

Чего у вас явно нет, потому что только два из трех кубиков одинаковые.

Я знаю, что продолжаю, продолжаю и продолжаю ... Мне сложно это объяснить. Вероятно, есть действительно простое объяснение, но меня это действительно беспокоит!

Кстати, есть ли какой-либо ярлык, который я могу использовать для генерации случайного числа несколько раз без необходимости набирать Math.floor (Math.random ..... Я не могу назначить его переменной и ввести переменную, потому что это генерирует случайное число один раз и использует это число каждый раз, когда встречает переменную. Есть ли более эффективный способ сделать это?

Ура

0
Sam McLennan 16 Дек 2016 в 04:37

2 ответа

Вы можете использовать ИЛИ или И, они могут быть преобразованы из одного в другой с помощью Законов Де Моргана .

dice1 != dice2 || dice2 != dice3

Эквивалентно:

! (dice1 == dice2 && dice2 == dice3)

Первое выражение говорит: «пока первые два кубика не равны ИЛИ вторые два кубика не равны» (т.е. одно из двух равенств неверно).

Второе выражение говорит: «while NOT (первые два кубика равны И вторые два кубика равны)» (т.е. одно из двух равенств неверно).

Для такого рода вещей полезно использовать таблицу истинности, она может помочь вам визуализировать логическое комбинации.

Что касается вашего примечания, генерации случайных чисел, вы делаете это правильно. Вам нужно каждый раз получать новый номер, поэтому вам придется каждый раз звонить Math.random().

Вы можете извлечь это в функцию, чтобы она была чище, когда вы хотите ее использовать:

function generateRandom(diceSides) {
    return Math.floor(Math.random() * diceSides + 1);
}

А затем используйте его так:

var diceOne = generateRandom(diceSides);
0
Matt 16 Дек 2016 в 04:54

Вы правильно понимаете логические операторы, вы не понимаете, как работает while. Когда условие выполнено, он продолжает цикл, он останавливается, когда условие не выполняется.

Таким образом, когда только две кости равны, одно из условий != будет истинным, поэтому условие || также будет истинным, поэтому цикл будет продолжен. Когда все три кубика равны, оба условия != будут false, а false || false также будет false, поэтому цикл останавливается.

В некоторых языках есть инструкция until, которая похожа на while, но инвертирует условие, так что цикл останавливается, когда условие истинно. Это сработает так, как вы описываете.

0
Barmar 16 Дек 2016 в 05:09