HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Codebreaker game

Submitted by: @import:stackexchange-codereview··
0
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_code

Solution

Interesting game :), and reasonable code. I only have a few suggestions.

for

if @level > 6
        raise "Error"
      end


and

if @code.length > 5
      puts "Invalid Difficulty!"
      exit
    end


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

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)}
    end


Should 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
  end


Avoid magic numbers, replace 4 with a constant.

def askuser(var)
      print var
      return gets
  end


Why 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]}"
      end


Personally 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
      end


retstring is better reset at the beginning of the loop.

end
  end


Regarding 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"
      end
if @code.length > 5
      puts "Invalid Difficulty!"
      exit
    end
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)}
    end
# sexit 2 "Invalid Difficulty" if @code.length > 5

    puts @code
  end
def askuser(var)
      print var
      return gets
  end

Context

StackExchange Code Review Q#11084, answer score: 5

Revisions (0)

No revisions yet.