# Ruby Hangman with JSON to save and load

This was an assignment from "The Odin Project". This is my first program using JSON. I've been told I need work on structuring my classes, any advice will be appreciated!

require 'json'

class Hangman
attr_accessor :name
@name = name

def initialize
@name = gets.chomp
puts "
################################################
HANGMAN
################################################
_________
|
|       |
|       O
|      /|\\
|       |
|      / \\
|
-----------------
Welcome #{@name} to Hangman. The computer will generate
a 5-12 letter random word. You will try to guess
that word one letter at a time. Try to solve the
puzzle before time runs out!
\n
"

end
end

class Gameplay
attr_accessor :array, :filestuff, :random_word, :cipher, :random_word2, :counter
def initialize
@array = []
@filestuff = File.foreach('5text.txt') do |x|
chomped = x.chomp
@array << chomped if (chomped.length >= 5 and chomped.length <= 12)
end
@random_word = @array.sample
@cipher = @random_word.gsub(/[a-z]/, '*').split(//)
@random_word2 = @random_word.split(//)
@counter = 5
puts "Would you like to load a saved game? Y/N"
saved_game = gets.chomp
if saved_game == "Y"
data = JSON.parse(game_file)
@filestuff = data["filestuff"]
@random_word = data["random_word"]
@cipher = data["cipher"]
@random_word2 = data["random_word2"]
@counter = data["counter"]
end
puts @cipher.join
puts "Enter a letter."

def to_json
JSON.generate({filestuff: @filestuff, random_word: @random_word, cipher: @cipher, random_word2: @random_word2})
end

def save_game(string)
File.open("saved.json", "w") do |game_file|
game_file.write(string)
end
end

def choice(n)
@random_word2.each_with_index do |i,index|
if i == n
@cipher[index] = i
end
end
if n == @random_word2.join.to_s
puts "You win"
puts "would you like to start another game? Y/N"
new_game = gets.chomp
if new_game == "Y"
Hangman.new
else exit
end
end
if @random_word2.include?(n) == false
@counter -= 1
display
puts "#{@counter} guesses remaining."
end
if @counter == 0
puts "would you like to start another game? Y/N"
new_game = gets.chomp
if new_game == "Y"
else exit
end
end
if n == "1"
save_game(to_json)
end
puts @cipher.join
puts "Want to save? Press 1 to save."
end

@counter = 5
while @counter > 0
choice(gets.chomp)
end

end
end
Hangman.new
Gameplay.new

• Do you have a link to the assignment? Are those classes & names required? Aug 25 '17 at 21:38
• theodinproject.com/courses/ruby-programming/lessons/… <<link to assignment. I just realized I never implemented it to be case sensitive I will fix that later. The names and classes are not required. I feel my biggest weakness right now is how I go about structuring everything. Aug 25 '17 at 22:17

One of the ways to structure your objects is to describe your problem in a sentence or two, then turn the nouns into classes, and the verb phrases into methods.

In this case, you may end up with Hangman (the game), Player, and not really much else. You can choose to put the user interaction in Hangman or you can create a separate class for it, as you did with GamePlay.

There are a couple of things to keep in mind:

• Make sure the interface makes sense. For example Hangman.new; GamePlay.new to start a game is a bit awkward. Whenever the interface is awkward it usually means there's a problem with the design. In this case, you have to manage two classes independently and you may have noticed that there's not much more you can do with your Hangman class as it is without managing it with logic external to either class.
• Apply the right behavior to the right object. Assuming Hangman represents the game, then it should do all the game stuff: new (begin), save, load, guess, show_word, etc. Then GamePlay would just be user interaction, calling the Hangman game's methods as needed.

Hangman.new
Gameplay.new


perhaps you want something more like GamePlay.begin, or if you want to specify what game it is, maybe Hangman::GamePlay.begin which means you'd put the classes in an organizing module.

This exercise structures everything around a mental model. Then it's up to you to keep the model clean. Every time you need to add functionality, ask yourself: should this go into Hangman or GamePlay? Make sure that you have the separation of concerns clear.

In your case you have user prompts in two classes which is not a clean separation of concerns and may cause problems (e.g. GamePlay doesn't know the player's name).

Hopefully this makes sense. It tackles just the organizing step, let me know if you want assistance refactoring to a different model.

• I'm currently waist deep in the next section trying to write a recursive merge sort. If I ever figure it out I'll get back to you on refactoring a new model. Aug 27 '17 at 3:09