<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Torquing Wet Strainers</title>
	<atom:link href="http://torquingwetstrainers.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://torquingwetstrainers.wordpress.com</link>
	<description>Just another WordPress.com weblog</description>
	<lastBuildDate>Wed, 27 Apr 2011 15:04:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='torquingwetstrainers.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Torquing Wet Strainers</title>
		<link>http://torquingwetstrainers.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://torquingwetstrainers.wordpress.com/osd.xml" title="Torquing Wet Strainers" />
	<atom:link rel='hub' href='http://torquingwetstrainers.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Intermission</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/05/16/intermission/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/05/16/intermission/#comments</comments>
		<pubDate>Sun, 16 May 2010 20:04:13 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=142</guid>
		<description><![CDATA[At the beginning of the month, I hit a wall. I have no more &#8220;saved-up&#8221; tic-tac-toe implementations, and it&#8217;s become pretty hard to contemplate taking a couple evenings a week away from my family to make new ones. This is partly because what I&#8217;m doing with them has become less interesting, and thus motivating. The [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=142&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>At the beginning of the month, I hit a wall.  I have no more &#8220;saved-up&#8221; tic-tac-toe implementations, and it&#8217;s become pretty hard to contemplate taking a couple evenings a week away from my family to make new ones.</p>
<p>This is partly because what I&#8217;m doing with them has become less interesting, and thus motivating.  The very nature of the exercise as I set it up, its pace, its limitations—a new implementation of an identical text-based game in a novel language, once a week—have been actually taking me away from the most interesting part, which is learning new ways of thinking.  Several times I&#8217;ve found myself essentially porting another implementation and in the process stripping away all the novel features of the language.  I wrote the <a href="http://torquingwetstrainers.wordpress.com/2010/04/21/tic-tac-toe-clojure/">Clojure</a> post by modifying my scheme program.  It&#8217;s somewhat interesting that this was straightforward to do, and I tried to make the best of it.  But it felt bad, and I don&#8217;t think it was really all that enlightening to learn that you can implement the same simple program similarly in two LISP dialects.</p>
<p>The last one I feel I really did justice was <a href="http://torquingwetstrainers.wordpress.com/2010/03/10/tic-tac-toe-cobra/">Cobra</a>, and that was the last one I really spent some time on.</p>
<p>I&#8217;ve also been avoiding or putting off languages without obvious parallels to things I already know.  This is precisely contrary to the point.  I downloaded Self the other day with the intent to use it for the week&#8217;s program, but found a) that it doesn&#8217;t seem to have a console interface at all, and b) that there&#8217;s no way to even write it outside its image-based environment and GUI.  This clearly counts as novel and interesting, but there&#8217;s no way I&#8217;m ending up with a working program after 4 hours.</p>
<p>So, I&#8217;m pivoting.  I&#8217;ll keep working through the list at a more measured pace, and with much more of a focus on producing end products that reflect the tool&#8217;s capabilities and intent.  I&#8217;ll write GUI programs for Visual Basic and Objective C, for example.  I&#8217;ll figure out some excuse to use goroutines in Go.</p>
<p>If you&#8217;ve been following along because the stunt seemed amusing, I&#8217;m sorry to disappoint.  If it&#8217;s any consolation, I still plan to do brainf*ck and Piet.  But as the man says, when you find yourself in a hole, stop digging.</p>
<p>It would also help me immeasurably if I knew there were people actually reading this stuff.  I don&#8217;t have stats on how many feed readers I have so some weeks it&#8217;s a bit like lecturing to an empty room.  If you&#8217;re still reading but not commenting, would you let me know?</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/142/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/142/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/142/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/142/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/142/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/142/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/142/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/142/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/142/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/142/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/142/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/142/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/142/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/142/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=142&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/05/16/intermission/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: Scala</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/04/28/tic-tac-toe-scala/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/04/28/tic-tac-toe-scala/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 17:27:13 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=136</guid>
		<description><![CDATA[If Clojure is a way to have your LISP and eat your JVM too, Scala seems more like a subversive attempt to introduce the Java world to dynamic and functional programming in friendly clothing.  The whole approach is very Java: syntactically baroque and wordy, but admirably complete and well-documented.  The java integration is more seamless [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=136&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If Clojure is a way to have your LISP and eat your JVM too, Scala seems more like a subversive attempt to introduce the Java world to dynamic and functional programming in friendly clothing.  The whole approach is very Java: syntactically baroque and wordy, but admirably complete and well-documented.  The java integration is more seamless than it is in Clojure.  I was struggling to figure out how to read a line of input the Scala way, and finally gave up and did it like Java.  It worked, it was easy, and most importantly (ha) it didn&#8217;t look out of place.</p>
<p>The downside of syntactical harmony with Java is that it&#8217;s a bit ugly.  For example, if you define a method that returns Unit (void), you can stick the curl brace right next to the method name.  If you give it a return type, you have to stick an equals sign in there.  Not a big deal.  But ugly.</p>
<p>That said, it&#8217;s still way better than bog-standard Java, as a a language.  Type inference, pattern matching, lazy evaluation, optional duck(ish) typing.  Almost everything I like about Ruby structurally, but with relatively unobtrusive type safety.  I&#8217;d miss method_missing under some circumstances, but maybe not enough to matter.  I could definitely see myself doing my next project in Scala + JRuby.</p>
<p>This compiles in Scala 2.7.7.</p>
<pre>

import java.io.{BufferedReader, InputStreamReader}

object TicTacToe {

  private val input = new BufferedReader(new InputStreamReader(System.in))

  def main(args: Array[String]) {

    var result: Result = Continue(X)

    while (true) {

      println
      println(board)
      println
      print(result)

      result match {
        case Continue(player) =&gt; {
            val space = readAnswer
            if (board.spaceAvailable(space)) {
              board.place(space, player)
              result = board.checkResult(player)
            }
        }
        case _ =&gt; return
      }

    }
  }

  def readAnswer: Int = {
    try {
      input.readLine().toInt
    } catch {
      case nfe: NumberFormatException =&gt; 0
    }
  }
}

abstract class Player {
  def next: Player
}
case object X extends Player {
  override def toString() = "X"
  def next = O
}
case object O extends Player {
  override def toString() = "O"
  def next = X
}

abstract class Space
case class Empty(n: Int) extends Space {
  override def toString() = "(" + n + ")"
}
case class Filled(player: Player) extends Space {
  override def toString() = " " + player + " "
}

abstract class Result
case class Win(player: Player) extends Result {
  override def toString() = "" + player + " Wins!\n"
}
case object Draw extends Result {
  override def toString() = "It's a Draw!\n"
}
case class Continue(player: Player) extends Result {
  override def toString() = "Select a square, " + player + ": "
}

object board {
  private val spaces = Array[Space](
    Empty(1),Empty(2),Empty(3),
    Empty(4),Empty(5),Empty(6),
    Empty(7),Empty(8),Empty(9)
  )

  def spaceAvailable(n: Int): Boolean = {
    for (space  return true
        case _ =&gt; ()
      }
    }
    return false
  }

  def full: Boolean = {
    for (space  return false
        case _ =&gt; ()
      }
    }
    return true;
  }

  def checkResult(player: Player): Result = {
    for (row  {
          return Win(p)
        }
        case _ =&gt; ()
      }
    }
    if (full) return Draw
    return Continue(player.next)
  }

  def place(n: Int, player: Player) {
    spaces(n-1) = Filled(player)
  }

  private def get(n: Int): Space = spaces(n-1)

  private def rows: Array[Array[Space]] = {
    Array[Array[Space]](
      spaces.slice(0,3),
      spaces.slice(3,6),
      spaces.slice(6,9),

      Array(get(1),get(4),get(7)),
      Array(get(2),get(5),get(8)),
      Array(get(3),get(6),get(9)),

      Array(get(1),get(5),get(9)),
      Array(get(3),get(5),get(7)))
  }

  override def toString() = {
    spaces(0) + "|" + spaces(1) + "|" + spaces(2) +
    "\n---+---+---\n" +
    spaces(3) + "|" + spaces(4) + "|" + spaces(5) +
    "\n---+---+---\n" +
    spaces(6) + "|" + spaces(7) + "|" + spaces(8)
  }
}
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/136/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=136&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/04/28/tic-tac-toe-scala/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: Clojure</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/04/21/tic-tac-toe-clojure/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/04/21/tic-tac-toe-clojure/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 03:34:58 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=129</guid>
		<description><![CDATA[Clojure, for those who don&#8217;t know, is a newish LISP implemented on top of the JVM. It&#8217;s designed to play nicely with Java libraries, which I didn&#8217;t end up exercising, and is largely lazy and functional, which I did. If you&#8217;ve been following along, you might notice that this implementation is very similar to the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=129&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://clojure.org">Clojure</a>, for those who don&#8217;t know, is a newish LISP implemented on top of the JVM.  It&#8217;s designed to play nicely with Java libraries, which I didn&#8217;t end up exercising, and is largely lazy and functional, which I did.</p>
<p>If you&#8217;ve been following along, you might notice that this implementation is very similar to the one for <a href="/2010/02/24/tic-tac-toe-scheme/">Scheme</a>.  That&#8217;s because I cheated and just ported it over.  There are some <a href="http://hyperpolyglot.wikidot.com/lisp">pointed differences</a> in its API, but it was actually pretty easy to translate.  No major changes in the basic logic, with the exception of one function which I had to rewrite to get around a JVM-imposed restriction on how recursive you can get inside a <code>let</code>.</p>
<p>I like scheme better on purely aesthetic grounds, but Clojure seems more useful, and is certainly more relevant lately.  A few notable innovations:</p>
<ul>
<li>Shortcut lambdas: <code>#(+ %1 10) =&gt; (fn [x] (+ x 10))</code></li>
<li>Extensive use of vectors as syntactic distinguishers, e.g. denoting function parameters</li>
<li>Java Method calls: <code>(.toString x)</code></li>
<li>Lots more that I didn&#8217;t end up using</li>
</ul>
<p>Here&#8217;s the code:</p>
<pre>; Defining the players -- Infinite Lazy Sequence
(def players (cycle ["X" "O"]))

; Setting up the board
(def *starting-board*
	 [[1 2 3]
	  [4 5 6]
	  [7 8 9]])

(defn space-available? [space board]
	  (some (fn [row] (some #(= %1 space) row)) board))

; Moving -- returns a transformed board
(defn move [player space board]
	  (letfn [(move-in-row
			   ([accum row]
				 (cond
				   ; if we reach the end, that's it
				   (empty? row) accum
				   ; if we have found the space, take it
				   (= space (first row)) (concat accum (cons player (rest row)))
				   ; if not, keep going
				   true (recur (concat accum (list (first row))) (rest row))))
				 ([row] (move-in-row '() row)))]
		(map move-in-row board)))

(defn space-&gt;string [space]
	  (if (number? space)
		(str "(" space ")")
		(str " " space " ")))

(defn row-&gt;string [row] (apply str (interpose "|" (map space-&gt;string row) )))

(defn board-&gt;string [board]
	  (apply str (interpose "\n---+---+---\n" (map row-&gt;string board))))

(defn third [seq] (nth seq 2))

(defn winner? [board]
	  (or
		; rows
		(apply = (first board))
		(apply = (second board))
		(apply = (third board))
		; columns
		(apply = (map first board))
		(apply = (map second board))
		(apply = (map third board))
		; diagonals
		(= (first (first board))
		   (second (second board))
		   (third (third board)))
		(= (third (first board))
		   (second (second board))
		   (first (third board)))))

(defn full? [board]
	  (not (some number? (mapcat identity board))))

(defn print-board [board]
	  (do
		(newline)
		(print (board-&gt;string board))
		(newline)
		(newline)))

(defn play [board players]
	  (do
		(print-board board)
		(let [ player (first players) ]
		  (cond
			(winner? board) (print (str (first (next players))  " Wins!\n"))
			(full? board) (print "It's a Draw!\n")
			true (do
				   (print (str "Select a square, " player ": "))
				   (flush)
				   (let [answer (read)]
					 (if (and answer (space-available? answer board))
					   (recur (move player answer board) (next players))
					   (recur board players))))))))

(play *starting-board* players)</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/129/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/129/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/129/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=129&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/04/21/tic-tac-toe-clojure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: Awk</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/04/14/tic-tac-toe-awk/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/04/14/tic-tac-toe-awk/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 17:00:36 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=125</guid>
		<description><![CDATA[Awk&#8217;s original intended use is as a stream processor, and in fact in its most basic form you can&#8217;t even do explicit input. My first version of this used gawk/nawk extensions for that purpose, but I figured it would be a bit more fun to use input patterns, so that&#8217;s what you see here. Perl [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=125&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Awk&#8217;s original intended use is as a stream processor, and in fact in its most basic form you can&#8217;t even do explicit input.  My first version of this used gawk/nawk extensions for that purpose, but I figured it would be a bit more fun to use input patterns, so that&#8217;s what you see here.</p>
<p>Perl fans (and thus, Ruby and Python fans) might recognize an ancestor here.</p>
<pre>
#!/usr/bin/env awk -f

BEGIN {
	split("1 2 3 4 5 6 7 8 9", spaces)
	player = "X"

	print_board()
	print_prompt()
}

/[0-9]/ { place_move($1) }
/./ { print_board(); print_prompt() }

function print_board () {
	print ""
	for (i = 1; i &lt;= 9; i++) {
		space = spaces[i]
		if (space ~ /[0-9]/)
			printf(&quot;(%d)&quot;, space);
		else
			printf(&quot; %s &quot;, space);

		if (i % 3 == 0) {
			if (i / 3 &lt; 3) {
				printf &quot;\n---+---+---\n&quot;;
			}
		} else {
			printf &quot;|&quot;;
		}
	}

	print &quot;\n&quot;
}

function print_prompt () {
	printf &quot;Select a square, %s: &quot;, player
}

function read_move () {
	getline move
}

function place_move (move) {
	if (move &amp;&amp; spaces[move] == move) {
		spaces[move] = player
		good_move = 0

		if (keep_playing()) {
			swap_player()
		} else {
			exit 0
		}
	}
}

function swap_player () {
	if (player == &quot;X&quot;)
		player = &quot;O&quot;
	else
		player = &quot;X&quot;
}

function m3(i, j, k) {
	return spaces[i] == spaces[j] &amp;&amp; spaces[j] == spaces[k]
}

function has_winner () {
	return m3(1,2,3) ||
		   m3(4,5,6) ||
		   m3(7,8,9) ||
		   m3(1,4,7) ||
		   m3(2,5,8) ||
		   m3(3,6,9) ||
		   m3(1,5,9) ||
		   m3(3,5,7);
}

function is_draw () {
	for (i = 1; i &lt;= 9; i++) {
		space = spaces[i]
		if (space ~ /[0-9]/)
			return 0;
	}
	return 1
}

function keep_playing() {
	if (has_winner()) {
		print_board()
		printf(&quot;%s Wins!\n&quot;, player)
		return 0;
	} else if (is_draw()) {
		print_board()
		print(&quot;It&#39;s a Draw!&quot;)
		return 0;
	} else
		return 1;
}
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/125/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=125&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/04/14/tic-tac-toe-awk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: Haskell</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/04/07/tic-tac-toe-haskell/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/04/07/tic-tac-toe-haskell/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 15:31:07 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=116</guid>
		<description><![CDATA[Haskell is seriously packed with modern, interesting, expressive goodies. But I have a message for the Haskell community: stop trying to &#8220;simplify&#8221; monads.  Really, just stop.  I have yet to see an &#8220;explanation&#8221; of monads that does not add to the confusion and fear a novice might feel at approaching the language.  You don&#8217;t need [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=116&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Haskell is seriously packed with modern, interesting, expressive goodies.</p>
<p>But I have a message for the Haskell community: stop trying to &#8220;simplify&#8221; monads.  Really, just stop.  I have yet to see an &#8220;explanation&#8221; of monads that does not add to the confusion and fear a novice might feel at approaching the language.  You don&#8217;t need to know what a monad is in order to use the language effectively.  Talking about them to a beginner is about as useful as explaining loop unrolling and keyhole optimization to a beginning C programmer.  Later, yes, it&#8217;s helpful.  But it&#8217;s too much information at the start.  A beginner just needs to know that if you want to use code that does IO, it has to go inside a <code>do</code>, and if you want to pull out values and use them elsewhere, you need the <code>&lt;-</code> operator.  It took me three nights of working on this one to learn that one, because the Gentle Introduction relegated I/O to chapter 7.</p>
<p>On that note, you&#8217;ve got to stop treating I/O in general as a red-headed stepchild.  I realize that isolating side effects is one of the <em>raisons d&#8217;être</em> for Haskell in the first place, but if you hope to win converts from the programming world at large (and I really hope you do) then you&#8217;ve got to understand that most of us mere mortals want our programs to <strong><em>do something</em><span style="font-weight:normal;">, and that means input/output.  I understand, or at least I think I do, that you want to instill good habits from the start and minimize time spend in the IO monad, but honestly, the language is pretty good at doing that already.  You&#8217;ve got to go and talk to people where they already are before you can lead them somewhere else.</span></strong></p>
<p>Once peple get used to IO and Maybe and whatever other monads are out there, <em>then </em>you can introduce the concept because there&#8217;s somewhere for it to land.  I remember taking CS theory in college, and talking with one of the TFs who I happened to know socially.  He is an extremely bright guy, and as is sometimes common with bright guys, can have trouble explaining a concept to someone who doesn&#8217;t get it themselves right away.  I made plea for more concrete examples to go with the theoretical explanations in the class, and his response was, &#8220;Well, we assume that you, the smart [name of school] students, can come up with the examples yourselves.&#8221;  This is exactly wrong for many many people out there, including a lot of the folks who are attracted to coding in the first place.  Some folks work well top-down &#8212; get the overarching concepts and then fill in the details themselves.  But some people learn the other way around &#8212; experience the details, and then build up the framework from there.  My impression is that the Haskell community is filled with the former type of learner.  But it&#8217;s a great language, even for the more experiential/practical and less theoretical, and I hate to see it shunned as too scary.</p>
<p>Ranting aside, I really enjoyed writing this.  For those of you who haven&#8217;t tried it yet, I highly recommend it.  It <em>will</em> make you smarter.  I stumbled on places where it differs from OCaml, and I got stuck on IO for a while, but I&#8217;m glad I persevered.</p>
<p>This was written against GHC 6.10.4.</p>
<pre>

import Data.List (intersperse)
import System.IO (stdout, hFlush)
import System.Exit (exitSuccess)

--
-- Users
--
data User = X | O
    deriving(Show, Eq)

otherUser X = O
otherUser O = X

--
-- Squares
--
data Square = Move User | Empty Int
    deriving(Eq)

instance Show Square where
    show (Move x)   = " " ++ show x ++ " "
    show (Empty x)  = "(" ++ show x ++ ")"

filled (Move _) = True
filled _        = False

--
-- Boards
--
data Board = Board [[Square]]
    deriving(Eq)

instance Show Board where
    show (Board ls) = "\n" ++ concat (intersperse "---+---+---\n" $ map showLine ls) ++ "\n"
        where
            showLine xs = concat (intersperse "|" $ map show xs) ++ "\n"

full (Board squares) = all filled (concat squares)

--
-- Results
--
data Result = Continue User Board | Win User Board | Draw Board

instance Show Result where
    show (Continue user board) = show board ++ "Select a square, " ++ show user ++ ": "
    show (Win user board)      = show board ++ show user ++ " Wins!\n"
    show (Draw board)          = show board ++ "It's a Draw!\n"

--
-- Initial Board
--
startingBoard :: Board
startingBoard = Board [[Empty 1,Empty 2,Empty 3],
                       [Empty 4,Empty 5,Empty 6],
                       [Empty 7,Empty 8,Empty 9]]

matchSquare :: User -&gt; Int -&gt; Square -&gt; Square
matchSquare user position (Empty x) | x == position = Move user
matchSquare _ _ square                              = square

-- This evaluates the board and determines the result of the current user's action
outcome :: User -&gt; Board -&gt; Result
outcome user board =
      case board of
           (Board [[a, _, _],
                   [_, b, _],
                   [_, _, c]]) | eq a b c -&gt; Win user board

           (Board [[_, _, a],
                   [_, b, _],
                   [c, _, _]]) | eq a b c -&gt; Win user board

           (Board [[a, b, c],
                   [_, _, _],
                   [_, _, _]]) | eq a b c -&gt; Win user board

           (Board [[_, _, _],
                   [a, b, c],
                   [_, _, _]]) | eq a b c -&gt; Win user board

           (Board [[_, _, _],
                   [_, _, _],
                   [a, b, c]]) | eq a b c -&gt; Win user board

           (Board [[a, _, _],
                   [b, _, _],
                   [c, _, _]]) | eq a b c -&gt; Win user board

           (Board [[_, a, _],
                   [_, b, _],
                   [_, c, _]]) | eq a b c -&gt; Win user board

           (Board [[_, _, a],
                   [_, _, b],
                   [_, _, c]]) | eq a b c -&gt; Win user board

           _ | full board -&gt; Draw board
             | otherwise  -&gt; Continue (otherUser user) board
    where
        eq a b c = a == b &amp;&amp; b == c

move :: User -&gt; Int -&gt; Board -&gt; Result
move user pos board = result user pos board (place user pos board)
    where
        place user pos (Board lines) = Board $ map (placeInLine user pos) lines

        placeInLine user pos         = map $ matchSquare user pos

        result user pos orig board
            | orig == board          = Continue user orig
            | otherwise              = outcome user board

main :: IO ()
main = loop (Continue X startingBoard)
    where
        loop result = do
            putStr $ show result
            hFlush stdout
            case result of
                 Win user board      -&gt; exitSuccess
                 Draw board          -&gt; exitSuccess
                 Continue user board -&gt; getInput user board
        getInput user board = do
             pos &lt;- readLn::IO Int
             loop (move user pos board)
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/116/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/116/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/116/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=116&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/04/07/tic-tac-toe-haskell/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: LOLCode</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/03/31/tic-tac-toe-lolcode/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/03/31/tic-tac-toe-lolcode/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 15:22:18 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=108</guid>
		<description><![CDATA[The clink&#8230; clink&#8230; clink sound you&#8217;ve been hearing was my IQ points sliding off onto the floor one by one as I wrote this. This program was written against a slightly tweaked version of the the Perl-based YALI interpreter.  You can check out the original, but to run this one you will need my version, which [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=108&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The <em>clink&#8230; clink&#8230; clink</em> sound you&#8217;ve been hearing was my IQ points sliding off onto the floor one by one as I wrote this.</p>
<p>This program was written against a slightly tweaked version of the the Perl-based YALI interpreter.  You can check out the <a title="original" href="http://1.618034.com/yali-yet-another-lolcode-interpreter/index.php">original</a>, but to run this one you will need my version, which is checked in with <a href="http://github.com/kemiller/tic-tac-toe/tree/master/lolcode/">the rest of the code</a>.  I also stole the array join implementation from his examples.</p>
<pre>HAI

  OBTW
    join
    Basic array join.
  TLDR
  HOW DUZ I join YR a AN YR b
    I HAS A count ITZ ALL a
    LOL count R count NERF 1

    IZ count SMALR DEN 0 ? FOUND YR ""

    I HAS A output ITZ ""
    IM IN YR LOOP
      LOL output R count IN MAH a N output

      IZ count BIGR DEN 0 ? LOL output R b N output
      IZ count LIEK 0 ? GTFO

      LOL count R count NERF 1
    KTHX

    FOUND YR output
  IF U SAY SO

  OBTW
    cell formatting
  TLDR
  HOW DUZ I formatz YR cell
    IZ cell SORTA "\d" ? FOUND YR "(" N cell N ")"
    FOUND YR " " N cell N " "
  IF U SAY SO

  HOW DUZ I printz YR bord
    I HAS A cell
    I HAS A colsep ITZ "|"
    I HAS A rowsep ITZ "\n---+---+---\n"
    I HAS A outputz ITZ ""

    LOL cell R formatz YR 0 IN MAH bord MKAY
    LOL outputz R "\n" N cell N colsep

    LOL cell R formatz YR 1 IN MAH bord MKAY
    LOL outputz R outputz N  cell N colsep

    LOL cell R formatz YR 2 IN MAH bord MKAY
    LOL outputz R outputz N  cell N rowsep

    LOL cell R formatz YR 3 IN MAH bord MKAY
    LOL outputz R outputz N  cell N colsep

    LOL cell R formatz YR 4 IN MAH bord MKAY
    LOL outputz R outputz N  cell N colsep

    LOL cell R formatz YR 5 IN MAH bord MKAY
    LOL outputz R outputz N  cell N rowsep

    LOL cell R formatz YR 6 IN MAH bord MKAY
    LOL outputz R outputz N  cell N colsep

    LOL cell R formatz YR 7 IN MAH bord MKAY
    LOL outputz R outputz N  cell N colsep

    LOL cell R formatz YR 8 IN MAH bord MKAY
    LOL outputz R outputz N cell N "\n"

    FOUND YR outputz
  IF U SAY SO

  HOW DUZ I makezYrMove YR playr AN YR space AN YR bord
    BTW This version of LOLCode has no TROOF values, so I use NUMBRs

    IZ space SMALR DEN 1 ? FOUND YR 0
    IZ space BIGR DEN 9 ? FOUND YR 0

    I HAS A indeks ITZ space NERF 1

    IZ indeks IN MAH bord SORTA "\d" O RLY?
      YA RLY
        LOL indeks IN MAH bord R playr
        FOUND YR 1
      NO WAI
        FOUND YR 0
    KTHX
  IF U SAY SO

  HOW DUZ I canHasWinnarIn YR bord AN YR playr
    I HAS A bordMaidUvYarn ITZ join YR bord AN YR "" MKAY

    BTW rows
    IZ bordMaidUvYarn SORTA "(" N playr N ")(" N playr N ")(" N playr N ")......" ? FOUND YR 1
    IZ bordMaidUvYarn SORTA "...(" N playr N ")(" N playr N ")(" N playr N ")..." ? FOUND YR 1
    IZ bordMaidUvYarn SORTA "......(" N playr N ")(" N playr N ")(" N playr N ")" ? FOUND YR 1

    BTW columns
    IZ bordMaidUvYarn SORTA "(" N playr N ")..(" N playr N ")..(" N playr N ").." ? FOUND YR 1
    IZ bordMaidUvYarn SORTA ".(" N playr N ")..(" N playr N ")..(" N playr N ")." ? FOUND YR 1
    IZ bordMaidUvYarn SORTA "..(" N playr N ")..(" N playr N ")..(" N playr N ")" ? FOUND YR 1

    BTW diagonals
    IZ bordMaidUvYarn SORTA "(" N playr N ")...(" N playr N ")...(" N playr N ")" ? FOUND YR 1
    IZ bordMaidUvYarn SORTA "..(" N playr N ").(" N playr N ").(" N playr N ").." ? FOUND YR 1

    FOUND YR 0
  IF U SAY SO

  HOW DUZ I canHasTieIn YR fantsyBord
    IZ fantsyBord SORTA "\d" ? FOUND YR 0
    FOUND YR 1
  IF U SAY SO

  I HAS A bord
  I HAS A bord_lemf ITZ 9
  I HAS A current_lemf
  IM IN YR loop
    LOL current_lemf R ALL bord
    IZ current_lemf LIEK bord_lemf ? GTFO

    LOL current_lemf IN MAH bord R current_lemf UP 1
  KTHX

  I HAS A playr ITZ "X"
  I HAS A moovWerked ITZ 0

  IM IN YR gaimLoop
    I HAS A fantsyBord ITZ printz YR bord MKAY
    VISIBLE fantsyBord

    I HAS A winnar ITZ canHasWinnarIn YR bord AN YR playr MKAY
    IZ winnar LIEK 1 O RLY?
      YA RLY
        VISIBLE playr N " IS TEH WINNAR!1!!!"
        BTW Use this line instead if you want to run tests
        BTW VISIBLE playr N " Wins!"
        GTFO
    KTHX

    I HAS A tie ITZ canHasTieIn YR fantsyBord MKAY
    IZ tie LIEK 1 O RLY?
      YA RLY
        VISIBLE "NO MOAR WINNARZ!!!?/1!"
        BTW Use this line instead if you want to run tests
        BTW VISIBLE "It's a Draw!"
        GTFO
    KTHX

    IZ moovWerked LIEK 1 O RLY?
      YA RLY
        IZ playr LIEK "X" O RLY?
          YA RLY
            LOL playr R "O"
          NO WAI
            LOL playr R "X"
        KTHX
    KTHX

    I HAS A moov

    VISIBLE "Makez yr moov, " N playr N ": "!
    BTW Use this line instead if you want to run tests
    BTW VISIBLE "Select a square, " N playr N ": "!

    GIMMEH NUMBR moov

    LOL moovWerked R makezYrMove YR playr AN YR moov AN YR bord MKAY
  KTHX

KTHXBYE

BTW vim: ts=2 sw=2 et</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/108/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/108/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/108/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=108&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/03/31/tic-tac-toe-lolcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: Python</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/03/24/tic-tac-toe-python/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/03/24/tic-tac-toe-python/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 00:47:44 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=103</guid>
		<description><![CDATA[Lock up the women and children &#8212; a rubyist is writing python. I&#8217;m curious what the herpetophiles in the audience will think of the code, because I know the Python community spends a reasonable amount of brainpower debating &#8220;pythonicness.&#8221; Broadly speaking, there were more places I found commonality between Ruby and Python than differences. This [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=103&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Lock up the women and children &#8212; a rubyist is writing python.  I&#8217;m curious what the herpetophiles in the audience will think of the code, because I know the Python community spends a reasonable amount of brainpower debating &#8220;pythonicness.&#8221;</p>
<p>Broadly speaking, there were more places I found commonality between Ruby and Python than differences.  This may have been more harmful than helpful in the short run, because it meant I kept reaching for familiar tools a finding they had been moved, or replaced.  For example, you can see in several places that I do this:  <code>if type(cell) == type(1)</code>, meaning if cell is a number.  Is this a common Python idiom?  It seems unlikely.</p>
<p>Differences I liked:</p>
<ul>
<li>Syntactically-significant indentation.  Makes short functions look great and longer ones look weird, thus encouraging short functions.  :)</li>
<li>List comprehensions.  Especially with multiple lists.</li>
<li>Real named arguments.</li>
<li>Excellent documentation.</li>
<li>TIOOWTDI</li>
</ul>
<p>Differences I didn&#8217;t like:</p>
<ul>
<li>Distinction between builtins and methods.  I kept looking for <code>any</code> and <code>map</code> in all the wrong places.</li>
<li>No implicit expression value / required explicit <code>return</code>.</li>
<li>More difficult reflection/metaprogramming.</li>
<li>TIOOWTDI</li>
</ul>
<p>With just a little practice, I&#8217;m sure I could be quite happy and productive in it.</p>
<p>What do you think, Python people?  What should I have done differently?</p>
<pre>#!/usr/bin/env python2.6

from __future__ import print_function
import sys

X = 'X'
O = 'O'

starting_player = X
starting_board = [ [1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9] ]

# Input/Output

def format(cell):
    if type(cell) == type(1):
        return "(" + repr(cell) + ")"
    else:
        return " " + cell + " "

def print_board(board):
    print("\n" + "\n---+---+---\n".join(["|".join([format(c) for c in row]) for row in board]) + "\n")

def print_prompt(player):
    print("Select a square, " + player + ": ", end='')

def print_winner(player):
    print(player + " Wins!")

def print_draw():
    print("It's a Draw!")

def read_answer():
    str = sys.stdin.readline()
    return int(str)

# Winner Detection

def rows(board):
    return board[:] # clone

def cols(board):
    return [[row[i] for row in board] for i in [0,1,2]]

def diagonals(board):
    return [[row[i] for row, i in zip(board,[0,1,2])],
            [row[i] for row, i in zip(board,[2,1,0])]]

def lines(board):
    return rows(board) + cols(board) + diagonals(board)

def complete_line(line):
    return line[0] == line[1] and line[1] == line[2]

def winner(board):
    return any([complete_line(line) for line in lines(board)])

def full(board):
    return not any([type(row[i]) == type(1) for row in board for i in [0,1,2]])

# Game Play

def other_player(player):
    if player == X:
        return O
    else:
        return X

def legal_move(space, board):
    return any([row[i] == space for row in board for i in [0, 1, 2]])

def make_move(player, space, board):
    new_board = [row[:] for row in board]
    new_board[(space-1)/3][(space-1)%3] = player
    return new_board

# Main loop

def loop(player, board):
    print_board(board)
    if winner(board):
        print_winner(other_player(player))
        return
    elif full(board):
        print_draw()
        return
    else:
        print_prompt(player)
        space = read_answer()
        if legal_move(space, board):
            loop(other_player(player), make_move(player, space, board))
        else:
            loop(player, board)

loop(starting_player, starting_board)
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/103/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/103/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/103/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=103&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/03/24/tic-tac-toe-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: Java</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/03/17/tic-tac-toe-java/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/03/17/tic-tac-toe-java/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 15:10:45 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=99</guid>
		<description><![CDATA[*Yawn* (Though I will say that generics and for-each are a big improvement. This is my first time seriously using Java since 1.4.2.) Happy St. Patrick&#8217;s Day! import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Queue; import java.util.Set; class TicTacToe { Queue [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=99&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>*Yawn*</p>
<p>(Though I will say that generics and for-each are a big improvement.  This is my first time seriously using Java since 1.4.2.) </p>
<p>Happy St. Patrick&#8217;s Day!</p>
<pre>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Queue;
import java.util.Set;

class TicTacToe {

	Queue players;
	Board board;
	BufferedReader in;

	public static void main(String argv[]) {
		new TicTacToe().play();
	}

	public TicTacToe() {
		// Player List
		players = new LinkedList();
		players.add(Player.X);
		players.add(Player.O);

		board = new Board();

		in = new BufferedReader(new InputStreamReader(System.in));
	}

	public void play() {
		Player player = nextPlayer();
		while (true) {
			System.out.println("");
			System.out.println(board);
			if (board.winner() != null) {
				System.out.println(String.format("\n%s Wins!", board.winner()));
				break;
			} else if (board.full()) {
				System.out.println("\nIt's a Draw!");
				break;
			} else {
				System.out.print(String.format("\nSelect a square, %s: ", player));
				int move = 0;

				try {
					String answer = in.readLine();
					move = Integer.parseInt(answer);
				} catch (IOException e) {
					e.printStackTrace();
					System.exit(1);
				} catch (NumberFormatException e) {
					continue;
				}

				if (board.place(player, move)) {
					player = nextPlayer();
				}
			}
		}
	}

	public Player nextPlayer() {
		Player nextPlayer = players.remove();
		players.add(nextPlayer);
		return nextPlayer;
	}

	class Cell {
		Player player = null;
		int address;
		List&lt;List&gt; neighborLists;

		public Cell(int address) {
			super();
			this.address = address;
			this.neighborLists = new LinkedList&lt;List&gt;();
		}

		public boolean assignPlayer(Player player, int targetAddress) {
			if (address == targetAddress) {
				this.player = player;
				return true;
			} else {
				return false;
			}
		}

		public void addNeighborList(List list) {
			neighborLists.add(list);
		}

		public void addNeighbors(Cell first, Cell second) {
			addNeighborList(Arrays.asList(first, second));
		}

		public boolean isWinner() {
			for (List list : neighborLists) {
				boolean result = true;
				for (Cell cell : list) {
					result = result &amp;&amp; this.equals(cell);
				}
				if (result) return true;
			}
			return false;
		}

		@Override
		public String toString() {
			if (player == null) {
				return String.format("(%d)", address);
			} else {
				return String.format(" %s ", player);
			}
		}

		@Override
		public boolean equals(Object obj) {
			if (obj.getClass() == Cell.class) {
				return this.player == ((Cell) obj).player;
			} else {
				return false;
			}
		}

	}

	enum Player {
		X("X"),
		O("O");

		String name;

		Player(String name) {
			this.name = name;
		}

		public String toString() {
			return name;
		}
	}

	class Board {
		DelimitedList&lt;DelimitedList&gt; cells;
		Set freeCells;
		Player winner;

		private final static String COLSEP = "|";
		private final static String ROWSEP = "\n---+---+---\n";
		private static final int SIZE = 3;

		public Board() {

			// Lay out cells in the board
			freeCells = new HashSet();
			cells = new DelimitedList&lt;DelimitedList&gt;(ROWSEP);
			for (int i = 0; i &lt; SIZE; i++) {
				DelimitedList row = new DelimitedList(COLSEP);
				cells.add(row);
				for (int j = 0; j &lt; SIZE; j++) {
					Cell cell = new Cell(i*SIZE + j + 1);
					row.add(cell);
					freeCells.add(cell);
				}
			}

			defineRow(1, 2, 3);
			defineRow(4, 5, 6);
			defineRow(7, 8, 9);

			defineRow(1, 4, 7);
			defineRow(2, 5, 8);
			defineRow(3, 6, 9);

			defineRow(1, 5, 9);
			defineRow(3, 5, 7);
		}

		public String toString() {
			StringBuffer sb = new StringBuffer();
			display(sb);
			return sb.toString();
		}

		public void display(StringBuffer sb) {
			cells.setStringBuffer(sb);
			for (DelimitedList row : cells) {
				display(row, sb);
			}
		}

		public void display(DelimitedList row, StringBuffer sb) {
			row.setStringBuffer(sb);
			for (Cell cell : row) {
				sb.append(cell);
			}
		}

		public boolean full() {
			return freeCells.isEmpty();
		}

		public Player winner() {
			return this.winner;
		}

		public boolean complete() {
			return winner() != null || full();
		}

		public boolean place(Player player, int space) {
			Iterator iterator = freeCells.iterator();
			while (iterator.hasNext()) {
				Cell cell = iterator.next();
				if (cell.assignPlayer(player, space)) {
					iterator.remove();
					if (cell.isWinner()) this.winner = player;
					return true;
				}
			}
			return false;
		}

		private Cell cellAt(int oneBasedIndex) {
			int i = oneBasedIndex  - 1;
			return cells.get(i / SIZE).get(i % SIZE);
		}

		private void defineRow(int first, int second, int third) {
			cellAt(first).addNeighbors(cellAt(second), cellAt(third));
			cellAt(second).addNeighbors(cellAt(third), cellAt(first));
			cellAt(third).addNeighbors(cellAt(first), cellAt(second));
		}

	}

	private static class DelimitingIterator implements Iterator {

		public DelimitingIterator(ListIterator iterator,
				StringBuffer stringBuffer, String delimiter) {
			super();
			this.iterator = iterator;
			this.stringBuffer = stringBuffer;
			this.delimiter = delimiter;
		}

		ListIterator iterator;
		StringBuffer stringBuffer;
		String delimiter;

		@Override
		public boolean hasNext() {
			return iterator.hasNext();
		}

		@Override
		public E next() {
			E nextItem =  iterator.next();
			if (iterator.previousIndex() != 0 &amp;&amp; stringBuffer != null) {
				stringBuffer.append(delimiter);
			}
			return nextItem;
		}

		@Override
		public void remove() {
			iterator.remove();
		}

	}

	private static class DelimitedList extends ArrayList {

		/**
		 *
		 */
		private static final long serialVersionUID = 1L;

		public DelimitedList(String delimiter) {
			super();
			this.delimiter = delimiter;
		}

		StringBuffer stringBuffer;
		String delimiter;

		public void setStringBuffer(StringBuffer stringBuffer) {
			this.stringBuffer = stringBuffer;
		}

		@Override
		public Iterator iterator() {
			return new DelimitingIterator(listIterator(), stringBuffer, delimiter);
		}
	}
}
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/99/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=99&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/03/17/tic-tac-toe-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: Cobra</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/03/10/tic-tac-toe-cobra/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/03/10/tic-tac-toe-cobra/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 15:45:22 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=93</guid>
		<description><![CDATA[Cobra is a work-in-progress language that primarily targets the CLR. As far as I could tell, it doesn&#8217;t do much pioneering of new ideas, but it does attempt to bring together a bunch of basically good ideas in one place. These include: Mixed static and dynamic typing First class unit tests First class contracts Semantic [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=93&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Cobra is a work-in-progress language that primarily targets the CLR.  As far as I could tell, it doesn&#8217;t do much pioneering of new ideas, but it does attempt to bring together a bunch of basically good ideas in one place.  These include:</p>
<ul>
<li>Mixed static and dynamic typing</li>
<li>First class unit tests</li>
<li>First class contracts</li>
<li>Semantic Indenting</li>
<li>Clean, expressive syntax</li>
<li>Full-featured OOP (with interfaces, mixins, generics)</li>
<li>Accurate decimal arithmetic</li>
<li>High performance</li>
</ul>
<p>How well does it do all this?  Reasonably well, I have to say.  The biggest missing features are closures, an an interactive runtime, but according to <a href="http://cobra-language.com/docs/papers-etc/Cobra-SoCal-Code-Camp-2009-01-Slides.pdf">this presentation</a> they&#8217;re on the way.  I was excited about the mix of static and dynamic typing.  I&#8217;ve wanted for a while to be able to hack something up without types and then go back through and tighten things up later.  Cobra doesn&#8217;t seem like it&#8217;s 100% there.  You can certainly omit type declarations, but it wasn&#8217;t always the case that a semantically valid program would run correctly without its type declarations.  For example, there was one place where I left a member variable untyped, and then assigned a list to it in the initializer.  It crashed like that.  Adding the type declaration fixed it without any other changes.</p>
<p>The documentation is still quite spotty, as you might expect from an unfinished project.  Most (all?) of the standard data types seem to be based directly on the .NET standard library, so you can go look some things up on MSDN.</p>
<p>Built-in unit tests are very cool.  I could see them being overused and cluttering things up (it would be nice to have the option to pull them back out into another file when you&#8217;re done) but having real support from the runtime means that the compiler can tell you things about your test that other languages can&#8217;t.  For example, <code>assert 2 == 1</code> will give you an error message like:</p>
<pre>
(MonoType)
info       = nil
this       = Cell (MonoType)
(2 == 1) = false
</pre>
<p>No need for awkward constructions like <code>assert_equal</code> or <code>2.should == 1</code></p>
<p>There is a JVM port underway, and also what looks like the beginnings of a port to the Objective-C runtime.  Looks like one to watch.</p>
<p>Here&#8217;s the code (for version 0.8.0 and mono):</p>
<pre>

class TicTacToe
	"""
	Tic Tac Toe in Cobra
	"""
	def main is shared
		players = Ring("X", "O")
		board = Board(3)

		player = players.next
		cellsRemaining = 9

		while true
			print board

			Console.write('Select a square, [player]: ')
			Console.out.flush
			try
				answer = Console.readLine
				Console.out.flush
			catch System.ArgumentNullException
				break

			cell = board.getCell(answer)
			if not cell
				continue

			cellsRemaining -= 1

			cell.value = player
			if cell.matchAny(3)
				print board
				print "[player] Wins!"
				break

			if cellsRemaining &lt;= 0
				print board
				print &quot;It&#39;s a Draw!&quot;
				break

			player = players.next

class Ring
	"""
	A Ring class that takes its inputs and will return one
	after the other ad infinitum.
	"""
	var _enumerator as IEnumerator

	test
		ring = Ring(1, 2, 3)
		assert ring.next == 1
		assert ring.next == 2
		assert ring.next == 3
		assert ring.next == 1

	cue init(items as vari T)
		base.init
		_enumerator = List(items).getEnumerator

	def next as T
		if _enumerator.moveNext
			return _enumerator.current
		else
			_enumerator.reset
			return .next

class Cell
	"""
	A mesh-aware cell on the tic-tac-toe board.  It keeps track
	of its neighbors and can detect winners that way.
	"""
	pro address from var as String
	pro value from var as String?

	enum Dir
		East
		Southeast
		South
		Southwest
		West
		Northwest
		North
		Northeast

	# Neighbors
	var _neighbors = Dictionary() 

	cue init(address as String)
		base.init
		.address = address
		for i in 8
			_neighbors[i to Dir] = nil

	cue init(address as String, value as String)
		.init(address)
		.value = value

	def opposite(dir as Dir) as Dir
		test
			cell = Cell('2')
			assert cell.opposite(Dir.East) == Dir.West
			assert cell.opposite(Dir.West) == Dir.East
			assert cell.opposite(Dir.Northeast) == Dir.Southwest
		body
			val = dir to int
			val = (val + 4) % 8
			return val to Dir

	def add(dir as Dir, cell as Cell?)
		if not _neighbors[dir]
			_neighbors[dir] = cell
			if cell, cell.add(.opposite(dir), this)

	def addOtherSide(cell as Cell)
		.add(Dir.East, cell)
		cell.add(Dir.Northwest, _neighbors[Dir.North])
		cell.addBelow(_neighbors[Dir.Northeast])

	def addAbove(cell as Cell)
		.add(Dir.South, cell)
		cell.add(Dir.Northeast, _neighbors[Dir.East])

	def addBelow(cell as Cell?) as Cell
		if cell, cell.addAbove(this)
		return this

	def addBeside(cell as Cell?) as Cell
		if cell, cell.addOtherSide(this)
		return this

	def match(direction as Dir, cell as Cell) as int
		if .value  cell.value
			return 0
		else if _neighbors[direction]
			return 1 + _neighbors[direction].match(direction, this)
		else
			return 1

	def match(dir as Dir, target as int) as bool
		test
			cell1 = Cell('1', "X")
			cell2 = Cell('2', "X").addBeside(cell1)
			cell3 = Cell('3', "X").addBeside(cell2)
			cell4 = Cell('4', "X").addBelow(cell1)
			cell5 = Cell('5', "X").addBeside(cell4)
			cell6 = Cell('6', "X").addBeside(cell5)
			cell7 = Cell('7', "X").addBelow(cell4)
			cell8 = Cell('8', "X").addBeside(cell7)
			cell9 = Cell('9', "X").addBeside(cell8)

			assert cell1.match(Dir.Southeast, 3)
			assert cell7.match(Dir.Southwest, 3)
			assert cell7.match(Dir.Northeast, 3)
			assert cell3.match(Dir.North, 3)
			assert not cell6.match(Dir.Northeast, 3)
			assert cell9.match(Dir.West, 3)

		body
			opp = .opposite(dir)
			num = 1
			if _neighbors[dir], num += _neighbors[dir].match(dir, this)
			if _neighbors[opp], num += _neighbors[opp].match(opp, this)
			return target == num

	def matchAny(target as int) as bool
		return  .match(Dir.East, target) or _
				.match(Dir.North, target) or _
				.match(Dir.Northeast, target) or _
				.match(Dir.Northwest, target)

	def toString as String is override
		if .value
			return ' [.value] '
		else
			return '([.address])'

	def rowToString(sb as StringBuilder, sep as String)
		sb.append(this)
		if _neighbors[Dir.East]
			sb.append(sep)
			_neighbors[Dir.East].rowToString(sb, sep)

	def allToString(sb as StringBuilder, colsep as String, rowsep as String)
		.rowToString(sb, colsep)
		if _neighbors[Dir.South]
			sb.append(Environment.newLine)
			sb.append(rowsep)
			sb.append(Environment.newLine)
			_neighbors[Dir.South].allToString(sb, colsep, rowsep)

class Board

	pro dim from var as int
	pro head from var as Cell?
	var _cells as IList
	var _rowsep as String

	cue init(dim as int)
		ensure
			dim &gt;= 3
		body
			base.init
			_dim = dim
			_cells = List()
			_constructBoard
			_rowsep = "---"
			for i in 1 : dim
				_rowsep += "+---"

	def _constructBoard
		head = nil
		tail = nil
		for i in .dim
			for j in .dim
				cell = Cell((i*.dim + j + 1).toString)
				_cells.add(cell)
				if j == 0
					head = tail = cell.addBelow(head)
				else
					tail = cell.addBeside(tail)
		.head = _cells[0]

	def getCell(address as String?) as Cell?
		if not address, return nil
		for cell in _cells
			if cell.address == address
				_cells.remove(cell)
				return cell
		return nil

	def toString as String is override
		sb = StringBuilder()
		sb.append(Environment.newLine)
		.head.allToString(sb, "|",_rowsep)
		sb.append(Environment.newLine)
		return sb.toString
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/93/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/93/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/93/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=93&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/03/10/tic-tac-toe-cobra/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
		<item>
		<title>Tic-Tac-Toe: LOGO</title>
		<link>http://torquingwetstrainers.wordpress.com/2010/03/03/tic-tac-toe-logo/</link>
		<comments>http://torquingwetstrainers.wordpress.com/2010/03/03/tic-tac-toe-logo/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 15:45:57 +0000</pubDate>
		<dc:creator>seriousken</dc:creator>
				<category><![CDATA[Tic Tac Toe]]></category>

		<guid isPermaLink="false">http://torquingwetstrainers.wordpress.com/?p=91</guid>
		<description><![CDATA[I couldn&#8217;t write it in LOGO and not use turtle graphics to draw the board. This runs in UCBLogo 6.0. #!/usr/bin/env logo make "cells {1 2 3 4 5 6 7 8 9} make "cellPositions { [-121 121] [ 0 121] [ 121 121] [-121 0] [ 0 0] [ 121 0] [-121 -121] [ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=91&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I couldn&#8217;t write it in LOGO and not use turtle graphics to draw the board.  This runs in UCBLogo 6.0.</p>
<pre>
#!/usr/bin/env logo

make "cells {1 2 3 4 5 6 7 8 9}
make "cellPositions {
	[-121  121]
	[   0  121]
	[ 121  121]
	[-121    0]
	[   0    0]
	[ 121    0]
	[-121 -121]
	[   0 -121]
	[ 121 -121]
}

TO drawLine <img src='http://s2.wp.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' />  :y :nx :ny
	penup
	setxy x y
	pendown
	setxy nx ny
	penup
END

TO drawX <img src='http://s2.wp.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' />  :y
	drawLine (x - 50) (y + 50) (x + 50) (y - 50)
	drawLine (x + 50) (y + 50) (x - 50) (y - 50)
END

TO drawO <img src='http://s2.wp.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' />  :y
	penup
	setxy x y
	pendown
	arc 360 50
	penup
END

TO drawGrid
	drawLine 61 171 61 -171
	drawLine -61 171 -61 -171
	drawLine 171 61 -171 61
	drawLine 171 -61 -171 -61
END

TO markPos :player :numpos
	localmake "coords (item :numpos cellPositions)
	setitem numpos cells player
	ifelse (player = "X) [
		drawX (item 1 coords) (item 2 coords)
	] [
		drawO (item 1 coords) (item 2 coords)
	]
end

TO swapPlayer
	ifelse (currentPlayer = "X) [
		make "currentPlayer "O
	] [
		make "currentPlayer "X
	]
END

TO checkRow <img src='http://s2.wp.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' />  :y :z
	output (and ((item x cells) = currentPlayer)
				((item y cells) = currentPlayer)
				((item z cells) = currentPlayer))
END

TO checkWinner
	if (or (checkRow 1 2 3)
		   (checkRow 4 5 6)
		   (checkRow 7 8 9)
		   (checkRow 1 4 7)
		   (checkRow 2 5 <img src='http://s0.wp.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' />
		   (checkRow 3 6 9)
		   (checkRow 1 5 9)
		   (checkRow 3 5 7)) [
		print `[,currentPlayer Wins!]
		bye
	]
END

TO checkDraw
	FOR [i 1 9 1] [
		IF (number? (item i cells)) [
			STOP
		]
	]
	print [It's a Draw!]
	bye
END

TO promptMove
	type `[Select a square, ,currentPlayer]
	type `[,": ," ]
	localmake "numpos readword
	if (number? numpos) [
		if (and (numpos &gt; 0) (numpos &lt; 10) (number? (item numpos cells))) [
			markPos currentPlayer numpos
			checkWinner
			checkDraw
			swapPlayer
		]
	]
END

penup
hideturtle

drawGrid 

make &quot;currentPlayer &quot;X

forever [ promptMove ]
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/torquingwetstrainers.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/torquingwetstrainers.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/torquingwetstrainers.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/torquingwetstrainers.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/torquingwetstrainers.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/torquingwetstrainers.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/torquingwetstrainers.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/torquingwetstrainers.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/torquingwetstrainers.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/torquingwetstrainers.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/torquingwetstrainers.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/torquingwetstrainers.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/torquingwetstrainers.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/torquingwetstrainers.wordpress.com/91/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=torquingwetstrainers.wordpress.com&amp;blog=10794320&amp;post=91&amp;subd=torquingwetstrainers&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://torquingwetstrainers.wordpress.com/2010/03/03/tic-tac-toe-logo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/baa2742c865e9fe9fe51ecc095c539fb?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">seriousken</media:title>
		</media:content>
	</item>
	</channel>
</rss>
