Learning ruby by make a simple game

Hello,
    I'm trying to learn ruby so I am making a tic tac toe game. It is
based
on the example the pugs example directory. I'm looking for advice on how
to
make the script more ruby like.

Thanks,
Robert

tic-tac-toe.rb (1.39 KB)

Hello,
    I'm trying to learn ruby so I am making a tic tac toe game. It is
based
on the example the pugs example directory. I'm looking for advice on how
to
make the script more ruby like.

Well, let's have a peek:

#!/usr/bin/ruby

# Add the ability to more than one object
# out of a collection
class Array
  def pick(num)
     (0...self.length).step(num) do
       >i> yield self[i...i+num]
     end
  end
end

Clever, I like that.

# Print Tic Tac Toe board
def print_board(b)
  puts "+---+---+---+"
  b.pick(3) do |x,y,z|
    puts "| #{x} | #{y} | #{z} |"
    puts "+---+---+---+"
  end
end

Looks good here.

# Test if there is a winner on the board
def winner?(game_board)
  winning_set = [[ 0, 1, 2 ],[ 3, 4, 5 ],[ 6, 7, 8 ],[ 0, 3, 6 ],
                 [ 1, 4, 7 ],[ 2, 5, 8 ],[ 0, 4, 8 ],[ 2, 4, 6 ]]
  winning_set.each do |x|
    test_set = game_board.values_at(x[0],x[1],x[2])
    raise "has won!" if (test_set == %w{X X X} || test_set == %w{O O O})
  end
end

WINS = [[ 0, 1, 2 ],[ 3, 4, 5 ],[ 6, 7, 8 ],[ 0, 3, 6 ],
         [ 1, 4, 7 ],[ 2, 5, 8 ],[ 0, 4, 8 ],[ 2, 4, 6 ]]

def winner?( game_board )
   WINS.any? do |win|
     game_board.values_at(*win).join =~ /^([XO])\1\1$/ ? $1 : nil
   end
end

# Build game board and fill it with .
board =
9.times do |x|
  board << '.'
end

board = Array.new(0) { "." }

player = 'X'
choice = ''
used =

print_board board

puts "Pick a number 1-9."
while board.any? {|square| square == '.' }
  print "#{player}'s turn> "
  choice = gets.chomp

  exit if choice =~ /[Qq](?:uit)?/

choice = choice.to_i # might as well just convert it once

  if used.any? {|number| number == choice.to_i}

if used.include? choice

    puts "Number #{choice} has been used!"
    next
  elsif not (1..9).include?(choice.to_i)
    puts "Out of range."
    next
  end

  used << choice.to_i

  board[choice.to_i-1] = player
  print_board board

  begin
    winner?(board)
  rescue => e
    puts "#{player} #{e}"
    exit
  end

if winner = winner?
   puts "#{winner} has won!"
end

  player = (player == 'X') ? 'O': 'X'
end

puts "Cat won the game."

Well, those are my ideas. Hope they help.

James Edward Gray II

···

On Oct 11, 2005, at 3:27 PM, Robert Boone wrote:

James Edward Gray II wrote:

> Hello,
> I'm trying to learn ruby so I am making a tic tac toe game. It is
> based
> on the example the pugs example directory. I'm looking for advice
> on how
> to
> make the script more ruby like.

Well, let's have a peek:

> #!/usr/bin/ruby
>
> # Add the ability to more than one object
> # out of a collection
> class Array
> def pick(num)
> (0...self.length).step(num) do
> >i> yield self[i...i+num]
> end
> end
> end

Clever, I like that.

> # Print Tic Tac Toe board
> def print_board(b)
> puts "+---+---+---+"
> b.pick(3) do |x,y,z|
> puts "| #{x} | #{y} | #{z} |"
> puts "+---+---+---+"
> end
> end

Looks good here.

> # Test if there is a winner on the board
> def winner?(game_board)
> winning_set = [[ 0, 1, 2 ],[ 3, 4, 5 ],[ 6, 7, 8 ],[ 0, 3, 6 ],
> [ 1, 4, 7 ],[ 2, 5, 8 ],[ 0, 4, 8 ],[ 2, 4, 6 ]]
> winning_set.each do |x|
> test_set = game_board.values_at(x[0],x[1],x[2])
> raise "has won!" if (test_set == %w{X X X} || test_set == %w{O
> O O})
> end
> end

WINS = [[ 0, 1, 2 ],[ 3, 4, 5 ],[ 6, 7, 8 ],[ 0, 3, 6 ],
         [ 1, 4, 7 ],[ 2, 5, 8 ],[ 0, 4, 8 ],[ 2, 4, 6 ]]

def winner?( game_board )
   WINS.any? do |win|
     game_board.values_at(*win).join =~ /^([XO])\1\1$/ ? $1 : nil
   end
end

class Array
  def winner?
    WINS.any? { |pat| a = self.values_at( *pat ).uniq
      a == ["X"] || a == ["O"]
    }
  end
end

> # Build game board and fill it with .
> board =
> 9.times do |x|
> board << '.'
> end

9.times do
  board << '.'
end

Or:

board = ( ". " * 9 ).split

board = Array.new(0) { "." }

After this, "print_board( board )" produces

···

On Oct 11, 2005, at 3:27 PM, Robert Boone wrote:

+---+---+---+

> player = 'X'
> choice = ''
> used =
>
> print_board board
>
> puts "Pick a number 1-9."
> while board.any? {|square| square == '.' }
> print "#{player}'s turn> "
> choice = gets.chomp
>
> exit if choice =~ /[Qq](?:uit)?/

  exit if choice =~ /^[Qq]/

choice = choice.to_i # might as well just convert it once

> if used.any? {|number| number == choice.to_i}

if used.include? choice

> puts "Number #{choice} has been used!"
> next
> elsif not (1..9).include?(choice.to_i)
> puts "Out of range."
> next
> end
>
> used << choice.to_i
>
> board[choice.to_i-1] = player
> print_board board
>
> begin
> winner?(board)
> rescue => e
> puts "#{player} #{e}"
> exit
> end

if winner = winner?
   puts "#{winner} has won!"
end

That would have to be
  if winner = winner?( board )
And it would print "true has won!"

if board.winner?
  puts "#{player} has won!"
  exit
end

> player = (player == 'X') ? 'O': 'X'
> end
>
> puts "Cat won the game."

An alternative:

require "enumerator"

def print_board( b )
   puts "+---+---+---+"
   b.each_slice(3) do |row|
     puts "| #{row.join(' | ')} |"
     puts "+---+---+---+"
   end
end

See tomorrow's Ruby Quiz summary for a detailed explanation... :wink:

James Edward Gray II

···

On Oct 11, 2005, at 3:46 PM, James Edward Gray II wrote:

#!/usr/bin/ruby

# Add the ability to more than one object
# out of a collection
class Array
  def pick(num)
     (0...self.length).step(num) do
       >i> yield self[i...i+num]
     end
  end
end

Clever, I like that.

# Print Tic Tac Toe board
def print_board(b)
  puts "+---+---+---+"
  b.pick(3) do |x,y,z|
    puts "| #{x} | #{y} | #{z} |"
    puts "+---+---+---+"
  end
end

Looks good here.