[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[QUIZ] Kalah (#58

James Gray

12/9/2005 1:28:00 PM

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rub...

3. Enjoy!

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Mark Van Holstyn

For my Computer Science class this month, we had to program a Kalah Player.
Sadly, we had to do our project in Java, but I ported the game code and the
sample players to ruby for this quiz though.

A good explanation of the game can be found at:

http://rubyu...

Your task is to create the best Kalah player you can. The player should look
like the following:

class HumanPlayer < Player
def choose_move
print 'Enter your move choice: '
gets.chomp.to_i
end
end

The 'choose_move' method is what the game will call to request a move from the
player. The Player class which you player should extend looks like so:

class Player
attr_accessor :name
attr_writer :game, :side

def initialize( name )
@name = name
end

def choose_move
if @side==KalahGame::TOP
(7..12).each { |i| return i if @game.stones_at?(i) > 0 }
else
(0..5).each { |i| return i if @game.stones_at?(i) > 0 }
end
end
end

The 'game' and 'side' attributes will be assigned by KalahGame. The side will
either be the constant KalahGame::TOP or KalahGame::BOTTOM. This is what you
will use to determine if you should be making moves from bowls 0-5 or 7-12 and
whether your Kalah is 6 or 13.

KalahMatch plays two games, one with each player on the each side of the board
and then averages their scores, so you must make you player be able to play both
on the top and the bottom.

Here's a sample game engine to get you started:

require 'Player'
require 'HumanPlayer'

class KalahMatch
def start( p1, p2 )
puts ''
puts '========== GAME 1 =========='
p1_score_1, p2_score_1 = KalahGame.new.play_game( p1, p2 )

if p1_score_1 > p2_score_1
puts p1.name+' won game #1: '+p1_score_1.to_s+'-'+p2_score_1.to_s
elsif p2_score_1 > p1_score_1
puts p2.name+' won game #1: '+p2_score_1.to_s+'-'+p1_score_1.to_s
else
puts 'game #1 was a tie: '+p1_score_1.to_s+'-'+p2_score_1.to_s
end

puts ''
puts '========== GAME 2 =========='
p2_score_2, p1_score_2 = KalahGame.new.play_game( p2, p1 )

if p1_score_2 > p2_score_2
puts p1.name+' won game #2: '+p1_score_2.to_s+'-'+p2_score_2.to_s
elsif p2_score_2 > p1_score_2
puts p2.name+' won game #2: '+p2_score_2.to_s+'-'+p1_score_2.to_s
else
puts 'game #2 was a tie: '+p1_score_2.to_s+'-'+p2_score_2.to_s
end

puts ''
puts '========== FINAL =========='

p1_final = p1_score_1+p1_score_2
p2_final = p2_score_1+p2_score_2

if p1_final > p2_final
puts p1.name+' won the match: '+p1_final.to_s+'-'+p2_final.to_s
elsif p2_final > p1_final
puts p2.name+' won the match: '+p2_final.to_s+'-'+p1_final.to_s
else
puts 'the match was tied overall : '+p1_final.to_s+'-'+p2_final.to_s
end
end
end

class KalahGame
NOBODY = 0
TOP = 1
BOTTOM = 2

def stones_at?( i )
@board[i]
end

def legal_move?( move )
( ( @player_to_move==TOP and move >= 7 and move <= 12 ) ||
( @player_to_move==BOTTOM and move >= 0 and move <= 5 ) ) and
@board[move] != 0
end

def game_over?
top = bottom = true
(7..12).each { |i| top = false if @board[i] > 0 }
(0..5).each { |i| bottom = false if @board[i] > 0 }
top or bottom
end

def winner
top, bottom = top_score, bottom_score
if top > bottm
return TOP
elsif bottom > top
return BOTTOM
else
return NOBODY
end
end

def top_score
score = 0
(7..13).each { |i| score += @board[i] }
score
end

def bottom_score
score = 0
(0..6).each { |i| score += @board[i] }
score
end

def make_move( move )
( puts 'Illegal move...' ; return ) unless legal_move?( move )

stones, @board[move] = @board[move], 0

pos = move+1
while stones > 0
pos+=1 if( (@player_to_move==TOP and pos==6) ||
(@player_to_move==BOTTOM and pos==13) )
pos = 0 if pos==14
@board[pos]+=1
stones-=1
pos+=1 if stones > 0
end

if( @player_to_move==TOP and pos>6 and pos<13 and @board[pos]==1 )
@board[13] += @board[12-pos]+1
@board[12-pos] = @board[pos] = 0
elsif( @player_to_move==BOTTOM and pos>=0 and pos<6 and @board[pos]==1 )
@board[6] += @board[12-pos]+1
@board[12-pos] = @board[pos] = 0
end

if @player_to_move==TOP
@player_to_move = BOTTOM unless pos == 13
else
@player_to_move=TOP unless pos == 6
end

end

def display
puts ''
top = ' '
[12,11,10,9,8,7].each { |i| top += @board[i].to_s+' ' }
puts top
puts @board[13].to_s + ' ' + @board[6].to_s
bottom = ' '
(0..5).each { |i| bottom += @board[i].to_s+' ' }
puts bottom
puts ''
end

def reset
@board = Array.new( 14, 4 )
@board[6] = @board[13] = 0
@player_to_move = BOTTOM
end

def play_game( bottom, top )
reset

bottom.side = BOTTOM
top.side = TOP
top.game = bottom.game = self

puts bottom.name+' starts...'
display

until game_over?
puts ''
if @player_to_move == TOP
move = top.choose_move
puts top.name+' choose move '+move.to_s
else
move = bottom.choose_move
puts bottom.name+' choose move '+move.to_s
end
make_move( move )
display
end

[top_score, bottom_score]
end
end

p1 = Player.new( 'Player 1' )
p2 = Player.new( 'Player 2' )
KalahMatch.new.start( p1, p2 )


26 Answers

Adam Shelly

12/9/2005 6:27:00 PM

0

Unless I'm really misreading the rules, there's a bug in the KalahGame class:


> def play_game( bottom, top )
> reset
## Play the game here...
> [top_score, bottom_score]
> end

It's returning the scores in the reverse order of the players..
So in KalahMatch, it reports the wrong winnner:
> puts '========== GAME 1 =========='
> p1_score_1, p2_score_1 = KalahGame.new.play_game( p1, p2 )

I think the last line of KalahGame#play_game should be:
[bottom_score, top_score]

-Adam


James Gray

12/9/2005 6:44:00 PM

0

On Dec 9, 2005, at 12:26 PM, Adam Shelly wrote:

> Unless I'm really misreading the rules, there's a bug in the
> KalahGame class:
>
>
>> def play_game( bottom, top )
>> reset
> ## Play the game here...
>> [top_score, bottom_score]
>> end
>
> It's returning the scores in the reverse order of the players..
> So in KalahMatch, it reports the wrong winnner:
>> puts '========== GAME 1 =========='
>> p1_score_1, p2_score_1 =
>> KalahGame.new.play_game( p1, p2 )
>
> I think the last line of KalahGame#play_game should be:
> [bottom_score, top_score]

I agree. That looks like a bug.

Thanks for pointing it out.

James Edward Gray II

P.S. If anyone enhances the game engine and wants to share the
changes, I don't consider that a spoiler...


Kero van Gelder

12/9/2005 7:23:00 PM

0

> I agree. That looks like a bug.

You want bugs? There's bttom or bottm somewhere in the code.

Bill Guindon

12/9/2005 7:58:00 PM

0

On 12/9/05, Kero <kero@chello.single-dot.nl> wrote:
> > I agree. That looks like a bug.
>
> You want bugs? There's bttom or bottm somewhere in the code.

Yep, in the 'winner' code:

def winner
top, bottom = top_score, bottom_score
if top > bottm

--
Bill Guindon (aka aGorilla)


James Gray

12/9/2005 8:59:00 PM

0

On Dec 9, 2005, at 1:57 PM, Bill Guindon wrote:

> On 12/9/05, Kero <kero@chello.single-dot.nl> wrote:
>>> I agree. That looks like a bug.
>>
>> You want bugs? There's bttom or bottm somewhere in the code.
>
> Yep, in the 'winner' code:
>
> def winner
> top, bottom = top_score, bottom_score
> if top > bottm

Ah yes. That's another one. Thanks you two.

James Edward Gray II


Stephen Waits

12/9/2005 9:40:00 PM

0

James Edward Gray II wrote:
>
> Ah yes. That's another one. Thanks you two.

Is there a place where we can easily grab the most recent version?

Thanks,
Steve



James Gray

12/9/2005 9:52:00 PM

0

On Dec 9, 2005, at 3:40 PM, Stephen Waits wrote:

> James Edward Gray II wrote:
>> Ah yes. That's another one. Thanks you two.
>
> Is there a place where we can easily grab the most recent version?

Sure. I've put it up here:

http://rubyquiz.com/Kal...

James Edward Gray II


David Balmain

12/10/2005 3:09:00 AM

0

Could we add this enhancement. It makes searching a lot easier.

class KalahGame
attr_reader :board, :player_to_move

def initialize_copy(other_game)
super
@board = other_game.board.dup
end
end

Cheers,
Dave

On 12/10/05, James Edward Gray II <james@grayproductions.net> wrote:
> On Dec 9, 2005, at 3:40 PM, Stephen Waits wrote:
>
> > James Edward Gray II wrote:
> >> Ah yes. That's another one. Thanks you two.
> >
> > Is there a place where we can easily grab the most recent version?
>
> Sure. I've put it up here:
>
> http://rubyquiz.com/Kal...
>
> James Edward Gray II
>
>


James Gray

12/10/2005 3:21:00 AM

0

On Dec 9, 2005, at 9:09 PM, David Balmain wrote:

> Could we add this enhancement. It makes searching a lot easier.
>
> class KalahGame
> attr_reader :board, :player_to_move
>
> def initialize_copy(other_game)
> super
> @board = other_game.board.dup
> end
> end

I'm pretty sure I did what you wanted. Double check me please.

http://rubyquiz.com/Kal...

James Edward Gray II


David Balmain

12/10/2005 3:33:00 AM

0

On 12/10/05, James Edward Gray II <james@grayproductions.net> wrote:
> On Dec 9, 2005, at 9:09 PM, David Balmain wrote:
>
> > Could we add this enhancement. It makes searching a lot easier.
> >
> > class KalahGame
> > attr_reader :board, :player_to_move
> >
> > def initialize_copy(other_game)
> > super
> > @board = other_game.board.dup
> > end
> > end
>
> I'm pretty sure I did what you wanted. Double check me please.
>
> http://rubyquiz.com/Kal...

Perfect. Thanks. Sorry I wasn't very clear. :)

Cheers,
Dave

> James Edward Gray II
>
>