Learning ruby by make a simple game...

R

Robert Boone

--=-0QjTykESxBTBvTz8ZNbf
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

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


--=-0QjTykESxBTBvTz8ZNbf
Content-Disposition: attachment; filename=tic-tac-toe.rb
Content-Type: application/x-ruby; name=tic-tac-toe.rb
Content-Transfer-Encoding: 7bit

#!/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

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

# 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

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

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)?/

if used.any? {|number| number == choice.to_i}
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

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

puts "Cat won the game."

--=-0QjTykESxBTBvTz8ZNbf--
 
J

James Edward Gray II

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
 
W

William James

James said:
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

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

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
 
J

James Edward Gray II

#!/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.

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... ;)

James Edward Gray II
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,698
Latest member
LydiaHalle

Latest Threads

Top