<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:refactormycode.com,2007:users435</id>
  <link type="application/atom+xml" href="http://refactormycode.com/users/435" rel="self"/>
  <title>elise.huard.myopenid.com</title>
  <updated>Tue Jan 01 20:50:15 +0000 2008</updated>
  <entry>
    <id>tag:refactormycode.com,2007:Code201</id>
    <published>2008-01-01T20:50:15+00:00</published>
    <updated>2008-03-21T16:38:17+00:00</updated>
    <title>[Ruby] connect-four</title>
    <content type="html">&lt;p&gt;You probably know the game of connect-four.  2 player alternatively drop a token in a grid (which i called board).  I wrote the following ruby classes for the game.  The board is organized in columns (in which you drop the tokens).  
&lt;br /&gt;All suggestions are welcome, i'll enjoy seeing any suggestions or variations !
&lt;br /&gt;I'm an experienced developer, but not in Ruby.&lt;/p&gt;

&lt;pre&gt;class ConnectFourBoard
  AIM = 4 # number of neighbouring tokens to obtain

  def initialize(rows,columns)
    @rows = rows  # number of rows
    @columns = columns  # number of columns
    @board = Array.new(@columns)
  end

  #  A player drop a token in the board at a certain position
  def drop_token(player,column)
    if @board[column] == nil
      @board[column] = Array.new
    end
    if @board[column].length == @rows
      raise RuntimeException
    end
    @board[column].push(Token.new(player))
  end

  # check the presencd of a token at a certain position in the board
  def position(row,column)
    col = @board[column]
    if !col.nil?
      position = col[row];
    else 
      return nil
    end
  end
  
  # empty board
  def reset
    @board.each do |column|
      column = nil
    end
    @board = nil
    initialize(@rows,@columns)
  end
  
  # check if a player has won
  def check_winner(player)
    win = vertical_count(player) || horizontal_count(player) ||
          diagonal_count(player) || back_diagonal_count(player)
  end

 private
  # check if there was a victory in vertical direction of board
  def vertical_count(player)
    win = false
    @board.each do |column|
      counter = 0
      if column.nil?
        next
      end
      column.each do |position|
        counter = increment(position,player,counter)
        win = win || win(counter) #if won it stays won
      end
    end
    win # return if won
  end

  # check if there was a victory in the horizontal direction of board
  def horizontal_count(player)
    win = false
    (0..@rows-1).each do |row|
      counter = 0
      @board.each_with_index do |column,column_index|
        if column.nil?
          counter = 0
        end
        position = position(row,column_index)
        counter = increment(position,player,counter)
        win = win || win(counter) # if won it stays won
      end
    end

    win # return if won
  end

# back_diagonal_count counts the tokens from a same player in diagonal line
# the &amp;quot;back&amp;quot; stands for \ (backslash) as in the direction of the diagonal
  def back_diagonal_count(player)
    win = false
    (AIM-1..@columns-1).each do |i|
      counter = 0
      rowlimit = @rows-1 &amp;gt; i ? i : @rows-1
      (0..rowlimit).each do |j|
        position = position (j,i-j)
        counter = increment(position,player,counter)
        win = win || win(counter)
      end
    end
    win # return if won
  end
  
# diagonal_count counts the tokens from a same player in diagonal line
# the counting happens in the / direction (slash) = direction of the diagonal 
  def diagonal_count(player)
    win = false
    (0..@columns-AIM).each do |i|
      counter = 0
      rowlimit = @rows-1-i
      (0..rowlimit).each do |j|
         position = position(j,i+j)
         counter = increment(position,player,counter)
         win = win || win(counter)
      end
    end    
    win
  end

  def increment(position,player,counter)
    if position &amp;amp;&amp;amp; position.player == player
      return counter.next
    else
      return 0
    end
  end
  
  def win(counter)
    if counter &amp;gt;= AIM
      return true
    else
      return false
    end    
  end

# for debugging purposes: to display the board as 0 and 1  
  def board_debug
    (0..@rows-1).each do |row|  
      @board.each_with_index do |column,index|
        position = position(@rows-1-row,index)
        if position 
          printf(&amp;quot;#{position.player.to_i}&amp;quot;)
        else
          printf(&amp;quot; &amp;quot;)
        end
      end
      printf(&amp;quot;\n&amp;quot;)
    end  
  end
end

# class token in board
class Token
  def initialize(player)
    @player = player
  end
  def player
    @player
  end
end


&lt;/pre&gt;</content>
    <author>
      <name>elise.huard.myopenid.com</name>
      <email>myopenid@elisehuard.be</email>
    </author>
    <link type="text/html" href="http://refactormycode.com/codes/201-connect-four" rel="alternate"/>
  </entry>
</feed>
