Так что я новичок в 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";
}
?>
Вы можете закодировать логику в 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);
}
}
Как сказал Марк Б в комментариях, есть более эффективные способы решения этой проблемы, но в вашей ситуации причина, по которой игрок 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 «победит», но это не имеет смысла в контексте игры.
Вы говорите, что вы новичок в 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)