learn ruby - lesson 2 - understanding objects

Upload: jorge-matos

Post on 14-Apr-2018

228 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    1/16

    LESSON #2: UNDERSTANDING OBJECTS

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    TABLE OF CONTENTS

    1. Comparing, Conditionals and Loops ............................................................................................2

    Ruby Control Structures and Operators ............................................................................................. 2

    2. The REAL Truth About Objects .....................................................................................................3

    Classes and the Ruby Class Hierarchy ............................................................................................. 3

    Object Instances, Instance Variables and Methods ........................................................................... 6

    5. Lesson 2 Review Challenge .........................................................................................................16

    Lesson 2 Review Challenge ............................................................................................................ 16

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    2/16

    2

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    1. COMPARING, CONDITIONALS AND LOOPS

    RUBY CONTROL STRUCTURES AND OPERATORS

    Programming is an art. The subtle techniques that we use give us the feeling of satisfaction and meaning

    behind the program in which we are building, just like an artist gets satisfaction from genius art. There are no

    boundaries to the types of art that we can create, granted we understand what type of art we can make and

    the tools we can use to create the art. For instance, some artists create art through realism, making the art

    seem as visually natural as possible. Other artists create art through surrealism and abstraction hence their art

    has a degree of independence from the real world. Although loosely coined, it is the conceptually the same

    with programming. When we program, we are essentially creating abstract representations of real world

    objects. So as programmers, we must control the way he creates his programs. Welcome to the (virtual) world

    of control structures!

    Control structures (also known as control flow) refers to the systematic order of the execution of a set of

    statements. Control structures, by definition, create a lexical scope when programming and regulate how

    properties within the scope are manipulated. A lexical scope is simply another name for the immediate localenvironment in the surrounding area. Another term forproperties is called members, which is widely used

    and a conventionally valid synonym. We often use control structures to compare expressions against one

    another. To do this we must understand some important operators in Ruby.

    The = sign

    A single = sign is used to assign the value on the rightto the object on the left. This is called the assignment

    operator.

    The == sign

    A double == sign is used to compare the value on the rightto the object on the left. This is called comparison

    operator, which is used in control structures.

    The === sign

    A triple === sign is used to check for equalitythat the value on the rightis the exactsame object as the one on

    the left. This is called equality operator, which is also used in control structures.

    a = 10

    test = This is a test

    iftest == This is a test

    print Success

    end

    iftrue === true

    print Both are true

    end

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    3/16

    3

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    It is important to know that the proper control structure to use ultimately depends on the type of objects

    being evaluated and the programmers desired results. Control structures begin with the name of the

    structure and end with the end keyword. There are, however, more advanced control structures that are

    implemented which well discuss later. The syntax for creating basic control structures (conditional branches

    and loops) are shown below:

    Conditional Branches Expressions or conditions that are evaluated.

    if / if-else Checks ifone or more conditions are met. else is an optional branch.

    unlessThe exact opposite of if. The code-block will only be executed if the expression is false. There is no

    elsif or elsunless.

    if-elsif-else A three branch conditional block that can evaluate multiple conditions.

    ternary operator The ternary operator is simply a short version of evaluating an expression and executing a

    code (think of it as a shorter version of the if/else statement). The syntax is:

    result = (condition) ? (expression-if-true) : (expression-if-false)

    a = 10

    ifa == 10

    print A is 10

    else

    print No answer

    a = 10

    unless a == 5

    print A is 10 # This will print A is 10 because the expression a== 5 is false

    a = 10

    ifa == 4

    print A is 4

    elsifa == 7

    print A is 7

    else

    print A is 10

    end

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    4/16

    4

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    Read it like this. The expression on the left of the : will be ran if the result equals the condition otherwise the

    condition on the right of the : will be ran.

    Use this with caution as it can get hard to read if you have large code. Also ? has another use so ambiguity

    can be a problem in some cases. It is wise to use parenthesis for executing your code.

    case The case conditional is another way to write an if-elsif-else statement (with more than one elsif). An

    object is given a case and when a condition is met then something happens.

    Loops Loops are blocks of code that are consecutively executed until a condition is met.

    while The code block will be executed over and over again so long as the expression evaluates true.

    untilThe code block will be executed over and over again so long as the expression evaluates false. When

    the expression is evaluated to true the loop ends. It is the opposite of while.

    Often times we will want to return something from a control structure or method and store that value in some

    variable. We use the return keyword to return the values from control structures.

    Note: To check more than one expression at a time in a control structure use the and (&&) and or (||)

    operators between expressions.

    true = true ? (puts 'a'): (puts 'b') #=> prints "a"

    case a

    when 0..4 then puts "#{a} is less than 5"when 5 then puts "#{a} equals 5"when 5..10 then puts "#{a} is greater than 5"else puts "unexpected value #{a}" # If a is bigger than 10 or negative.

    end

    while # if this is true# # do code

    end

    until # if this is false# # do code

    end

    if a = 5return true

    end

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    5/16

    5

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    Lets do an exercise on control structures and comparison.

    1. Open your OS command line prompt.

    2. Navigate to the folder where you downloaded all the files folder that came with this lesson.

    3. In the command prompt type: ruby files/control_structures.rb it will print the word No

    4. Open control_structures.rb in your text editor and fix the code. Your job in this exercise is to make the

    program print the word Thanks by fixing the 6 problems.5. After you have completed the exercise open files/answers/control_structures.rb for answers and

    explanations.

    control_structures.rb teaches you:

    Conditional branches and nested conditional statements

    Critical thinking and error checking

    break keyword

    Conditional branches and nested conditional statements Programming involves loops and conditions. There

    is just no way around this truth. If you already come from a programming background then you understand

    how crucial it is to understand control structures, which is why I taught them in this lesson, even if you may

    have already known this. Control structures can be nested inside of each other, which is the basis of how

    routing in a program is handled. You must understand conditional statements and when to use the

    appropriate ones to have a bug free program.

    Critical thinking and error checking The comments provided in the files are meant to be read for clarification.

    Although slightly verbose, it is clear explanation of what is happening between the problems. This exercise is

    intended to get you to think about how youre coding (and not necessarily why youre coding.).

    2. THE REAL TRUTH ABOUT OBJECTS

    CLASSES AND THE RUBY CLASS HIERARCHY

    A very nice diagram of the current Ruby class hierarchy can be found here:

    http://objectgraph.rubyforge.org/neatoOG.html

    It is not necessary to know this diagram for now, but it explains one good concept Ive been waiting to solidify

    in your brain. In its strictest sense, nearly everything in Ruby is an object (and treated as such). But what is an

    object really? What is this abstract idea I keep mentioning? Lets look at how to make an object and why its soimportant in Ruby.

    In order to make an object we must make a class of that object. A class is set of coding instructions that

    defines an object andhow it should be presented in your ruby program. That class definition of an objectcan

    then be instantiated(created) throughout our program and manipulated and interact with other objects

    within our program. Every custom built class is an instance of the Class class in the Ruby class hierarchy.

    Now armed with this knowledge, lets define a class and instantiate an object of that class.

    http://objectgraph.rubyforge.org/neatoOG.htmlhttp://objectgraph.rubyforge.org/neatoOG.html
  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    6/16

    6

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    OBJECT INSTANCES, VARIABLES, AND METHODS

    To create a new class we use the class keyword followed by a whitespace the name of the class. The first

    letter of the class name must be capitalized. We then use the end keyword to explicitly close our class. We

    can then assign a variable to the class by calling that classs new method (which instantiates the initial state

    of an instance of that object). In our example above myVariable is an instance ofMyNewClass (i.e. an object).

    All of the things that this class will do goes between class and endkeywords. Lets look at what those things

    can be:

    Variables Local variables, instance variables, class variables, global variables

    Methods class methods, instance methods, inherited methods

    The concept of sending/receiving messages

    Constants

    Some other things we will wait on explaining

    VariablesWeve already defined what local variables are inLesson 1and we understand them pretty clearly

    now. A refresher is that local variables are basic containers that can be used to store a value and can only be

    manipulated within the scope in which it was declared inside of. A class variable can be used by a child of the

    its parent class (more on this much later). A global variable can be used throughout the entire program (it is

    not limited by scope at all. A global variable can be accessed anywhere and is seldom used). But what is an

    instance variable? An instance variable is a variable defined in a class that stores a value and is associated

    onlyto the current instance of the class (the variable that was assigned the new class again that particular

    object). Below is an example using local and instance variables and two instances of a custom Person class.

    classMyNewClass

    #Coding instructions

    end

    myVariable = MyNewClass.new # an object instance of MyNewClass

    classPerson

    attr_accessor :name # allows @name to be read and written

    def initialize(param) # Consider this the .new method w/ 1 parameter@name = param # instance variable is now equal to local variable

    end

    end

    me = Person.new(Kadeem) # one instance object .new calls initialize method w/ 1 argument

    you = Person.new(Your Name) # another instance w/ 1 argument

    puts me.name # calls this instances name => prints Kadeemputs you.name # calls this instances name => prints Your Name

    http://bit.ly/13NCsQrhttp://bit.ly/13NCsQrhttp://bit.ly/13NCsQrhttp://bit.ly/13NCsQr
  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    7/16

    7

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    To define an instance variable we declare a name preceded by an @ symbol. You use the same naming

    conventions as a local variable. In the above example @name is an instance variable. This means that every

    instance of a Person object that we create will have @name attribute that we can access.

    attr_accessor will be fairly new to you but it is extremely easy to understand. attr_accessor is a type of Ruby

    syntactical sugar (which is just a fancy name for a way of Ruby understanding what youre really implying).

    What attr_accessor means is that we want our class (Person) to have the ability to read and write to aninstance variable (@name). Now we have the ability to not only access a Persons @name but we also have

    the ability to overwrite a Persons @name. If we only wanted to accessan instance variables value (i.e. allow

    access to it from the outside world external access only) we declare attr_reader and if we only wanted to

    write to an instance variable (i.e. deny all access to it from the outside world - internal access to the class only)

    we declare attr_writer.In our example we want to read and write so we chose to use attr_accessor so at

    any time later in our program we can overwrite @name for that particular instance of that Person object.

    Things like variables are the called attributes of a class. They can also be used for other things which we will

    learn later. We will skip constants, class variables and global variables for now and save them for another day.

    Methods A method is a simply set of instructions inside of a class that you as a programmer define. That

    method can then be invoked and called upon in your program. For the sake of comprehension, a methodis

    the same thing as afunction in other languages. Most programmers argue that a methodis a function defined

    inside of a class whereas afunctionis not defined in any class (perhaps floating in a main namespace).

    Methods are the actions and behaviors that your class will perform. Methods can be custom built and also

    overwritten (Yes you can manipulate the behavior of a default Ruby classs methods!). To create a method we

    use the def keyword followed by the name of the method (lowercase convention) and an end keyword to

    close it. When we create an instance (object) of our Person class we set the variable equal to Person.new.

    .new is a method of Rubys Class class (see Ruby hierarchy ) that calls that classs initialize method.

    Every class in Ruby has an initialize method. Even if we dontexplicitly define the initialize method, Ruby will

    create one for us automatically (it will be empty of course). The purpose of the initialize method is to create

    the initial state of the object instance. Once the initial state of the object has been completed we have an

    instance of our object that is referenced by our variable (in our example me and you are the variables

    where we are referencing two separate instances of the Person class).

    Some methods are public to the entire program, but some can be private and protected (we will discuss scope

    and types of methods in another lesson). By default all custom methods are made public and can be accessed

    anywhere in the program.

    Methods can also have parameters associated with them. Aparameteris aplaceholderthat is associated with

    an argument when the method is invoked. It is used to setup variables in a method, but has no explicit value.

    In our example param is a methodparameterand Kadeem and Your Name are method call arguments.

    Parameters become local variables once an argument has been given when we call the method. Thus, our

    method initialize now contains a local variable called param that it can use inside of itself.

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    8/16

    8

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    Lets do two exercises on classes, objects, variables, and methods.

    1. Navigate to the folder where you downloaded all the files folder that came with this lesson.

    2. In your command prompt open: ruby files/game.rb

    3. You are going to play a fighting game with an AI computer opponent for the chance to win $1,000,000.

    4. After you have completed the game open were going to go step-by-step below to build this game.

    The code behind game.rb teaches you:

    Creating a standalone ruby program

    Classes, object instances and initialization

    Instances variables and methods

    How classes can interact with each other

    Accessibility and scope

    Loops and conditional statements

    Interpolation

    A brief introduction to Array objects

    sample method

    A verybrief introduction to regular expressions

    Creating random numbers

    Creating a nave system of artificial intelligence

    Exiting a program

    Well go step by step in how to build this program.

    Part 1: The concepts in our game

    The first part is just to understand what will be in our program. We want to create a game and somefighters

    in the game. Armed with this knowledge we know we are going to build two separate classes. The concept of

    what afighterwill be goes in a Fighter class and the concept of the game itself will go in a Game class.

    Part 2: Control and characteristics of each class

    Now that we know the objects that our game lets identify control and some of the characteristics of classes.

    classFighter

    # Defines a Fighter object

    end

    classGame

    # Defines a Game object

    end

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    9/16

    9

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    We want to have our Game class to be the center of control in our game. That means that our Game class will

    need two instances (objects) of our Fighter class and will control how those two instances interact with each

    other. This means that our Game class must havepublic access to the behaviors and attributes (sometimes

    called members) of the Fighter class. Thispublic access is considered a type of class scope. Scope deals with

    access to the members of a class. We want our Game class to have access to everything about a Fighter class.

    When we start our game and create two Fighters we want to set the initialstate of those Fighters. So what are

    some of those initial characteristics of a Fighter? Lets give our Fighter class some attributes for our game.

    So when we create a new Fighter we initialize aname, weapon, health and statuses. To the outside world the

    name and weapon can onlybe read (and cannot be overwritten), while the health and statuses can be read

    and overwritten because of the scope restrictions.

    Next lets define some of custom behaviors of a Fighter class. These will be our Fighterpublic methods.

    Our Fighter can attack. The damage ensued is determined by the Fighters @weapon, therefore were going to

    give @weapon a case statement and generate the damage by a Random number between a range of numbers

    multiplied by a damage_factor that is controlled by Game (and finally explicitly convert that number to an

    integer using .to_i). Because the randomly generated number is the last expression evaluated in the attack

    method, that number gets returned to the receiver of the attack method (of course this will be handled by

    our Game).

    classFighter

    attr_reader :nameattr_reader :weaponattr_accessor :healthattr_accessor :defenselessattr_accessor :dead

    def initialize(name, weapon)@name = name # Sets Fighter name@weapon = weapon # Sets Fighter weapon@health =50 # Sets Fighter health@defenseless =true # By default he is not defending@dead =false # By default he is not dead

    end

    #...def attack(damage_factor)

    case @weaponwhen "Longsword" then (Random.rand(7...29) * damage_factor).to_iwhen "Crossbow" then (Random.rand(9...22) * damage_factor).to_iwhen "Hammer" then (Random.rand(1...39) * damage_factor).to_iwhen "Shotgun" then (Random.rand(4...22) * damage_factor).to_i

    endend

    #...

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    10/16

    10

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    Our Fighter can take damage from an attack. In our Game class, the receiver from the attack method (the

    number returned from the attack method) becomes the amount argument when the took_damage method is

    called. When a Fighter takes damage we want to subtract the amount from the fighters @health. We would

    not be able to do this if we didnt have the overwriting capabilities we specified earlier. We also want to check

    if that Fighters @health is now 0 or less than 0. If it is, then we set @health to 0 and change the state of the

    Fighter object to @dead. Our Game class will check whether a Fighter is dead at the beginning of the next turn

    and route the state of the game appropriately.

    Our Fighter can defend against an attack. This small method simply changes the status of our Fighter object.

    When our opponent Fighter attacks us while @defenseless is truewewill take maximum damage, but when

    our opponent attacks us while @defenseless is falsewe will only take 1/3 damage. This is the damage_factor

    we defined earlier. Of course, a Fighter cannot defend forever so at the beginning of the Fighters turn, we

    will have our Game class set @defenseless back to trueevery time. This decision making will controlled, of

    course, by the Game class.

    Finally, our Fighter can heal himself. Because our Game class can access a Fighters @health we can explicitly

    increase @health by a random amount. We also set the Fighters @health to 100 if it ever goes over 100

    (otherwise we could heal forever!). We then end our Fighter class.

    Thats it! Thats all we need to define our Fighter class. You just learned some important concepts about

    instance variables (@), scope (public and private), and some other neat things (randomly generated numbers

    and also Range objects). Next lets define our Game class.

    #...def took_damage(amount)

    @health -=amountif @health = 100

    @health = 100end

    end

    end #END of Fighter class

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    11/16

    11

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    We said earlier that our Game class will control (i.e. have access to) the Fighter class. This means that our

    Game class will have to create two instance objects of the Fighter class (one will be us, the other will be a

    computer opponent).

    We dont want anyone to access the behaviors of our Game class, so all of the methods inside of our Game

    class will be private and inaccessible anywhere in our program (aside from initialize which is always public).

    This is an important concept because we wouldnt want to directly alter the state ofthe Game by calling someof its methods, we want the Game to control itself (a concept I like to call self-containment).

    One more thing about our Game class. For the sake of comprehension we will avoid handling Exceptions

    (errors) in our program for now. We will spend an entire lesson on this later. Our program wont have any

    bugs, but as a rule of thumb, once we cover exceptions and error handling you should implement them.

    Lets build our Game class. We need to be able to create andmanipulate two Fighter object instances. We also

    need a way to store which Fighter object has the current turn. Additionally, although not required, we should

    specify the actions a Fighter can invoke in our Game and be able to read them (not overwrite them).

    We now have the initial state of our Game. When Game.newis called, we need the name and weapon that

    player 1 has entered. We want our Game to be able to read @actions that a Fighter can take. We also want to

    store the weapons that a Fighter can choose (used for player 2 computer only). Both collections are stored in

    Array objects ( using [ ] braces ) respectively. We then create a new Fighter called @player1 with the player 1s

    name and weapon and also a @player2 object with a name ofBob the Grandmaster and a random weapon

    from the weapons Array collection (weapons.sample does this for us). Remember that @player1 and

    @player2 are now newly created object instances of our Fighter class that can be used inside our Game class.Finally after we have created our objects we call our (private) opening_sequence method of our Game.

    The methods below this private declaration are now internally accessible to the Game class, but inaccessible

    to the outside world (i.e. Fighter class cannot access these methods.). Lets start with opening_sequence.

    classGame

    attr_accessor :player1attr_accessor :player2attr_accessor :current_turnattr_reader :actions

    def initialize(player1_name, player1_weapon)@current_turn = nil@actions = ["Attack", "Defend", "Heal", "Nothing"]weapons =["Longsword", "Crossbow", "Hammer", "Shotgun"]@player1 =Fighter.new(player1_name, player1_weapon)@player2 =Fighter.new("Bob the Grandmaster", weapons.sample)opening_sequence

    end

    #..private

    #..

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    12/16

    12

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    Here we have defined our games opening sequence. At this point when this method is called we have fully

    created our two Fighters as @player1 and @player2 objects. We print an introduction that the player will see

    and supply gets in intermediate lines so that the player can read the lines. We also want to space out our

    lines a little for readability so we need to put carriage returns. \n means newline in a string. We also use

    interpolation inside of our strings to access members of our object (in this case we want to access @player1s

    name attribute and will be printed thanks to puts). We do interpolation in a string by using a unique syntaxlike so: #{ stuff_goes_here }. We can put expressions, method calls, variables, classes, roughly anything

    inside of interpolated expressions. Next lets have our player flip a coin heads or tails to see who goes first in

    our game. The user input is stored in the choice local variable all lowercase. That value is then passed as an

    argument to the coin_toss method in our Game class which well define later. coin_toss will store the new

    value of our Games attribute @current_turn. Because we have set the Games @current_turn (remember we

    can access @current_turn anywhere in our Game class) we will then call our main Games loop update

    method and start our game! So lets first define coin_toss and then our update method.

    Here we define our coin_toss that method that has one parameter. It checks if the choice selected is heads

    and sets @current_turn equal to @player1 object, otherwise sets @current_turn equal to @player2 object.We didnt have to explicitly set @current_turn here; Ruby always returns the last expression evaluated in the

    method. We could have written the last line as @player1 or @player2 and set a @current_turn equal to the

    coin_toss method call in our opening_sequence. I did it like this because I like to explicitly know what my

    methods are really doing and their purpose which means that my coin_toss method returns nil. Either way is

    fine, and it is simply a matter of taste. When you begin to write your own programs you will find the best

    procedures for yourself. Great now we know who goes first in our game. Lets create our games main loop.

    #...def opening_sequence

    puts "\nWelcome to Fight Club, #{@player1.name}!"; gets;puts "\nFight your opponent for the chance to win $1,000,000!"; gets;puts "\nPress Ctrl + C at anytime to exit the fight."; gets;puts "\nLet's flip a coin to see who goes first!"; gets;puts "\nChoose heads or tails!"choice = gets.chomp.downcase

    coin_toss(choice)gets; puts "\nLet's fight!"; gets;update

    end#...

    #...def coin_toss(choice)

    if choice == "heads"puts "\nGot it! #{@player1.name}, you go first!"@current_turn = @player1

    elseputs "\n#{@player2.name} goes first!"@current_turn = @player2

    endend

    #...

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    13/16

    13

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    This is the main loop of our program. It is a custom method called update. This loop first checks if the@current_turn (@player1 or @player2) object has a @dead attribute that is true. If it is truewe call the

    Gamesgameover method with two parameters (the (losing) Fighter object, and a method call to switch_turn

    which returns the (winning) Fighter object). We have not defined the switch_turn method yet, but its purpose

    is to simply return the opposite Fighter object. So gameover will have two arguments and we will define that

    method a little later as well. If that @current_turns @dead attribute is set to falsewe reset the

    @current_turns @defenseless attribute back to true(since it is currently that Fighters turn and hes still

    alive). Then we have another condition (we call this nested conditional statements).

    If the @current_turn object the same as (note the === sign)@player1 we print their name and the actions in

    which they can perform and wait for user input and do that action by calling do_action, passing it the action

    choice. If the turn object is the same as @player2 we print its @name (i.e. Bob the Grandmaster). We then

    call do_action passing it a random action from the Games @actions. Because @player1 or @player2 has

    called do_action we will want our do_action method to recall update after it is done. So lets define our

    switch_turn method first and then our do_action afterwards.

    Here is Games switch_turn method that simply (explicitly) assigns the new @current_turn object. We have to

    be careful with it because we dont want to ruin the update method and state of the game. We will call the

    switch_turn method when necessary (before the calls to the update method throughout our program).

    #...def update

    if @current_turn.dead == truegameover(@current_turn, switch_turn)

    else@current_turn.defenseless = trueif @current_turn === @player1

    puts "\n\n\n\n#{@current_turn.name}, it's your turn."

    puts "\nWhat do you want to do? 1: #{@actions[0]} 2:#{@actions[1]} 3: #{@actions[2]} 4: #{@actions[3]}"choice = gets.chomp.capitalizedo_action(choice)

    else @current_turn === @player2puts "\n\n\n\nIt's now #{@current_turn.name}'s turn";gets;puts do_action(@actions.sample); gets;

    endend

    end#...

    #...def switch_turn

    if @current_turn === @player1

    @current_turn = @player2

    else@current_turn = @player1

    endend

    #...

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    14/16

    14

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    Here is our do_action method with one parameter. It maps the either @player1s user input choice to an

    action or @player2s randomly selected choice from the update method. We give the choice a case and a

    corresponding call to the Fighter objects helper classes. If we are attacking, we grab a temporary instance of

    the opposite opponent and call the opposite opponents took_damage method and supply a damage_factor

    argument. Once the action method has been executed we call switch_turn again and recall update. As you can

    see, control is passed back and forth between do_action, update, and Fighters helper methods. Finally we

    need to define our gameover method when a Fighter is dead.

    #...def do_action(choice)

    if @current_turn ===@player1opponent =@player2

    elseopponent =@player1

    end

    case choicewhen "Attack" then

    puts "\n#{@current_turn.name} is attacking#{opponent.name} with a #{@current_turn.weapon}!"

    if opponent.defenseless == truedamage = @current_turn.attack(1.0)

    elsedamage = @current_turn.attack(0.3)

    endgets; puts "#{opponent.name} took #{damage} damage!"opponent.took_damage(damage)puts "#{opponent.name}'s health has dropped to:

    #{opponent.health}"; gets;

    when "Defend" then puts "\n#{@current_turn.name} is nowdefending against #{opponent.name}'s next attack."

    @current_turn.defend; gets;when "Heal" then puts "\n#{@current_turn.name} is now healing.";

    @current_turn.healputs "#{@current_turn.name}'s health is now:

    #{@current_turn.health}"; gets;else

    puts "\n#{@current_turn.name} has dropped his guard andis defenseless this turn!"; gets;

    end

    switch_turn

    update

    end#...

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    15/16

  • 7/29/2019 Learn Ruby - Lesson 2 - Understanding Objects

    16/16

    16

    Learn Ruby: Lesson 2 Understanding Objects

    www.soultheory.ne

    3. LESSON 2 REVIEW CHALLENGE

    LESSON 2 REVIEW CHALLENGE

    Your challenge is to build a banking system. You can begin by defining an Account class (checking and savings)

    and a Bank class. Maybe the bank can lend @loans to its members? You can use your imagination with it.

    There is a couple of catches. One is that no Burglar should be able to access a Bank class or an Account class.

    The Burglar could try to rob the bank during a random time of the day and if successful (at random) he steals

    money from an Account! Perhaps the Bank can call the Police in the attempt of a burglary? The possibilities

    here are endless but bring real world situations and program them from abstract concepts with the

    information learned from this lesson.

    Whats to come in the next lesson:

    Rubys Secret Weapon: Blocks

    A Closer Look At Arithmetic

    The Beauty Of Arrays and Hashes

    Inheritance, Modules, and Mixins

    Instance Methods Vs. Class Methods

    Useful Methods Cheat Sheet

    Thanks for downloading. Contact me: [email protected]

    Downloaded from:www.soultheory.net

    Resources:

    www.ruby-lang.org

    http://www.ruby-doc.org/docs/ProgrammingRuby

    http://apidock.com

    http://www.skorks.com/

    http://explainruby.net/ - An online Ruby code interpreter!

    http://rubylearning.com/

    http://www.soultheory.net/http://www.soultheory.net/http://www.soultheory.net/http://www.ruby-lang.org/http://www.ruby-lang.org/http://www.ruby-doc.org/docs/ProgrammingRubyhttp://www.ruby-doc.org/docs/ProgrammingRubyhttp://apidock.com/http://apidock.com/http://www.skorks.com/http://www.skorks.com/http://explainruby.net/http://explainruby.net/http://rubylearning.com/http://rubylearning.com/http://rubylearning.com/http://explainruby.net/http://www.skorks.com/http://apidock.com/http://www.ruby-doc.org/docs/ProgrammingRubyhttp://www.ruby-lang.org/http://www.soultheory.net/