- Въведение
- If/else
- Произволен избор и валидация
- Съкращаване на кода с хеш таблица
- Съкращаване на кода с двумерен масив
Също както променихме кода с if-клаузата да използва хеш таблица, можем и да го съкратим по друг начин. Вместо да запазим ключове и стойности, нека създадем таблица с две измерения:
- възможните ходове на потребителя
- възможните ходове на компютъра
Тя би изглеждала горе-долу по следния начин:
| R P S
--+------
R | = W L
P | L = W
S | W L =
В тази таблица нека редовете да са избора на компютъра, а колоните - избора на потребителя. При това положение, стойностите имат следното значение:
- "=" означава, че двамата са наравно
- "W" означава, че потребителя печели (win)
- "L" означава, че потребителя губи (lose)
Първо, ще дефинираме таблицата:
result_table = [
["=", "W", "L"],
["L", "=", "W"],
["W", "L", "="]
]
Базови познания: списъци Базови познания: двумерни таблици
Тази таблица е чисто и просто списък от списъци. Ако достъпим първия елемент от списъка с result_table[0]
, ще получим като резултат ["=", "W", "L"]
, което само по себе си е списък. И така, за да достъпим (примерно) втория елемент от този вложен списък, ще използваме result_table[0][1]
, което ще ни даде W
.
След това, ще вземем вход от потребителя и ще изберем ход за компютъра, използвайки метода, който ползвахме досега:
puts "Please enter one of: rock, paper, scissors"
user_choice = gets.chomp
possible_choices = ["rock", "paper", "scissors"]
if not possible_choices.include?(user_choice)
puts "Your choice, '#{user_choice}', is not one of: rock, paper, scissors. Please try again."
exit
end
computer_choice = possible_choices.sample
puts "You played: #{user_choice}"
puts "Computer played: #{computer_choice}"
Последната стъпка е да използваме таблицата, която дефинирахме, за да намерим резултата. Засега имаме ход за потребителя и такъв за компютъра. Ще разберем кой поред е този ход в списъка от ходове:
user_choice_index = possible_choices.index(user_choice)
computer_choice_index = possible_choices.index(computer_choice)
Така получаваме две числа, user_choice_index
и computer_choice_index
, които са между 0 и 2. Ще индексираме двумерната таблица с тези две числа и ще получим отговор от "L", "W", или "=".
result = result_table[computer_choice_index][user_choice_index]
if result == "W"
puts "You win!"
elsif result == "L"
puts "You lose!"
elsif result == "="
puts "It's a tie"
else
raise "Unknown result: '#{result}' for computer choice: '#{computer_choice}', user choice: '#{user_choice}'"
end
Това решение също е компактно откъм код, понеже използва специална структура (двумерната таблица), която съдържа отговора на "кой побеждава при такъв ход на играча и такъв ход на компютъра". Единственото, което трябва да направим, е да преведем хода, идващ като низ "rock", "paper", "scissors", до число, с което да достъпим правилните елементи в таблицата.
Забележете, че този път правим проверка и за трите стойности, "W", "L", "=". В случай, че не е нито една от тези стойности, има някаква грешка в програмата! На теория, кода, който сме написали, би трябвало да работи правилно и никога да не се попадне в else
клаузата. На практика обаче, ако ние, като програмисти, сме допуснали грешка в програмата, може да се получи грешен резултат и да не осъзнаем, че това е така. А дори да осъзнаем, да не намерим лесно проблема.
Кода в else
клаузата хвърля грешка с raise
. Грешката съдържа информация за това какви са били стойностите на ключовите променливи в момента. От тях можем да си направим някакви изводи за това какъв може да е проблема.
Такъв тип програмиране се нарича "defensive". Понякога е добра идея да вмъкваме подобни проверки, просто за да сме сигурни, че правим правилното нещо. В повечето случаи обаче, програмата ще ни даде грешка при грешни данни така или иначе, така че не си заслужава да правим специална проверка. Но в случай, че имате сравнително засукана логика, грешка в която не би била очевидна, може би е добра идея да проверите дали всичко е както очаквате да бъде.
Ето целия код на решението:
result_table = [
["=", "W", "L"],
["L", "=", "W"],
["W", "L", "="]
]
puts "Please enter one of: rock, paper, scissors"
user_choice = gets.chomp
possible_choices = ["rock", "paper", "scissors"]
if not possible_choices.include?(user_choice)
puts "Your choice, '#{user_choice}', is not one of: rock, paper, scissors. Please try again."
exit
end
computer_choice = possible_choices.sample
puts "You played: #{user_choice}"
puts "Computer played: #{computer_choice}"
user_choice_index = possible_choices.index(user_choice)
computer_choice_index = possible_choices.index(computer_choice)
result = result_table[computer_choice_index][user_choice_index]
if result == "W"
puts "You win!"
elsif result == "L"
puts "You lose!"
elsif result == "="
puts "It's a tie"
else
raise "Unknown result: '#{result}' for computer choice: '#{computer_choice}', user choice: '#{user_choice}'"
end