patternrubyMinor
Codebreaker game
Viewed 0 times
gamecodebreakerstackoverflow
Problem
This is the "Codebreaker" game in Ruby. Tell me what I can make better!
#!/usr/bin/env ruby
class Sequence
attr_accessor :guess, :code
def initialize
puts "Type the difficulty level you would like: 1, 2, 3, 4, or 5"
begin
@level = gets; @level = @level.to_i
if @level > 6
raise "Error"
end
rescue
puts "Invalid Difficulty"
exit
end
end
def create_code
@code = "#{rand(@level*2)}#{rand(@level*2)}#{rand(@level*2)}#{rand(@level*2)}"
if @level == 5
@code += "#{rand(@level*2)}"
end
if @code.length > 5
puts "Invalid Difficulty!"
exit
end
puts @code
end
def prompt
@retstring = ""
@guess = ""
guesses = 0
while guesses < 4
print "Enter a guess: "
@guess = gets
x = 0
4.times do
if @code[x] == @guess[x]
@retstring += "+"
else
@retstring += "-"
end
puts @retstring
sleep(1)
x += 1
end
puts "Would you like a hint? Type 'hint' to get a hint"
hint = gets
match = hint =~ /(h|H)(i|I)(n|N)\w/
unless match == nil
j = rand(@level*2)
puts "#{j}: #{@code[j]}"
end
guesses += 1
if @retstring == "++++"
puts "Correct!"
break
end
@retstring = ""
end
end
def print_code
print @code
print " was the code\n"
end
end
j = Sequence.new
j.create_code
j.prompt
j.print_codeSolution
Interesting game :), and reasonable code. I only have a few suggestions.
for
and
Any particular reason you handled the first one using exception and the second one using an if condition?
Also consider returning an error code,
If program can be used in non-interactive way, printing any errors to stderr also helps. I would also modify it as
Should you check this here? It is more of an assert than a problem with user input, and the user input is validated elsewhere.
Avoid magic numbers, replace 4 with a constant.
Why is retstring and guess a member variable? You dont seem to be using them any where else.
Whi is this a while loop? while you used a times loop inside?
you dont need to maintain x.
Also, why do you have only 4 here? from the above, if the level is 5 you add a new cell.
and better put as ternary
Why do you use a separate match? Also name j some thing descriptive.
And why \w ? Do you want to catch spellos in hint?
Personally I prefer a case statement to check this. Also note you can get a case insensitive match.
retstring is better reset at the beginning of the loop.
Regarding the whole organization, it might be better organized as a small command interpreter with specific commands for hint, level etc
for
if @level > 6
raise "Error"
endand
if @code.length > 5
puts "Invalid Difficulty!"
exit
endAny particular reason you handled the first one using exception and the second one using an if condition?
Also consider returning an error code,
If program can be used in non-interactive way, printing any errors to stderr also helps. I would also modify it as
def sexit(code, str)
puts str
exit code
end
def initialize
puts "Type the difficulty level you would like: 1, 2, 3, 4, or 5"
@level = gets.to_i
sexit 1 "Invalid Difficulty" if @level > 6
end
def create_code
code_rows = 4
code_rows += 1 if @level > 4
@code = ''
code_rows.times do
@code += "#{rand(@level*2)}
endShould you check this here? It is more of an assert than a problem with user input, and the user input is validated elsewhere.
# sexit 2 "Invalid Difficulty" if @code.length > 5
puts @code
endAvoid magic numbers, replace 4 with a constant.
def askuser(var)
print var
return gets
endWhy is retstring and guess a member variable? You dont seem to be using them any where else.
def prompt
guess = ""Whi is this a while loop? while you used a times loop inside?
max_guess.times |guesses|
retstring = ""
guess = askuser "Enter a guess: "you dont need to maintain x.
Also, why do you have only 4 here? from the above, if the level is 5 you add a new cell.
4.times do |x|and better put as ternary
retstring += (@code[x] == guess[x] ? "+" : "-")
puts retstring
sleep(1)
end
hint = askuser "Would you like a hint? Type 'hint' to get a hint"Why do you use a separate match? Also name j some thing descriptive.
And why \w ? Do you want to catch spellos in hint?
if hint =~ /hint/i
j = rand(@level*2)
puts "#{j}: #{@code[j]}"
endPersonally I prefer a case statement to check this. Also note you can get a case insensitive match.
case askuser "Would you like a hint? Type 'hint' to get a hint"
when /hint/i
j = rand(@level*2)
puts "#{j}: #{@code[j]}"
end
if retstring == "++++"
puts "Correct!"
break
endretstring is better reset at the beginning of the loop.
end
endRegarding the whole organization, it might be better organized as a small command interpreter with specific commands for hint, level etc
Code Snippets
if @level > 6
raise "Error"
endif @code.length > 5
puts "Invalid Difficulty!"
exit
enddef sexit(code, str)
puts str
exit code
end
def initialize
puts "Type the difficulty level you would like: 1, 2, 3, 4, or 5"
@level = gets.to_i
sexit 1 "Invalid Difficulty" if @level > 6
end
def create_code
code_rows = 4
code_rows += 1 if @level > 4
@code = ''
code_rows.times do
@code += "#{rand(@level*2)}
end# sexit 2 "Invalid Difficulty" if @code.length > 5
puts @code
enddef askuser(var)
print var
return gets
endContext
StackExchange Code Review Q#11084, answer score: 5
Revisions (0)
No revisions yet.