28
Apr
10

Tic-Tac-Toe: Scala

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’t look out of place.

The downside of syntactical harmony with Java is that it’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.

That said, it’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’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.

This compiles in Scala 2.7.7.


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) => {
            val space = readAnswer
            if (board.spaceAvailable(space)) {
              board.place(space, player)
              result = board.checkResult(player)
            }
        }
        case _ => return
      }

    }
  }

  def readAnswer: Int = {
    try {
      input.readLine().toInt
    } catch {
      case nfe: NumberFormatException => 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 _ => ()
      }
    }
    return false
  }

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

  def checkResult(player: Player): Result = {
    for (row  {
          return Win(p)
        }
        case _ => ()
      }
    }
    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)
  }
}
Advertisement

4 Responses to “Tic-Tac-Toe: Scala”


  1. 1 Rick Reuben
    April 29, 2010 at 4:56 pm

    This doesn’t compile correctly

  2. 3 Rick Reuben
    April 29, 2010 at 10:42 pm

    Couldn’t find it,, U have a link


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.