если заявление — ящерица с бумажными ножницами в переполнении стека

Так что я новичок в PHP и создаю реализацию RPSLS, просто для выполнения в командной строке. У меня есть полуработающая реализация, но есть две проблемы.

1) Код ниже, кажется, не соответствует условию else, когда игрок 2 побеждает игрока первого, и я не могу определить, почему?

2) Это невероятно повторяющийся набор условных выражений. Что будет более эффективной реализацией? Мне бы очень хотелось понять, как сделать это лучше.

Спасибо

<?php

// Assign moves to integers (1 = Rock, 2 = Paper, 3 = Scissors, 4 = Lizard, 5 = Spock)
echo 'Welcome to Rock, Paper Scissors, Lizard, Spock';
echo "\n";

// Randomize Moves
$player1 = rand(1, 5);
$player2 = rand(1, 5);

// Declare wins
$rock_wins = array(3, 4);
$paper_wins = array(1, 5);
$scissors_wins = array(2, 4);
$lizard_wins = array(5, 2);
$spock_wins = array(3, 1);

// Conditional logic for wins
if ($player1 == $player2) {
echo "Tie.";
echo "\n";
} elseif ($player1 == 1) {
if (in_array($player2, $rock_wins)) {
echo "Player 1 wins";
echo "\n";
}
} elseif ($player1 == 2) {
if (in_array($player2, $paper_wins)) {
echo "Player 1 wins";
echo "\n";
}
} elseif ($player1 == 3) {
if (in_array($player2, $scissors_wins)) {
echo "Player 1 wins";
echo "\n";
}
}
elseif ($player1 == 4) {
if (in_array($player2, $lizard_wins)) {
echo "Player 1 wins";
echo "\n";
}
}
elseif ($player1 == 5) {
if (in_array($player2, $spock_wins)) {
echo "Player 1 wins";
echo "\n";
}
} else {
echo "Player 2 wins";
}

?>

3

Решение

Вы можете закодировать логику в 2-мерном массиве:

<?php
$play = function ($player1, $player2) {
$rock = 1;
$paper = 2;
$scissors = 3;
$lizard = 4;
$spock = 5;
$matches = array(
$rock => array($scissor, $lizard),
$paper => array($rock, $spock),
$scissors => array($paper, $lizard),
$lizard => array($spock, $paper),
$spock => array($scissor, $rock),
);

return in_array($player2, $matches[$player1]);
};

// Assign moves to integers (1 = Rock, 2 = Paper, 3 = Scissors, 4 = Lizard, 5 = Spock)
echo 'Welcome to Rock, Paper Scissors, Lizard, Spock';
echo "\n";

// Randomize Moves
$player1 = rand(1, 5);
$player2 = rand(1, 5);

if ($player1 == $player2) {
echo "Draw!\n";
} else if (Game::play($player1, $player2)) {
echo "Player 1 wins\n";
} else {
echo "Player 2 wins\n";
}

Очевидно, улучшения бесконечны:

  • Вы можете заменить функцию с замыканием (либо класс с play метод или вложенная функция внутри фабричной функции) в 2d-массиве, так что вы не создаете его экземпляр при каждом вызове
  • вы можете использовать константы вместо переменных для значений рока, бумаги и т. д.
  • вы должен проверить, что входные данные находятся в пределах набора допустимых значений, и так далее.

    <?php
    class Game {
    const ROCK = 1;
    const PAPER = 2;
    const SCISSORS = 3;
    const LIZARD = 4;
    const SPOCK = 5;
    const MATCHES = array(
    self::ROCK => array(self::SCISSOR, self::LIZARD),
    self::PAPER => array(self::ROCK, self::SPOCK),
    self::SCISSORS => array(self::PAPER, self::LIZARD),
    self::LIZARD => array(self::SPOCK, self::PAPER),
    self::SPOCK => array(self::SCISSOR, self::ROCK),
    );
    
    public static function play($player1, $player2) {
    if (!self::isValid($player1) || !self::isValid($player2)) {
    throw new Exception('Invalid input!');
    }
    return in_array($player2, self::matches[$player1]);
    }
    
    public static function isValid($num) {
    return array_key_exists(self::MATCHES, $num);
    }
    }
    
3

Другие решения

Как сказал Марк Б в комментариях, есть более эффективные способы решения этой проблемы, но в вашей ситуации причина, по которой игрок 2 никогда не выиграет, заключается в том, что у вас есть это как еще одно условие, основанное на том, что $player1 равно. Вы должны иметь другое основанное на $player2 находится в массиве.

Просто удалите внутреннюю часть, если есть ограничения, и вы получите:

if ($player1 == $player2) {
echo "Tie.";
echo "\n";
} elseif ($player1 == 1) {

} elseif ($player1 == 2) {

} elseif ($player1 == 3) {

} elseif ($player1 == 4) {

} elseif ($player1 == 5) {

} else {
echo "Player 2 wins";
}

Единственный возможный способ выиграть 2 игрока — это если $player2 не равно $player1 а также $player1 не равно 1 через 5,

Так что если вы установите $player1 в 6Игрок 2 «победит», но это не имеет смысла в контексте игры.

1

Вы говорите, что вы новичок в php, и я предполагаю, что вы относительно новичок в программировании. Имея это в виду, я бы сосредоточился на некоторых основных принципах.

Итак, чтобы ответить на ваш вопрос 2), вот несколько вещей, которые стоит рассмотреть:

  • Добавьте хорошие комментарии к своему коду — здесь было бы полезно
    документировать правила RPSLS. Я должен был искать правила для этого
    игра, и похоже, что по крайней мере один человек неправильно понял
    правила. Я считаю, что способы решения проблемы часто становятся ясными
    когда я пишу комментарии.

  • Используйте константы для значений, которые не будут меняться, т.е.
    ROCK вместо 1, PAPER вместо 2 и т. Д. Другие языки имеют
    перечисления для этой цели, но в PHP вы можете использовать «определить» для
    свяжите каждую именованную константу с ее значением. Это должно значительно облегчить чтение программы и облегчить обнаружение любых ошибок — если вы попытаетесь использовать константу, которая не была определена, вы получите предупреждение.

  • Если возможно, структура программы должна соответствовать «логическому»
    думать о проблеме. Например суть программы
    как следует:

    if (player 1 beats player 2) {
    echo "Player 1 wins\n";
    }
    elseif (player 2 beats player 1) {
    echo "Player 2 wins\n";
    }
    else {
    echo "Tie.";
    }
    

Взяв их вместе, вот альтернативный способ сделать то, что вы хотите:

<?php

// As we'll use these as array indices, we'll start at 0
define ('ROCK', 0);
define ('PAPER', 1);
define ('SCISSORS', 2);
define ('LIZARD', 3);
define ('SPOCK', 4);

/*
A reasonable place to document the rules ....
*/
$winning_conditions = array();
$winning_conditions[ROCK] = array(SCISSORS, LIZARD);
$winning_conditions[SCISSORS] = array(PAPER, LIZARD);
$winning_conditions[LIZARD] = array(SPOCK, PAPER);
$winning_conditions[SPOCK] = array(SCISSORS, ROCK);
$winning_conditions[PAPER] = array(ROCK, SPOCK);

// Randomize Moves
$player1 = rand(0, 4);
$player2 = rand(0, 4);

if (in_array($player2, $winning_conditions[$player1]) {
echo "Player 1 wins\n";
}
elseif (in_array($player1, $winning_conditions[$player2]) {
echo "Player 2 wins\n";
}
else {
echo "Tie.\n";
}

?>

И с несколькими дополнениями (возможно, с использованием ассоциативных массивов php) должно быть возможно улучшить вывод до чего-то вроде:

Player 2 wins (Lizard poisons Spock)
0
По вопросам рекламы [email protected]