<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: Pousse code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Fri, 25 Jul 2008 09:55:03 GMT</pubDate>
    <description>DZone Snippets: Pousse code</description>
    <item>
      <title>Pousse (Game)</title>
      <link>http://snippets.dzone.com/posts/show/5460</link>
      <description>&lt;code&gt;&lt;br /&gt;#! /usr/bin/ruby&lt;br /&gt;# Pousse.rb   Ruby implementation of the game of Pousse.&lt;br /&gt;class Hash&lt;br /&gt;  #add a method to Hash that gets the next key in the hash, given a key.&lt;br /&gt;  def next(key)&lt;br /&gt;    keys = self.keys&lt;br /&gt;    pos  = keys.index(key)&lt;br /&gt;    if pos+1 == keys.length&lt;br /&gt;      return keys[0]&lt;br /&gt;    else&lt;br /&gt;      return keys[pos+1]&lt;br /&gt;    end&lt;br /&gt;  end  &lt;br /&gt;end&lt;br /&gt;  &lt;br /&gt;class Pousse&lt;br /&gt;  def initialize(size = 4)&lt;br /&gt;    @size       = size.to_i.freeze                      #our size can't change&lt;br /&gt;    @board      = Array.new(@size){ Array.new(@size) }  #2d board array&lt;br /&gt;    @previous   = []                                    #previous boards&lt;br /&gt;    @players    = {:one =&gt; 'X', :two =&gt; 'O'}.freeze     #hash of players as:&lt;br /&gt;                                                        # :name =&gt; piece&lt;br /&gt;    run                                                 #run the game&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #returns true if a victor is found, false if not&lt;br /&gt;  def victory?&lt;br /&gt;    grand_total = Hash.new(0)&lt;br /&gt;    inv_players = @players.invert&lt;br /&gt;    &lt;br /&gt;    #add all the rows/cols representing a straight to grand_total&lt;br /&gt;    @board.each_index do |x|&lt;br /&gt;      r_sub, c_sub = Hash.new(0), Hash.new(0)&lt;br /&gt;      @board[x].each_index do |y|&lt;br /&gt;        r_sub[inv_players[@board[x][y]]] += 1 if @board[x][y]&lt;br /&gt;        c_sub[inv_players[@board[y][x]]] += 1 if @board[y][x]&lt;br /&gt;      end&lt;br /&gt;      #add up subtotal vals&lt;br /&gt;      [c_sub, r_sub].each do |a|&lt;br /&gt;        a.each do |x|&lt;br /&gt;          grand_total[x[0]] += 1 if x[1] == @size&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    #check for victory with straights&lt;br /&gt;    if grand_total.values.inject{|sum, n| sum+n}&lt;br /&gt;      if grand_total[@player] == grand_total[@players.next(@player)]&lt;br /&gt;        puts "It's a tie!"&lt;br /&gt;      elsif grand_total[@player] &gt; grand_total[@players.next(@player)]&lt;br /&gt;        puts "Player #{@player.to_s}, you win!"&lt;br /&gt;        return true&lt;br /&gt;      else&lt;br /&gt;        puts "Player #{@players.next(@player)}, you win!"&lt;br /&gt;        return true&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    #check to see if this board is not a new one..&lt;br /&gt;    @previous.each do |x|&lt;br /&gt;      if x == @board&lt;br /&gt;        puts "Player #{@player.to_s}, that board is a REPEAT! YOU LOSE!"&lt;br /&gt;        return true&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    #add a deep copy of the current board to the previous board list&lt;br /&gt;    @previous &lt;&lt; Marshal.load(Marshal.dump(@board))&lt;br /&gt;    false&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #print help messages&lt;br /&gt;  def display_help&lt;br /&gt;    puts "--------"&lt;br /&gt;    puts "General commands:&lt;br /&gt;    h - display this help dialog&lt;br /&gt;    d - draw the board&lt;br /&gt;    q - quit the program"&lt;br /&gt;    &lt;br /&gt;    puts "move? commands (i is an integer from 1 to #{@size})&lt;br /&gt;    Li - Left&lt;br /&gt;    Ri - Right&lt;br /&gt;    Ti - Top&lt;br /&gt;    Bi - Bottom"&lt;br /&gt;    puts "--------"&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #draw a grid representing current board status&lt;br /&gt;  def draw_board&lt;br /&gt;    #build numbers for top&lt;br /&gt;    print "\n  "&lt;br /&gt;    @size.times do |x|&lt;br /&gt;      print " #{x+1}"&lt;br /&gt;    end&lt;br /&gt;    puts ""&lt;br /&gt;    &lt;br /&gt;    #main board section&lt;br /&gt;    (@size * 2).times do |x|&lt;br /&gt;      if (x % 2 == 0) #print a boundry&lt;br /&gt;        print "  "&lt;br /&gt;        @size.times { print "+-" }&lt;br /&gt;        puts "+"&lt;br /&gt;      else #print a data row&lt;br /&gt;        print "#{x/2+1} "&lt;br /&gt;        @size.times do |y|&lt;br /&gt;          print "|"&lt;br /&gt;          print @board[x/2][y] ? @board[x/2][y] : " "&lt;br /&gt;        end&lt;br /&gt;        puts "|"&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    #bottom border&lt;br /&gt;    print "  "&lt;br /&gt;    @size.times { print "+-" }&lt;br /&gt;     puts "+"&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  #execute a move? command. returns true if the move? was successful,&lt;br /&gt;  #false if not&lt;br /&gt;  def move?(command)&lt;br /&gt;    direction, row = command.split(//)&lt;br /&gt;    row = row.to_i&lt;br /&gt;    &lt;br /&gt;    if row &gt; @size or row &lt; 1 #we have a problem.&lt;br /&gt;      puts "Invalid index value (#{row}) supplied."&lt;br /&gt;      return false&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    row -= 1 #offset because of array index&lt;br /&gt;    &lt;br /&gt;    #setup values for shift_board call&lt;br /&gt;    case direction.upcase&lt;br /&gt;      when "L" then x = row;      y = 0;        dx = 0;   dy =  1&lt;br /&gt;      when "R" then x = row;      y = @size-1;  dx = 0;   dy = -1&lt;br /&gt;      when "T" then x = 0;        y = row;      dx = 1;   dy =  0&lt;br /&gt;      when "B" then x = @size-1;  y = row ;     dx = -1;  dy =  0&lt;br /&gt;    end&lt;br /&gt;    shift_board(x, y, dx, dy, @players[@player])&lt;br /&gt;    true&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #game run loop. this method returns when the game is over&lt;br /&gt;  def run&lt;br /&gt;    puts "Welcome to Pousse!"&lt;br /&gt;    display_help&lt;br /&gt;    @player = :one&lt;br /&gt;    loop do&lt;br /&gt;      puts "Player #{@player.to_s}'s (#{@players[@player]}) turn."&lt;br /&gt;      &lt;br /&gt;      #get a value from the command line&lt;br /&gt;      print "&gt; "&lt;br /&gt;      _input = $stdin.gets&lt;br /&gt;      &lt;br /&gt;      #process the input&lt;br /&gt;      if    _input =~ /^[q|Q]/                  then break&lt;br /&gt;      elsif _input =~ /^[h|H]/                  then display_help&lt;br /&gt;      elsif _input =~ /^[d|D]/                  then draw_board&lt;br /&gt;      elsif _input =~ /^[L|R|T|B|l|r|t|b][\d]/  then&lt;br /&gt;        if move?(_input)&lt;br /&gt;           draw_board&lt;br /&gt;           break if victory? #exit the loop if we find a winner&lt;br /&gt;           @player = @players.next(@player)&lt;br /&gt;        end&lt;br /&gt;      else puts "Command not recognized."&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    puts "Thanks for playing Pousse!"&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #shift cells in the board until our new data is appended and old data&lt;br /&gt;  #is shifted into blank spaces or lost&lt;br /&gt;  def shift_board(to_x, to_y, dx, dy, append)&lt;br /&gt;    if to_y &lt; @size and to_x &lt; @size then #only handle existing cells&lt;br /&gt;      if @board[to_x][to_y] != nil then&lt;br /&gt;        mv = @board[to_x][to_y]&lt;br /&gt;        @board[to_x][to_y] = nil&lt;br /&gt;        shift_board(to_x+dx, to_y+dy, dx, dy, mv)&lt;br /&gt;      end&lt;br /&gt;      @board[to_x][to_y] = append&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;if ARGV[0]&lt;br /&gt;  Pousse.new(ARGV[0]) &lt;br /&gt;else&lt;br /&gt;  Pousse.new&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Mon, 05 May 2008 03:26:22 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/5460</guid>
      <author>psychomonkey (Allyn Bauer)</author>
    </item>
  </channel>
</rss>
