Voting

Category

real language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language Scala

(Animated version)

Date:10/02/09
Author:D Mackenzie
URL:n/a
Comments:0
Info:http://www.scala-lang.org
Score: (2.60 in 5 votes)
import java.awt.{Font, Color, Dimension, Graphics, List => _}
import javax.swing.{JPanel, JFrame, SwingUtilities}
import java.util.{Timer, TimerTask}

object NinetynineBottles {
  abstract class DrawnThing {def draw(gc: Graphics)}

  class Bottle(var x: Int, var y: Int) extends DrawnThing {
    private val r = new java.util.Random()

    def draw(gc: Graphics) {
      gc.setColor(new Color(80,40,20))
      gc.fillRoundRect(x - 12,y - 30,24,60,15,15); gc.fillRoundRect(x - 5,y - 50,10,40,5,5)
      gc.setColor(new Color(0,0,255)); gc.fillRect(x - 6,y - 20,16,28)
    }

    def move(doff: Int) {x = 1160 + (r.nextInt(400) - 200); y = 470 + doff / 2}

    def move(p: (Int, Int)) {x = p._1; y = p._2}
  }

  object Wall extends DrawnThing {
    def draw(gc: Graphics) {
      gc.setColor(new Color(230,120,90)); gc.fillRect(0,300,900,300)
      gc.setColor(new Color(160,160,160)); gc.setClip(0,300,900,300)
      for (h <- -20 to 900 by 36; v <- 300 to 600 by 19; o = v % 2 * 18)
        gc.drawRect(h + o,v,32,16)
      gc.setClip(0,0,1400,600)
    }
  }

  object Lyrics extends DrawnThing {
    val f1 = new Font("Serif", Font.PLAIN, 20)

    def lyric = {
      def qty(n:Int) =
        (n match {case 0 => "no more bottles"
                  case 1 => "1 bottle"
                  case n => n + " bottles"}) + " of beer"

      qty(bc).capitalize + " on the wall, " + qty(bc) + "." +
            (if (bc > 0)
              "\nTake one down and pass it around, \n" + qty(bc - 1) + " on the wall.\n"
             else
              "\nGo to the store and buy some more, \n" + qty(99) + " on the wall.")
    }

    def draw(gc: Graphics) {
      gc.setColor(new Color(100 + bc,200,100 + bc)); gc.fillOval(850,30,550,200)
      gc.fillPolygon(Array(900,940,1020),Array(320,150,180),3)
      gc.setColor(new Color(255,0,0)); gc.setFont(f1)
      List.fromString(lyric, '\n').foldLeft(0){(d,l:String) =>
        gc.drawString(l,900,120 + d); d + 20}
    }
  }

  private var bc = 99
  val timer      = new Timer()
  val bottles    = (for {bi <- 0 until bc
                         (x,y) = stacker(bi,34,0,0)} yield new Bottle(x,y)).toList
  val things     = Wall :: bottles ::: List(Lyrics)
  val top        = new JFrame {
         setPreferredSize(new Dimension(1400,600))
         setTitle("99 Bottles of Beer")
         getContentPane.add(new JPanel{
           override def paintComponent(gc: Graphics) {things.foreach(_.draw(gc))}})
       }

  def stacker(ind: Int, lrc: Int, lri: Int, rh: Int):(Int, Int) = {
    if ((ind - lri) < lrc) (25 + rh * 12 + 25 * (ind - lri),270 - rh * 78)
    else stacker(ind,lrc - 1,lri + lrc,rh + 1)
  }

  def main(args: Array[String]) {
    def moveEmpties {bottles.drop(bc).head.move(bc)}

    def swingRequest(req: => Unit) {SwingUtilities.invokeLater(new Runnable{def run{req}})}

    swingRequest{top.pack(); top.setVisible(true)}
    timer.schedule(new TimerTask{
      def run {
        if (bc > 0) {bc -= 1; moveEmpties; swingRequest{top.repaint()}}
        else {
          bottles.foldLeft(0){(d, b) => b move stacker(d,34,0,0); d+1}
          Thread.sleep(4000); swingRequest{top.repaint()}; timer.cancel()
        }}}, 2000, 1500)
  }
}

Download Source | Write Comment

Alternative Versions

VersionAuthorDateCommentsRate
Scala with a vengeanceEduardo Costa09/16/090
Fun semi-DSL readable versionCalum Leslie01/31/080
GrabbaBeer & CaseOfBeersD Mackenzie05/30/090

Comments

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: