Need help with shortening my code

Hello, i was wondering if anyone was willing to help me get started with shortening my code? I got the hang of just coding without classes or objects and just used a bunch of code and a lot of it is similar, but didn’t know how to put them into classes. I currently have over 40k lines because of a lot of just copy and past and changed a word or two here and their.

That’s a broad question! And I’m amazed you got to 40k lines …

The key to shortening is the same in all cases: what parts of the code are changing, and what are staying the same?

We have loops, methods (also called functions) and classes to prevent copy-pasting.

If you have a loop, the body of the loop is the thing ‘staying the same’ with the loop variable ‘the part that changes’.

When you have a method, you pass it values for the ‘parts that change’ - its parameters - and its body, again, is what has stayed the same.

Classes represent related variables and methods. You create a class with some values for its own variables - the parts that change - and the methods work on those values - the methods here are staying the same.

If you want to simplify your code, look for the pieces that you copy-pasted - those words you changed, could you make them variables and the piece you copy-pasted a method?

Do you have lots of related variables, and slightly different methods working on those variables in the same way? Then that’s where you could use a class.

Take it in pieces. If you have some smallish bit of code you’re not sure about, post it here with what you are trying to simplify.

require_relative “Player_Object”
require_relative "Current_Stats_Object
class Game
def initialize
player = Player.new()
puts player
class_choice = gets.chomp()
stats = Stats.new()
puts stats

end

end

class Player
attr_accessor :weapon, :hp, :max_hp, :damage, :defense, :luck
def initialize(weapon, hp, max_hp, damage, defense, luck)
weapon = weapon
hp = hp
max_hp = max_hp
damage = damage
defense = defense
luck = luck
end

end
player1 = Player.new(“wand”, 13, 13, 3, 3, 10)

	player2 = Player.new("dagger", 11, 11, 4, 2, 30)

	player3 = Player.new("sword", 17, 17, 3, 4, 15)

	player4 = Player.new("bow", 15, 14, 2, 3, 25)

	puts "Please choose a starting class. mage/rogue/warrior/archer"
	puts "Class   : Mage     Rogue     Warrior     Archer"
	puts "Weapon  : " + player1.weapon + "    " + player2.weapon + "      " + player3.weapon + "       " + player4.weapon
	puts "HP      : " + player1.hp.to_s + "        " + player2.hp.to_s + "          " + player3.hp.to_s + "        " + player4.hp.to_s
	puts "Damage  : " + player1.damage.to_s + "         " + player2.damage.to_s + "           " + player3.damage.to_s + "         " + player4.damage.to_s 
	puts "Defense : " + player1.defense.to_s + "         " + player2.defense.to_s + "           " + player3.defense.to_s + "         " + player4.defense.to_s
	puts "Luck    : " + player1.luck.to_s + "        " + player2.luck.to_s + "          " + player3.luck.to_s + "        " + player4.luck.to_s

class Stats
if
class_choice == “mage”
puts "Your current stats are " + player1.hp.to_s + " " + player1.damage.to_s + " " + player1.defense.to_s + " " + player1.luck.to_s
elsif
class_choice == “rogue”
puts "Your current stats are " + player2.hp.to_s + " " + player2.damage.to_s + " " + player2.defense.to_s + " " + player2.luck.to_s
elsif
class_choice == “warrior”
puts "Your current stats are " + player3.hp.to_s + " " + player3.damage.to_s + " " + player3.defense.to_s + " " + player3.luck.to_s
elsif
class_choice == “archer”
puts "Your current stats are " + player4.hp.to_s + " " + player4.damage.to_s + " " + player4.defense.to_s + " " + player4.luck.to_s
end
end

Also, i couldnt put the @ in the position because im a new user and deleted them

You’ve got a Player class, which holds information on each player.
Then you create instances of Player: player1, player2, etc.

For a start, look at your if-statement in Stats: see that all the print statements are the same?

In the Player Class, put this duplicate code in a method:

class Player
  # the code you already have

  def get_stats()
"Your current stats are " + @hp.to_s + " " + @damage.to_s + " " + @defense.to_s + " " + @luck.to_s
  end
end

Then, to print the players’ stats you can call:

puts player1.get_stats()
puts player2.get_stats()
puts player3.get_stats()
puts player4.get_stats()

You should also think of a collection to store your players in. A ‘map’ makes sense, as you have those ‘class_choice’ names:

AllPlayers = {"mage" => player1, "rogue" => player2, "warrior" => player3, "archer" => player4}

You can then show the stats for the named player by looking them up:

class_choice = gets.chomp()
puts AllPlayers[class_choice].get_stats()

So, I have complied the code but am getting an error on the undefined allplayers variable. This is what I have so far.

require_relative “Player_Object”

class Game
def initialize
puts Player.new()

end
class_choice = gets.chomp()
puts allplayers[class_choice].get_stats()

end

class Player
attr_accessor :weapon, :hp, :max_hp, :damage, :defense, :luck
def initialize(weapon, hp, max_hp, damage, defense, luck)
weapon = weapon
hp = hp
max_hp = max_hp
damage = damage
defense = defense
luck = luck #(These have the @ sign, but new user problem of referencing >2 users, so I took them out.)
end

	player1 = Player.new("wand", 13, 13, 3, 3, 10)
	
	player2 = Player.new("dagger", 11, 11, 4, 2, 30)

	player3 = Player.new("sword", 17, 17, 3, 4, 15)

	player4 = Player.new("bow", 15, 14, 2, 3, 25)

	puts "Please choose a starting class. mage/rogue/warrior/archer"
	puts "Class   : Mage     Rogue     Warrior     Archer"
	puts "Weapon  : " + player1.weapon + "    " + player2.weapon + "      " + player3.weapon + "       " + player4.weapon
	puts "HP      : " + player1.hp.to_s + "        " + player2.hp.to_s + "          " + player3.hp.to_s + "        " + player4.hp.to_s
	puts "Damage  : " + player1.damage.to_s + "         " + player2.damage.to_s + "           " + player3.damage.to_s + "         " + player4.damage.to_s 
	puts "Defense : " + player1.defense.to_s + "         " + player2.defense.to_s + "           " + player3.defense.to_s + "         " + player4.defense.to_s
	puts "Luck    : " + player1.luck.to_s + "        " + player2.luck.to_s + "          " + player3.luck.to_s + "        " + player4.luck.to_s

	allplayers = {"mage" => player1, "rogue" => player2, "warrior" => player3, "archer" => player4}

	def get_stats()
		puts "Your current stats are " + hp.to_s + " " + damage.to_s + " " + defense.to_s + " " + luck.to_s #(These have the @ sign, but new user problem of referencing >2 users, so I took them out.)
	end

end

(If you put three back-ticks either side of your code, it will ‘pretty-print’.)

You need to think about visibility of your variables. In this case, all_players seems to be a characteristic of Game, so make it an instance variable.

Try this:

class Player
  attr_accessor :weapon, :hp, :max_hp, :damage, :defense, :luck
  
  def initialize(weapon, hp, max_hp, damage, defense, luck)
    @weapon = weapon
    @hp = hp
    @max_hp = max_hp
    @damage = damage
    @defense = defense
    @luck = luck
  end

  def get_stats()
    "Your current stats are " + @hp.to_s + " " + @damage.to_s + " " + @defense.to_s + " " + @luck.to_s
  end
end

class Game
  # set up your four players, and store them in an instance variable
  def initialize

    player1 = Player.new("wand", 13, 13, 3, 3, 10)
    player2 = Player.new("dagger", 11, 11, 4, 2, 30)
    player3 = Player.new("sword", 17, 17, 3, 4, 15)
    player4 = Player.new("bow", 15, 14, 2, 3, 25)

    @all_players = {"mage" => player1, "rogue" => player2, "warrior" => player3, "archer" => player4}
  end

  def show_menu
    puts "Class   : Mage     Rogue     Warrior     Archer"
    puts "Weapon  : " + @all_players["mage"].weapon + "    " + @all_players["rogue"].weapon + "      " + @all_players["warrior"].weapon + "       " + @all_players["archer"].weapon
    puts "HP      : " + @all_players["mage"].hp.to_s + "        " + @all_players["rogue"].hp.to_s + "          " + @all_players["warrior"].hp.to_s + "        " + @all_players["archer"].hp.to_s
    puts "Damage  : " + @all_players["mage"].damage.to_s + "         " + @all_players["rogue"].damage.to_s + "           " + @all_players["warrior"].damage.to_s + "         " + @all_players["archer"].damage.to_s 
    puts "Defense : " + @all_players["mage"].defense.to_s + "         " + @all_players["rogue"].defense.to_s + "           " + @all_players["warrior"].defense.to_s + "         " + @all_players["archer"].defense.to_s
    puts "Luck    : " + @all_players["mage"].luck.to_s + "        " + @all_players["rogue"].luck.to_s + "          " + @all_players["warrior"].luck.to_s + "        " + @all_players["archer"].luck.to_s
  end

  # This method handles your game play
  def play_game
    show_menu
    puts "Please choose a starting class. mage/rogue/warrior/archer"
    puts "Choice? "
    class_choice = gets.chomp()
    puts @all_players[class_choice].get_stats()
  end
end

# Make a game instance and play the game
game = Game.new
game.play_game

So how will I be able to add stats and make it permanent for a given item to a given player? Been trying to test out different ideas, but none seems to work.

Can you post one of your ideas and what the problem is?