2014-11-26 3 views
3

Итак, я новичок в PHP и создаю реализацию RPSLS, которую нужно выполнить только в командной строке. У меня есть полуработающая реализация, но у меня две проблемы.Rock Paper Scissors Ящерица Спок в PHP

1) Код, кажется, не попадает в другое условие, когда игрок 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"; 
} 

?> 
+1

поскольку есть только 5 вариантов, просто установите массив 5x5 и поместите значение win/lose/tie в каждую позицию. например -1, 0, 1. тогда вы попадаете в простой поиск массива, чтобы получить состояние игры. –

+0

Что бы я сделал: $ messages = array («Player 1 побед», «Победители 2», «Ничья»); print ($ messages [rand (0, count ($ messages) - 1)]); – ehwas

ответ

4

Вы можете кодировать логику в 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); 
        } 
    } 
    
+1

Upvote. Выглядит чисто и легко. Мне нравится, как вы возвращаете true или false, но одна проблема, которую я вижу, - это тот факт, что вам нужно проверить, равны ли '$ player1' и' $ player2' вне функции. Просто мозговой штурм здесь, но, возможно, вам стоит проверить, равны ли они в функции и вернуть 0 для ничьей, 1, если победит игрок1 и 2, если победит 2 игрока. Поэтому рассматривайте возвращение как победителя. – Devon

1

Как сказал Марк B в комментариях, есть лучшие способы сделать эту проблему, но для вашей ситуации, причины, почему Игрок 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

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

Попробуйте что-нибудь подобное, чтобы сделать его ДЕЙСТВИТЕЛЬНО легким.

//Here you store your player 
$player['one'] = rand(1,5); 
$player['two'] = rand(1,5); 
//Here are all of your pieces 
$pieces = array (
    1 => "Rock", 
    2 => "Paper", 
    3 => "Scissors", 
    4 => "Lizard", 
    5 => "Spock", 
); 
if ($player['one']==$player['two']) { 
    echo "<p>Draw!</p>"; 
} elseif (
    (($player['one'] == 1) && (($player['two']==4) || ($player['two']==3))) 
    || (($player['one'] == 2) && (($player['two']==5) || ($player['two']==1))) 
    || (($player['one'] == 3) && (($player['two']==2) || ($player['two']==4))) 
    || (($player['one'] == 4) && (($player['two']==5) || ($player['two']==2))) 
    || (($player['one'] == 5) && (($player['two']==3) || ($player['two']==2))) 
) { 
    echo "<p>Player 1 Wins</p>"; 
} else { 
    echo "<p>Player 2 Wins</p>"; 
} 
echo " 
    <p>Player 1:" . $pieces[$player['one']] . "&nbsp;Player2: " . $pieces[$player['two']] . "</p> 
"; 
+2

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

+0

Мне это довольно легко читать, это просто '' и '' 'и' 'if's.''. Проверьте первую часть игроков, а затем две части, которые он может победить. Кажется, каждый из них. – TheElm

+1

Не пытайтесь оскорбить вас. Трудно быть объективным с вашим собственным кодом, но приложите все усилия и посмотрите на это по сравнению с ответом Надира на исходный код. В течение одной недели легко видеть, какие ценности выигрывают и легко добавлять или изменять эти значения без изменения условий. – Devon

0

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

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

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

  • Используйте константы для значений, которые не собираются менять - то есть использовать ROCK вместо 1, бумага вместо 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)