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!
https://github.com/jmooree30/Hangman/upload/master
require 'json'
load 'display.rb'
class Hangman
attr_accessor :name
@name = name
def initialize
puts "What is your name?"
@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"
game_file = File.read("saved.json")
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
-
\$\begingroup\$ Do you have a link to the assignment? Are those classes & names required? \$\endgroup\$Mark Thomas– Mark Thomas2017年08月25日 21:38:36 +00:00Commented Aug 25, 2017 at 21:38
-
\$\begingroup\$ 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. \$\endgroup\$Jacob Moore– Jacob Moore2017年08月25日 22:17:09 +00:00Commented Aug 25, 2017 at 22:17
1 Answer 1
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 yourHangman
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. ThenGamePlay
would just be user interaction, calling theHangman
game's methods as needed.
So let's think about the interface a bit: instead of
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.
-
\$\begingroup\$ 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. \$\endgroup\$Jacob Moore– Jacob Moore2017年08月27日 03:09:49 +00:00Commented Aug 27, 2017 at 3:09