├── .gitignore ├── README.md ├── bloxorz ├── levels │ ├── level01.txt │ ├── level02.txt │ ├── level03.txt │ ├── level04.txt │ ├── level05.txt │ ├── level06.txt │ ├── level07.txt │ ├── level08.txt │ ├── level09.txt │ ├── level10.txt │ ├── level11.txt │ ├── level12.txt │ └── level13.txt └── simple │ ├── level01.txt │ ├── level02.txt │ ├── level03.txt │ ├── level04.txt │ ├── level05.txt │ ├── level06.txt │ ├── level07.txt │ ├── level08.txt │ └── level09.txt ├── cs109ui ├── cs109ui.jar ├── cs109ui.scala ├── uitest-animation.scala ├── uitest-dialogs.scala ├── uitest1.scala ├── uitest2.scala ├── uitest3.scala ├── uitest4.scala └── uitest5.scala ├── examples ├── drawing.scala ├── image.scala └── mastermind.scala ├── projects ├── alice.txt ├── bloxorz-simple-levels.zip ├── cmudict.txt ├── gpx.zip ├── kaist.txt ├── polynomial.scala ├── replies.txt ├── scala.txt ├── scrabble.txt └── words.txt ├── swing ├── clock1.scala ├── crossword1.scala ├── crossword2.scala ├── floodit.scala ├── gui1.scala ├── gui2.scala ├── gui3.scala ├── gui3a.scala ├── gui3b.scala ├── gui3c.scala ├── gui3d.scala ├── gui4.scala ├── gui5.scala ├── gui6.scala ├── panel1.scala ├── panel2.scala ├── panel3.scala ├── panel4.scala ├── tictactoe1.scala ├── tictactoe2.scala ├── tictactoe3.scala ├── tictactoe4.scala └── words.txt └── tutorial ├── 05-basic ├── arguments.scala ├── overloading.scala ├── triangle1.scala ├── triangle2.scala └── triangle3.scala ├── 07-collatz ├── collatz1.scala ├── collatz2.scala ├── collatz3.scala ├── collatz4.scala └── collatz5.scala ├── 10-objects └── test.scala ├── 13-sets ├── sieve1.scala ├── sieve2.scala ├── spell1.scala └── words.txt ├── 16-exceptions ├── catch1.scala ├── catch2.scala ├── except1.scala ├── except2.scala ├── except3.scala ├── quiz.scala ├── read1.scala └── require1.scala ├── 18-buffers ├── makestring1.scala ├── makestring2.scala ├── readwords1.scala ├── readwords2.scala ├── readwords3.scala └── words.txt ├── 30-maps ├── anagrams.scala ├── cmudict.txt ├── cmudict1.scala ├── cmudict2.scala ├── histogram1.scala ├── histogram2.scala ├── histogram3.scala ├── histogram4.scala └── scala.txt ├── 35-lists ├── readwords4.scala ├── squarelist.scala ├── squarelist2.scala └── words.txt ├── 45-higher-order ├── higher1.scala ├── higher2.scala ├── higher3.scala ├── higher4.scala ├── integrate.scala ├── primes.scala └── table.scala ├── 50-objects ├── days1.scala ├── days2.scala ├── days3.scala ├── days4.scala ├── days5.scala ├── days6.scala └── days7.scala ├── 55-objects ├── accum1.scala ├── accum2.scala ├── blackjack-game.scala ├── blackjack1.scala ├── blackjack2.scala ├── blackjack3.scala ├── rectangle1.scala └── rectangle2.scala ├── 56-dads-puzzle ├── puzzle1.scala ├── puzzle2.scala ├── puzzle3.scala ├── puzzle4.scala └── puzzle5.scala ├── 60-compiling ├── blackjack-app.scala ├── date1.scala ├── date2.scala ├── date3.scala ├── date4.scala ├── date5.scala ├── date6.scala ├── date7.scala ├── days.scala ├── hello.scala ├── kermit.scala ├── numbers.scala └── point.scala └── 70-scalatest ├── checkpoly.scala ├── polynomial1.scala ├── polynomial2.scala ├── test1.scala ├── test2.scala └── test3.scala /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cs109ui 2 | 3 | A module CS109UI that allows students to build simple programs with a 4 | graphical user interface without learning about Swing or event-based 5 | programming. 6 | 7 | See http://otfried.org/scala/cs109ui.html for documentation. 8 | 9 | 10 | # swing 11 | 12 | Example code for my tutorial about Scala Swing 13 | at http://otfried.org/scala/gui.html. 14 | 15 | 16 | # examples 17 | 18 | General example code for my Scala documentation page 19 | at http://otfried.org/scala 20 | 21 | 22 | # tutorial 23 | 24 | Code snippets as used in my CS109 tutorials 25 | at http://otfried.org/courses/cs109/tutorial.html 26 | 27 | 28 | # projects 29 | 30 | Data files and starting code for CS109 projects. 31 | 32 | -------------------------------------------------------------------------------- /bloxorz/levels/level01.txt: -------------------------------------------------------------------------------- 1 | ooo 2 | oSoooo 3 | ooooooooo 4 | -ooooooooo 5 | -----ooToo 6 | ------ooo 7 | -------------------------------------------------------------------------------- /bloxorz/levels/level02.txt: -------------------------------------------------------------------------------- 1 | ------oooo--ooo 2 | oooo--ooBo--oTo 3 | ooAo--oooo--ooo 4 | oooo--oooo--ooo 5 | oSooaaoooobbooo 6 | oooo--oooo 7 | #AOa 8 | #BXb 9 | -------------------------------------------------------------------------------- /bloxorz/levels/level03.txt: -------------------------------------------------------------------------------- 1 | ------ooooooo 2 | oooo--ooo--oo 3 | ooooooooo--oooo 4 | oSoo-------ooTo 5 | oooo-------oooo 6 | ------------ooo 7 | -------------------------------------------------------------------------------- /bloxorz/levels/level04.txt: -------------------------------------------------------------------------------- 1 | ---....... 2 | ---....... 3 | oooo-----ooo 4 | ooo-------oo 5 | ooo-------oo 6 | oSo--oooo..... 7 | ooo--oooo..... 8 | -----oTo--..o. 9 | -----ooo--.... 10 | -------------------------------------------------------------------------------- /bloxorz/levels/level05.txt: -------------------------------------------------------------------------------- 1 | -----------oooo 2 | -ooooaaoAooooSo 3 | -oooo-------ooo 4 | -ooBo 5 | -oooo 6 | ---oooCobbooo 7 | ----------ooooD 8 | ooo-------ooooo 9 | oToooccoooooo 10 | oooo 11 | %a 12 | %b 13 | %c 14 | #AOa 15 | #BO+c 16 | #CO-c 17 | #DOc 18 | -------------------------------------------------------------------------------- /bloxorz/levels/level06.txt: -------------------------------------------------------------------------------- 1 | -----oooooo 2 | -----o--ooo 3 | -----o--ooooo 4 | Sooooo-----oooo 5 | ----ooo----ooTo 6 | ----ooo-----ooo 7 | ------o--oo 8 | ------ooooo 9 | ------ooooo 10 | -------ooo 11 | -------------------------------------------------------------------------------- /bloxorz/levels/level07.txt: -------------------------------------------------------------------------------- 1 | --------oooo 2 | --------oooo 3 | ooo-----o--oooo 4 | oSooooooo---oTo 5 | ooo----ooA--ooo 6 | ooo----ooo--ooo 7 | -ooa---o 8 | --oooooo 9 | #AXa 10 | -------------------------------------------------------------------------------- /bloxorz/levels/level08.txt: -------------------------------------------------------------------------------- 1 | ---------ooo 2 | ---------ooo 3 | ---------ooo 4 | oooooo---oooooo 5 | oSooAo---ooooTo 6 | oooooo---oooooo 7 | ---------ooo 8 | ---------ooo 9 | ---------ooo 10 | #AS 10 1 10 7 11 | -------------------------------------------------------------------------------- /bloxorz/levels/level09.txt: -------------------------------------------------------------------------------- 1 | oooo---o---oooo 2 | oSoo---o---ooAo 3 | ooooooooooooooo 4 | ------oTo 5 | ------ooo 6 | #AS 2 1 12 1 7 | 8 | -------------------------------------------------------------------------------- /bloxorz/levels/level10.txt: -------------------------------------------------------------------------------- 1 | ooo-----oooooo 2 | oToccobboSooAo 3 | ooo-----oooob 4 | ---------ooob 5 | -----------oo 6 | ------------o 7 | ------------o 8 | -----------oo 9 | ----ooooo--oo 10 | ----oC--oooBo 11 | #AS 12 | #BXb 13 | #COc 14 | 15 | -------------------------------------------------------------------------------- /bloxorz/levels/level11.txt: -------------------------------------------------------------------------------- 1 | -oooa 2 | -oToa 3 | -ooo 4 | -o---oooooo 5 | -o---oo--oo 6 | Soooooo--ooo 7 | -----oA----o 8 | -----oooo--o 9 | -----ooooooo 10 | --------ooo 11 | %a 12 | #AO-a 13 | -------------------------------------------------------------------------------- /bloxorz/levels/level12.txt: -------------------------------------------------------------------------------- 1 | ------------A 2 | -----ooo--ooo 3 | -----oBooooob 4 | ---ooooo--oo 5 | ---oToa---oo 6 | -ooooo---oooo 7 | ooSo-----oooo 8 | oooo--ooooo 9 | -----ooo 10 | -----ooo 11 | #AXa 12 | #BXb 13 | -------------------------------------------------------------------------------- /bloxorz/levels/level13.txt: -------------------------------------------------------------------------------- 1 | ooo.oooo.oooo 2 | oo--------ooo 3 | oo---------ooo 4 | ooo---ooo--oSo 5 | ooo...oTo--ooo 6 | ooo--.ooo--o 7 | --o--.....oo 8 | --ooo..o... 9 | ---oo...... 10 | ---ooo--oo 11 | -------------------------------------------------------------------------------- /bloxorz/simple/level01.txt: -------------------------------------------------------------------------------- 1 | ooo 2 | oSoooo 3 | ooooooooo 4 | -ooooooooo 5 | -----ooToo 6 | ------ooo 7 | -------------------------------------------------------------------------------- /bloxorz/simple/level02.txt: -------------------------------------------------------------------------------- 1 | ------oooo--ooo 2 | oooo--oooo--oTo 3 | oooo--oooo--ooo 4 | oooo--oooo--ooo 5 | oSooooooooooooo 6 | oooo--oooo 7 | -------------------------------------------------------------------------------- /bloxorz/simple/level03.txt: -------------------------------------------------------------------------------- 1 | ------ooooooo 2 | oooo--ooo--oo 3 | ooooooooo--oooo 4 | oSoo-------ooTo 5 | oooo-------oooo 6 | ------------ooo 7 | -------------------------------------------------------------------------------- /bloxorz/simple/level04.txt: -------------------------------------------------------------------------------- 1 | ---....... 2 | ---....... 3 | oooo-----ooo 4 | ooo-------oo 5 | ooo-------oo 6 | oSo--oooo..... 7 | ooo--oooo..... 8 | -----oTo--..o. 9 | -----ooo--.... 10 | -------------------------------------------------------------------------------- /bloxorz/simple/level05.txt: -------------------------------------------------------------------------------- 1 | -----------oooo 2 | -ooooooooooooSo 3 | -oooo-------ooo 4 | -oooo 5 | -oooo 6 | ---oooooooooo 7 | ----------ooooo 8 | ooo-------ooooo 9 | oTooooooooooo 10 | oooo 11 | -------------------------------------------------------------------------------- /bloxorz/simple/level06.txt: -------------------------------------------------------------------------------- 1 | -----oooooo 2 | -----o--ooo 3 | -----o--ooooo 4 | Sooooo-----oooo 5 | ----ooo----ooTo 6 | ----ooo-----ooo 7 | ------o--oo 8 | ------ooooo 9 | ------ooooo 10 | -------ooo 11 | -------------------------------------------------------------------------------- /bloxorz/simple/level07.txt: -------------------------------------------------------------------------------- 1 | --------oooo 2 | --------oooo 3 | ooo-----o--oooo 4 | oSooooooo---oTo 5 | ooo----ooo--ooo 6 | ooo----ooo--ooo 7 | -ooo---o 8 | --oooooo 9 | -------------------------------------------------------------------------------- /bloxorz/simple/level08.txt: -------------------------------------------------------------------------------- 1 | -oooo 2 | -oToo 3 | -ooo 4 | -o---oooooo 5 | -o---oo--oo 6 | Soooooo--ooo 7 | -----o-----o 8 | -----oooo--o 9 | -----ooooooo 10 | --------ooo 11 | -------------------------------------------------------------------------------- /bloxorz/simple/level09.txt: -------------------------------------------------------------------------------- 1 | ooo.oooo.oooo 2 | oo--------ooo 3 | oo---------ooo 4 | ooo---ooo--oSo 5 | ooo...oTo--ooo 6 | ooo--.ooo--o 7 | --o--.....oo 8 | --ooo..o... 9 | ---oo...... 10 | ---ooo--oo 11 | -------------------------------------------------------------------------------- /cs109ui/cs109ui.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otfried/cs109-scala/0097f4a7aac22e45868938d91476878bf422c8b2/cs109ui/cs109ui.jar -------------------------------------------------------------------------------- /cs109ui/cs109ui.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * How to make a jar file: 3 | * jar cvf cs109ui.jar org 4 | */ 5 | 6 | package org.otfried.cs109 7 | 8 | import scala.swing._ 9 | import scala.swing.event._ 10 | import java.awt.{Color,Graphics2D} 11 | import java.awt.image.BufferedImage 12 | 13 | // -------------------------------------------------------------------- 14 | 15 | // -------------------------------------------------------------------- 16 | 17 | private class Canvas extends Component { 18 | private var image: BufferedImage = null 19 | 20 | focusable = true 21 | preferredSize = new Dimension(480, 320) 22 | 23 | listenTo(mouse.clicks) 24 | listenTo(keys) 25 | 26 | reactions += { 27 | case MouseClicked(_, p, _, _, _) => sendEvent(UI.Mouse(p.x, p.y)) 28 | case KeyTyped(_, c, _, _) => sendEvent(UI.Key(c)) 29 | } 30 | 31 | def sendEvent(r: UI.Result) { 32 | UI.timer.stop() // key or mouse event cancels timeout 33 | UI.queue synchronized { 34 | UI.queue.add(r) 35 | UI.queue.notify() 36 | } 37 | } 38 | 39 | override def paintComponent(g : Graphics2D) { 40 | if (image == null) { 41 | val d = size 42 | g.setColor(Color.WHITE) 43 | g.fillRect(0,0, d.width, d.height) 44 | } else 45 | g.drawImage(image, null, 0, 0) 46 | } 47 | 48 | def setImage(im: BufferedImage) { 49 | if (image == null || image.getWidth != im.getWidth 50 | || image.getHeight != im.getHeight) { 51 | image = new BufferedImage(im.getWidth, im.getHeight, 52 | BufferedImage.TYPE_INT_RGB) 53 | } 54 | image.setData(im.getData()) 55 | preferredSize = new Dimension(im.getWidth, im. getHeight) 56 | repaint() 57 | } 58 | } 59 | 60 | // -------------------------------------------------------------------- 61 | 62 | private class UI(canvas: Canvas) extends MainFrame { 63 | title = "CS109 UI" 64 | resizable = false 65 | 66 | contents = new BoxPanel(Orientation.Vertical) { 67 | contents += canvas 68 | border = Swing.EmptyBorder(10, 10, 10, 10) 69 | } 70 | } 71 | 72 | // -------------------------------------------------------------------- 73 | 74 | object UI { 75 | trait Result 76 | case class Key(ch: Char) extends Result 77 | case class Mouse(x: Int, y: Int) extends Result 78 | object TimeOut extends Result 79 | 80 | val timeOutChar = '\u0000' 81 | 82 | private val timeOutOp = new javax.swing.AbstractAction() { 83 | def actionPerformed(e : java.awt.event.ActionEvent) = 84 | queue synchronized { 85 | queue.add(TimeOut) 86 | queue.notify() 87 | } 88 | } 89 | 90 | protected[cs109] val queue = 91 | new java.util.concurrent.ConcurrentLinkedQueue[Result] 92 | 93 | protected[cs109] val timer = 94 | new javax.swing.Timer(1000, timeOutOp) 95 | 96 | private val canvas = new Canvas 97 | private val ui = new UI(canvas) 98 | println("CS109 UI version 2015/03/31") 99 | 100 | def setTitle(title: String) { 101 | Swing.onEDTWait { ui.title = title } 102 | } 103 | 104 | def show(image: BufferedImage) { 105 | Swing.onEDT { 106 | canvas.setImage(image) 107 | val insets = ui.peer.getInsets() 108 | ui.size = 109 | new Dimension(image.getWidth + 20 + insets.left + insets.right, 110 | image.getHeight + 20 + insets.top + insets.bottom) 111 | ui.visible = true 112 | } 113 | } 114 | 115 | def setTimeOut(ms: Int) { 116 | timer.setRepeats(false) 117 | timer.setInitialDelay(ms) 118 | timer.restart() 119 | } 120 | 121 | def waitEvent(): Result = { 122 | queue synchronized { 123 | while (queue.isEmpty) { 124 | queue.wait() 125 | } 126 | queue.remove() 127 | } 128 | } 129 | 130 | def waitKey(): Char = { 131 | while (true) { 132 | val r = waitEvent() 133 | r match { 134 | case Key(ch) => return ch 135 | case TimeOut => return timeOutChar 136 | case Mouse(_, _) => // ignore it 137 | } 138 | } 139 | ' ' 140 | } 141 | 142 | def waitMouse(): (Int, Int) = { 143 | while (true) { 144 | val r = waitEvent() 145 | r match { 146 | case Key(_) => // ignore it 147 | case Mouse(x, y) => return (x, y) 148 | case TimeOut => return (-1, -1) 149 | } 150 | } 151 | (0, 0) 152 | } 153 | 154 | def close() { 155 | Swing.onEDTWait { 156 | ui.close() 157 | } 158 | sys.exit(0) 159 | } 160 | 161 | // ------------------------------------------------------------ 162 | // Dialogs 163 | // ------------------------------------------------------------ 164 | 165 | def showMessage(msg: String) { 166 | Swing.onEDTWait { 167 | ui.visible = true 168 | Dialog.showMessage(canvas, msg, title=ui.title) 169 | } 170 | } 171 | 172 | def askYesNo(question: String): Boolean = { 173 | var result: Boolean = false 174 | Swing.onEDTWait { 175 | ui.visible = true 176 | Dialog.showConfirmation(canvas, question, title=ui.title) match { 177 | case Dialog.Result.Yes => result = true 178 | case _ => 179 | } 180 | } 181 | result 182 | } 183 | 184 | def inputString(msg: String): String = { 185 | var result: String = "" 186 | Swing.onEDTWait { 187 | ui.visible = true 188 | val r = Dialog.showInput(canvas, msg, title=ui.title, 189 | Dialog.Message.Plain, 190 | Swing.EmptyIcon, Nil, "") 191 | r match { 192 | case Some(s) => result = s 193 | case None => 194 | } 195 | } 196 | result 197 | } 198 | 199 | // up to three buttons are okay 200 | def askButtons(question: String, buttons: List[String]): Int = { 201 | var result: Int = 0 202 | Swing.onEDTWait { 203 | ui.visible = true 204 | val r = Dialog.showOptions(canvas, message=question, title=ui.title, 205 | entries = buttons, initial = 1) 206 | r match { 207 | case Dialog.Result.Yes => result = 1 208 | case Dialog.Result.No => result = 2 209 | case Dialog.Result.Cancel => result = 3 210 | case _ => 211 | } 212 | } 213 | result 214 | } 215 | 216 | def askChoice(msg: String, choices: List[String]): String = { 217 | var result: String = "" 218 | Swing.onEDTWait { 219 | ui.visible = true 220 | val r = Dialog.showInput(canvas, msg, title=ui.title, 221 | Dialog.Message.Plain, 222 | Swing.EmptyIcon, choices, null) 223 | r match { 224 | case Some(s) => result = s 225 | case None => 226 | } 227 | } 228 | result 229 | } 230 | } 231 | 232 | // -------------------------------------------------------------------- 233 | -------------------------------------------------------------------------------- /cs109ui/uitest-animation.scala: -------------------------------------------------------------------------------- 1 | import org.otfried.cs109.UI._ 2 | import java.awt.image.BufferedImage 3 | import java.awt.{Graphics2D,Color,Font,BasicStroke} 4 | import java.awt.geom._ 5 | 6 | def draw(canvas: BufferedImage, x: Int, y: Int) { 7 | val g = canvas.createGraphics() 8 | g.setColor(Color.WHITE) 9 | g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) 10 | g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, 11 | java.awt.RenderingHints.VALUE_ANTIALIAS_ON) 12 | g.setColor(Color.RED) 13 | g.fill(new Ellipse2D.Double(x, y, 40.0, 40.0)) 14 | g.dispose() 15 | } 16 | 17 | def main() { 18 | setTitle("CS109 UI Animation test") 19 | 20 | val canvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB) 21 | 22 | var x = 30 23 | var y = 30 24 | while (x < 500) { 25 | draw(canvas, x, y) 26 | x += 2 27 | y += 1 28 | show(canvas) 29 | Thread.sleep(10) 30 | } 31 | } 32 | 33 | main() 34 | -------------------------------------------------------------------------------- /cs109ui/uitest-dialogs.scala: -------------------------------------------------------------------------------- 1 | 2 | import org.otfried.cs109.UI._ 3 | 4 | def main() { 5 | setTitle("CS109 UI Dialog Test") 6 | 7 | while (true) { 8 | showMessage("This is a message") 9 | 10 | val yesno = askYesNo("Do you like this?") 11 | printf("Answer: %s\n", yesno) 12 | 13 | val name = inputString("What is your name?") 14 | printf("Name: %s\n", name) 15 | 16 | val drink = askChoice("What do you like best", 17 | List("Beer", "Wine", "Makkoli", 18 | "Soju", "Water")) 19 | printf("Drink: %s\n", drink) 20 | 21 | val choice =askButtons("What do you want to do now?", 22 | List("Exit", "More dialogs", "Nothing")) 23 | choice match { 24 | case 1 => close() 25 | case 2 => 26 | case 3 => return 27 | } 28 | } 29 | } 30 | 31 | main() 32 | 33 | -------------------------------------------------------------------------------- /cs109ui/uitest1.scala: -------------------------------------------------------------------------------- 1 | 2 | import org.otfried.cs109.UI._ 3 | 4 | import java.awt.image.BufferedImage 5 | import java.awt.{Graphics2D,Color,Font,BasicStroke} 6 | import java.awt.geom._ 7 | 8 | def draw(canvas: BufferedImage) { 9 | // get Graphics2D for the image 10 | val g = canvas.createGraphics() 11 | 12 | // clear background 13 | g.setColor(Color.WHITE) 14 | g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) 15 | 16 | // enable anti-aliased rendering (prettier lines and circles) 17 | // Comment it out to see what this does! 18 | g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, 19 | java.awt.RenderingHints.VALUE_ANTIALIAS_ON) 20 | 21 | // draw two filled circles 22 | g.setColor(Color.RED) 23 | g.fill(new Ellipse2D.Double(30.0, 30.0, 40.0, 40.0)) 24 | g.fill(new Ellipse2D.Double(230.0, 380.0, 40.0, 40.0)) 25 | 26 | // draw an unfilled circle with a pen of width 3 27 | g.setColor(Color.MAGENTA) 28 | g.setStroke(new BasicStroke(3f)) 29 | g.draw(new Ellipse2D.Double(400.0, 35.0, 30.0, 30.0)) 30 | 31 | // draw a filled and an unfilled Rectangle 32 | g.setColor(Color.CYAN) 33 | g.fill(new Rectangle2D.Double(20.0, 400.0, 50.0, 20.0)) 34 | g.draw(new Rectangle2D.Double(400.0, 400.0, 50.0, 20.0)) 35 | 36 | // draw a line 37 | g.setStroke(new BasicStroke()) // reset to default 38 | g.setColor(new Color(0, 0, 255)) // same as Color.BLUE 39 | g.draw(new Line2D.Double(50.0, 50.0, 250.0, 400.0)) 40 | 41 | // draw some text 42 | g.setColor(new Color(0, 128, 0)) // a darker green 43 | g.setFont(new Font("Batang", Font.PLAIN, 20)) 44 | g.drawString("Hello World!", 155, 225) 45 | g.drawString("안녕 하세요", 175, 245) 46 | 47 | // done with drawing 48 | g.dispose() 49 | } 50 | 51 | def main() { 52 | setTitle("CS109 UI Test #1") 53 | val canvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB) 54 | draw(canvas) 55 | show(canvas) 56 | } 57 | 58 | main() 59 | -------------------------------------------------------------------------------- /cs109ui/uitest2.scala: -------------------------------------------------------------------------------- 1 | import org.otfried.cs109.UI._ 2 | 3 | import java.awt.image.BufferedImage 4 | import java.awt.{Graphics2D,Color,Font,BasicStroke} 5 | import java.awt.geom._ 6 | 7 | def draw(canvas: BufferedImage, color: Color) { 8 | val g = canvas.createGraphics() 9 | g.setColor(Color.WHITE) 10 | g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) 11 | g.setColor(color) 12 | g.fillRect(100, 100, 300, 300) 13 | g.dispose() 14 | } 15 | 16 | def showSleep(canvas: BufferedImage, color: Color, ms: Int) { 17 | draw(canvas, color) // draw rectangle 18 | show(canvas) 19 | Thread.sleep(ms) // wait ms milliseconds 20 | } 21 | 22 | def main() { 23 | setTitle("CS109 UI Blinking Rectangle") 24 | 25 | val canvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB) 26 | 27 | showSleep(canvas, Color.WHITE, 500) // 0.5 sec white picture 28 | showSleep(canvas, Color.RED, 1000) // 1 sec red rectangle 29 | showSleep(canvas, Color.WHITE, 500) // 0.5 sec white picture 30 | showSleep(canvas, Color.BLUE, 1000) // 1 sec blue rectangle 31 | showSleep(canvas, Color.WHITE, 5000) // 5 secs white picture 32 | 33 | close() // close window and terminate program 34 | } 35 | 36 | main() 37 | -------------------------------------------------------------------------------- /cs109ui/uitest3.scala: -------------------------------------------------------------------------------- 1 | import org.otfried.cs109.UI._ 2 | 3 | import java.awt.image.BufferedImage 4 | import java.awt.{Graphics2D,Color,Font,BasicStroke} 5 | import java.awt.geom._ 6 | 7 | def draw(canvas: BufferedImage, color: Color) { 8 | val g = canvas.createGraphics() 9 | g.setColor(Color.WHITE) 10 | g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) 11 | g.setColor(color) 12 | g.fillRect(100, 100, 300, 300) 13 | g.dispose() 14 | } 15 | 16 | def main() { 17 | setTitle("CS109 UI Keyboard Input Test") 18 | 19 | val canvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB) 20 | 21 | draw(canvas, Color.RED) 22 | show(canvas) 23 | 24 | println("Now press some keys inside the CS109 UI windows") 25 | println("Pressing 'q' will terminate the program") 26 | 27 | while (true) { 28 | val ch = waitKey() 29 | printf("Got character %c\n", ch) 30 | if (ch == 'q') 31 | close() // close window and terminate program 32 | } 33 | } 34 | 35 | main() 36 | -------------------------------------------------------------------------------- /cs109ui/uitest4.scala: -------------------------------------------------------------------------------- 1 | import org.otfried.cs109.UI._ 2 | 3 | import java.awt.image.BufferedImage 4 | import java.awt.{Graphics2D,Color,Font,BasicStroke} 5 | import java.awt.geom._ 6 | 7 | def draw(canvas: BufferedImage, color: Color) { 8 | val g = canvas.createGraphics() 9 | g.setColor(Color.WHITE) 10 | g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) 11 | g.setColor(color) 12 | g.fillRect(100, 100, 300, 300) 13 | g.dispose() 14 | } 15 | 16 | def main() { 17 | setTitle("CS109 UI Keyboard Input Test") 18 | 19 | val canvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB) 20 | 21 | draw(canvas, Color.RED) 22 | show(canvas) 23 | 24 | println("Now click the moused inside the CS109 UI windows") 25 | println("Close the window to terminate the program") 26 | 27 | while (true) { 28 | val (x,y) = waitMouse() 29 | printf("Mouse click at (%d,%d)\n", x, y) 30 | } 31 | } 32 | 33 | main() 34 | -------------------------------------------------------------------------------- /cs109ui/uitest5.scala: -------------------------------------------------------------------------------- 1 | import org.otfried.cs109.UI._ 2 | 3 | import java.awt.image.BufferedImage 4 | import java.awt.{Graphics2D,Color,Font,BasicStroke} 5 | import java.awt.geom._ 6 | 7 | def draw(canvas: BufferedImage, color: Color) { 8 | val g = canvas.createGraphics() 9 | g.setColor(Color.WHITE) 10 | g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) 11 | g.setColor(color) 12 | g.fillRect(100, 100, 300, 300) 13 | g.dispose() 14 | } 15 | 16 | def main() { 17 | setTitle("CS109 UI Keyboard Input Test") 18 | 19 | val canvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB) 20 | 21 | draw(canvas, Color.RED) 22 | show(canvas) 23 | 24 | println("You have 5 seconds to press a key inside the CS109 UI window") 25 | 26 | setTimeOut(5000) 27 | val ch = waitKey() 28 | if (ch == timeOutChar) 29 | println("You lost!") 30 | else 31 | printf("You won by typing %c\n", ch) 32 | 33 | close() // close window and terminate program 34 | } 35 | 36 | main() 37 | -------------------------------------------------------------------------------- /examples/drawing.scala: -------------------------------------------------------------------------------- 1 | 2 | import java.awt.image.BufferedImage 3 | import java.awt.{Graphics2D,Color,Font,BasicStroke} 4 | import java.awt.geom._ 5 | 6 | // Size of image 7 | val size = (500, 500) 8 | 9 | // create an image 10 | val canvas = new BufferedImage(size._1, size._2, BufferedImage.TYPE_INT_RGB) 11 | 12 | // get Graphics2D for the image 13 | val g = canvas.createGraphics() 14 | 15 | // clear background 16 | g.setColor(Color.WHITE) 17 | g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) 18 | 19 | // enable anti-aliased rendering (prettier lines and circles) 20 | // Comment it out to see what this does! 21 | g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, 22 | java.awt.RenderingHints.VALUE_ANTIALIAS_ON) 23 | 24 | // draw two filled circles 25 | g.setColor(Color.RED) 26 | g.fill(new Ellipse2D.Double(30.0, 30.0, 40.0, 40.0)) 27 | g.fill(new Ellipse2D.Double(230.0, 380.0, 40.0, 40.0)) 28 | 29 | // draw an unfilled circle with a pen of width 3 30 | g.setColor(Color.MAGENTA) 31 | g.setStroke(new BasicStroke(3f)) 32 | g.draw(new Ellipse2D.Double(400.0, 35.0, 30.0, 30.0)) 33 | 34 | // draw a filled and an unfilled Rectangle 35 | g.setColor(Color.CYAN) 36 | g.fill(new Rectangle2D.Double(20.0, 400.0, 50.0, 20.0)) 37 | g.draw(new Rectangle2D.Double(400.0, 400.0, 50.0, 20.0)) 38 | 39 | // draw a line 40 | g.setStroke(new BasicStroke()) // reset to default 41 | g.setColor(new Color(0, 0, 255)) // same as Color.BLUE 42 | g.draw(new Line2D.Double(50.0, 50.0, 250.0, 400.0)) 43 | 44 | // draw some text 45 | g.setColor(new Color(0, 128, 0)) // a darker green 46 | g.setFont(new Font("Batang", Font.PLAIN, 20)) 47 | g.drawString("Hello World!", 155, 225) 48 | g.drawString("안녕 하세요", 175, 245) 49 | 50 | // done with drawing 51 | g.dispose() 52 | 53 | // write image to a file 54 | javax.imageio.ImageIO.write(canvas, "png", new java.io.File("drawing.png")) 55 | -------------------------------------------------------------------------------- /examples/image.scala: -------------------------------------------------------------------------------- 1 | import java.io.File 2 | import javax.imageio.ImageIO 3 | import java.awt.image.BufferedImage 4 | 5 | def phototest(img: BufferedImage): BufferedImage = { 6 | // obtain width and height of image 7 | val w = img.getWidth 8 | val h = img.getHeight 9 | 10 | // create new image of the same size 11 | val out = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB) 12 | 13 | // copy pixels (mirror horizontally) 14 | for (x <- 0 until w) 15 | for (y <- 0 until h) 16 | out.setRGB(x, y, img.getRGB(w - x - 1, y) & 0xffffff) 17 | 18 | // draw red diagonal line 19 | for (x <- 0 until (h min w)) 20 | out.setRGB(x, x, 0xff0000) 21 | 22 | out 23 | } 24 | 25 | def test() { 26 | // read original image, and obtain width and height 27 | val photo1 = ImageIO.read(new File("photo.jpg")) 28 | 29 | val photo2 = phototest(photo1) 30 | 31 | // save image to file "test.jpg" 32 | ImageIO.write(photo2, "jpg", new File("test.jpg")) 33 | } 34 | 35 | test() 36 | -------------------------------------------------------------------------------- /examples/mastermind.scala: -------------------------------------------------------------------------------- 1 | // 2 | // Mastermind game 3 | // 4 | 5 | import scala.io.StdIn.readLine 6 | 7 | val MaxNumGuesses = 10 8 | 9 | // Create secret: four distinct letters from A-F. 10 | def createSecret(): String = { 11 | var c = "ABCDEF" 12 | var secret = "" 13 | for (i <- 1 to 4) { 14 | val index = (math.random * c.length).toInt 15 | val letter = c(index) 16 | c = c.substring(0,index) + c.substring(index+1) 17 | secret = secret + letter 18 | } 19 | secret 20 | } 21 | 22 | // Check if guess is legal: Four distinct letters from A-F. 23 | // Returns pair (ok: Boolean, message : String) 24 | def checkGuess(guess: String): (Boolean, String) = { 25 | if (guess.length != 4) 26 | return (false, "Your guess must have four letters") 27 | for (i <- 0 until 4) { 28 | val letter = guess(i) 29 | if (!"ABCDEF".contains(letter)) 30 | return (false, "You can only use letters A, B, C, D, E, and F.") 31 | for (j <- 0 until i) { 32 | if (letter == guess(j)) 33 | return (false, "All letters must be distinct.") 34 | } 35 | } 36 | return (true, "") 37 | } 38 | 39 | // read a guess from the terminal 40 | def getGuess(): String = { 41 | while (true) { 42 | var guess = readLine("Enter your guess> ") 43 | guess = guess.trim.toUpperCase.replace(" ", "") 44 | val (ok, msg) = checkGuess(guess) 45 | if (ok) 46 | return guess 47 | println(msg) 48 | } 49 | "" // only necessary because compiler complains otherwise 50 | } 51 | 52 | // Compute (pos, let) where pos is the number of correct letters in 53 | // the correct position, and let is the number of correct letters in 54 | // the wrong position. 55 | def evaluateGuess(secret: String, guess: String): (Int, Int) = { 56 | var pos = 0 57 | var let = 0 58 | for (i <- 0 until 4) { 59 | if (guess(i) == secret(i)) 60 | pos += 1 61 | else if (secret.contains(guess(i))) 62 | let += 1 63 | } 64 | (pos, let) 65 | } 66 | 67 | // Show history of guessing 68 | def showHistory(h: Array[String], current: Int, secret: String) { 69 | for (count <- 0 until current) { 70 | val guess = h(count) 71 | val (pos, let) = evaluateGuess(secret, guess) 72 | printf("%2d: %s : %d positions, %d letters\n", count+1, guess, pos, let) 73 | } 74 | } 75 | 76 | // main game 77 | def main() { 78 | val secret = createSecret() 79 | val history = new Array[String](MaxNumGuesses) 80 | var current = 0 81 | println("Welcome to Mastermind!") 82 | println("I have created a secret combination:") 83 | println("Four distinct letters from A - F.") 84 | printf("You have %d guesses to find it.\n", MaxNumGuesses) 85 | while (true) { 86 | showHistory(history, current, secret) 87 | if (current == MaxNumGuesses) { 88 | printf("My secret was %s, you failed to find it in %d guesses!\n", 89 | secret, current) 90 | return 91 | } 92 | val guess = getGuess() 93 | history(current) = guess 94 | current += 1 95 | val (pos, let) = evaluateGuess(secret, guess) 96 | if (pos == 4) { 97 | printf("My secret was %s, you guessed correctly in %d guesses!\n", 98 | secret, current) 99 | return 100 | } 101 | } 102 | } 103 | 104 | main() 105 | 106 | -------------------------------------------------------------------------------- /projects/bloxorz-simple-levels.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otfried/cs109-scala/0097f4a7aac22e45868938d91476878bf422c8b2/projects/bloxorz-simple-levels.zip -------------------------------------------------------------------------------- /projects/gpx.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/otfried/cs109-scala/0097f4a7aac22e45868938d91476878bf422c8b2/projects/gpx.zip -------------------------------------------------------------------------------- /projects/kaist.txt: -------------------------------------------------------------------------------- 1 | Korea Advanced Institute of Science and Technology (KAIST) was 2 | established in 1971 as the nation’s first graduate school specializing 3 | in science and engineering education and research. The school’s 4 | founding was a catalyst for Korea’s rapid rise from a producer of 5 | light industry goods to a world leader in high-technology industries. 6 | 7 | The political leadership in the 1960s and 1970s singled out education, 8 | work ethics and technological advancement as the means of transforming 9 | Korea from an underdeveloped agrarian society into an emerging economy 10 | equipped with technological and industrial competitiveness. KAIST was 11 | founded under a special law with government funding and initially 12 | staffed with a number of Korean engineering and science faculty 13 | educated in the United States. 14 | 15 | Research emphasis from the outset has been put on both theoretical and 16 | applied studies. KAIST continues to be Korea’s foremost center for 17 | mid- to long-term strategic R&D projects with national and 18 | international significance. The University has pioneered the 19 | establishment of competitive graduate school programs in Korea. 20 | 21 | Over the past four decades, KAIST has evolved into a global research 22 | university. The University’s strong faculty conducts internationally 23 | recognized research in cooperation with academic institutions and 24 | industries all over the world. KAIST offers generous grants and 25 | fellowships to international students, promoting Korea as a global 26 | educational power. 27 | 28 | The University has in recent years been recruiting distinguished 29 | scholars from overseas. All lectures at KAIST are given in English in 30 | principle to better serve a growing number of graduate and 31 | undergraduate students from overseas. 32 | 33 | The merger of KAIST and Information and Communications University in 34 | March 2009 further expanded KAIST’s academic asset in both research 35 | and education and enhanced its role as the major provider of high-tech 36 | manpower for Korea’s ever-growing economy. ICU had been established in 37 | 1997 as the nation’s only information technology research university 38 | jointly funded by the Korean government and some IT industrial 39 | organizations. Before the merger, ICU had 109 faculty members for 40 | bachelor’s, master’s and doctoral programs in its School of 41 | Engineering and School of IT-Business to a student-faculty ratio of 10 42 | to 1, the lowest in Korea. 43 | -------------------------------------------------------------------------------- /projects/polynomial.scala: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------- 2 | // Polynomials 3 | // -------------------------------------------------------------------- 4 | 5 | class Polynomial(coeffs: Array[Int]) { 6 | private val A = createCoeffs(coeffs) 7 | 8 | private def createCoeffs(A: Array[Int]): Array[Int] = { 9 | var s = A.length - 1 10 | while (s >= 0 && A(s) == 0) 11 | s -= 1 12 | A take (s+1) 13 | } 14 | 15 | def degree: Int = A.length - 1 16 | 17 | def coeff(i: Int): Int = if (i < A.length) A(i) else 0 18 | 19 | override def toString: String = { 20 | var s = new StringBuilder 21 | var plus = "" 22 | var minus = "-" 23 | for (i <- degree to 0 by -1) { 24 | if (coeff(i) != 0) { 25 | var c = coeff(i) 26 | s ++= (if (c > 0) plus else minus) 27 | plus = " + "; minus = " - " 28 | c = c.abs 29 | if (i == 0) 30 | s ++= c.toString 31 | else { 32 | if (c != 1) 33 | s ++= c.toString + " * " 34 | if (i > 1) 35 | s ++= "X^" + i.toString 36 | else 37 | s ++= "X" 38 | } 39 | } 40 | } 41 | s.toString 42 | } 43 | 44 | def + (rhs: Polynomial): Polynomial = { 45 | val deg = degree max rhs.degree 46 | val R = new Array[Int](deg + 1) 47 | for (i <- 0 to deg) 48 | R(i) = coeff(i) + rhs.coeff(i) 49 | new Polynomial(R) 50 | } 51 | 52 | def - (rhs: Polynomial): Polynomial = { 53 | val deg = degree max rhs.degree 54 | val R = new Array[Int](deg + 1) 55 | for (i <- 0 to deg) 56 | R(i) = coeff(i) - rhs.coeff(i) 57 | new Polynomial(R) 58 | } 59 | 60 | def * (rhs: Polynomial): Polynomial = { 61 | // first handle case if one factor is the zero polynomial 62 | if (degree < 0) 63 | this 64 | else if (rhs.degree < 0) 65 | rhs 66 | else { 67 | val deg = degree + rhs.degree 68 | val R = new Array[Int](deg + 1) 69 | for (i <- 0 to deg) { 70 | var sum = 0 71 | for (j <- 0 to i) 72 | sum += coeff(j) * rhs.coeff(i - j) 73 | R(i) = sum 74 | } 75 | new Polynomial(R) 76 | } 77 | } 78 | 79 | def ^ (ex: Int): Polynomial = { 80 | ex match { 81 | case 0 => new Polynomial(Array(1)) 82 | case 1 => this 83 | case 2 => this * this 84 | case 3 => this * this * this 85 | case _ => { 86 | val p = this ^ (ex / 2) 87 | if (ex % 2 == 1) p * p * this else p * p 88 | } 89 | } 90 | } 91 | 92 | // evaluate this polynomial at x 93 | def apply(x: Double): Double = { 94 | var result = 0.0 95 | for (i <- 0 to degree) { 96 | var power = 1.0 97 | for (j <- 1 to i) 98 | power *= x 99 | result += coeff(i) * power 100 | } 101 | result 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /projects/replies.txt: -------------------------------------------------------------------------------- 1 | family|mother|father|sister|brother|husband|wife: 2 | Tell me more about your family. 3 | How do you get along with your family? 4 | Is your family important to you? 5 | Do you often think about your family? 6 | How would you like to change your family? 7 | friend|friends|pal|mate|buddy|buddies: 8 | Why do you bring up the topic of friends? 9 | Do your friends worry you? 10 | Do your friends pick on you? 11 | Are you sure you have any friends? 12 | Do you impose on your friends? 13 | Perhaps your love for friends worries you? 14 | computer|computers: 15 | Do computers worry you? 16 | Are you talking about me in particular? 17 | Are you frightened by machines? 18 | Why do you mention computers? 19 | What do you think computers have to do with your problem? 20 | Don't you think computers can help people? 21 | What is it about machines that worries you? 22 | dream|dreams|nightmare|nightmares: 23 | What does that dream suggest to you? 24 | Do you dream often? 25 | What persons appear in your dreams? 26 | Are you disturbed by your dreams? 27 | can you: 28 | Don't you believe that I can* 29 | Perhaps you would like to be able to* 30 | You want me to be able to* 31 | can i: 32 | Perhaps you don't want to* 33 | Do you want to be able to* 34 | you are|youre: 35 | What makes you think I am* 36 | Does it please you to believe that I am* 37 | Perhaps you would like to be* 38 | Do you sometimes wish you were* 39 | i like|i am fond of: 40 | Why do you like* 41 | When did you decide that you like* 42 | What makes you fond of* 43 | i dont|i do not: 44 | Don't you really* 45 | Why don't you* 46 | Do you wish to be able to* 47 | Does that trouble you? 48 | i feel: 49 | Tell me more about such feelings. 50 | Do you often feel* 51 | Do you enjoy feeling* 52 | Why do you feel that way? 53 | why dont you: 54 | Do you really believe I don't* 55 | Perhaps in good time I will* 56 | Why do you think I don't* 57 | Do you want me to* 58 | why cant i: 59 | Do you think you should be able to* 60 | Why can't you* 61 | are you: 62 | Why are you interested in whether or not I am* 63 | Would you prefer if I were not* 64 | Perhaps in your fantasies I am* 65 | i cant|i cannot: 66 | How do you know you can't* 67 | Have you tried? 68 | Perhaps you can now* 69 | i am|im: 70 | Did you come to me because you are* 71 | How long have you been* 72 | Do you believe it is normal to be* 73 | Do you enjoy being* 74 | love: 75 | Why do you love* 76 | Isn't love too strong a word for your feeling about* 77 | What is your favorite thing about* 78 | Do you really love, or just like* 79 | i hate: 80 | Is it because of your upbringing that you hate* 81 | How do you express your hatred of* 82 | What brought you to hate* 83 | Have you tried doing something about* 84 | I also at times hate* 85 | fear|scared|afraid of: 86 | You are in friendly surroundings, please try not to worry. 87 | Would you like your friends to help you overcome your fear of* 88 | What scares you about* 89 | Why are you frightened by* 90 | i want: 91 | What would it mean if you got* 92 | Why do you want* 93 | Suppose you soon got* 94 | What if you never got* 95 | I sometimes also want* 96 | name: 97 | Names don't interest me. 98 | I don't care about names. Go on. 99 | cause|because: 100 | Is that the real reason? 101 | Don't any other reasons come to mind? 102 | Does that reason explain anything else? 103 | What other reason might there be? 104 | sorry: 105 | Please don't apologize. 106 | Apologies are not necessary. 107 | What feelings do you get when you apologize. 108 | Don't be so defensive! 109 | hi|hello: 110 | How do you do... Please state your problem. 111 | maybe: 112 | You don't seem quite certain. 113 | Why the uncertain tone? 114 | Can't you be more positive? 115 | You aren't sure? 116 | Don't you know? 117 | your: 118 | Why are you concerned about my* 119 | What about your own* 120 | always: 121 | Can you think of a specific example? 122 | When? 123 | What are you thinking of? 124 | Really, always? 125 | i think: 126 | Do you really think so? 127 | But are you sure* 128 | Do you doubt that* 129 | Why do you think* 130 | alike|the same: 131 | In what way? 132 | What resemblence do you see? 133 | What does the similarity suggest to you? 134 | What other connections do you see? 135 | Could there really be some connection? 136 | How? 137 | You seem quite positive. 138 | he|she: 139 | I am interested in your feelings about this person. Please describe them. 140 | What is your relationship to this person? 141 | money: 142 | How do you use money to enjoy yourself? 143 | Have you tried to do anything to increase your income lately? 144 | How do you react to financial stress? 145 | job|boss|jobs|work: 146 | Do you feel competent in your work? 147 | Have you considered changing jobs? 148 | Is your career satisfying to you? 149 | Do you find work stressful? 150 | What is your relationship with your boss like? 151 | sad|depressed: 152 | Are you sad because you want to avoid people? 153 | Do you feel bad from something that happened to you, or to somebody else?" 154 | Your situation doesn't sound that bad to me. Perhaps you're worrying too much. 155 | anger|angry: 156 | Do you really want to be angry? 157 | Does anger satisfy you in some way? 158 | Why are you so angry? 159 | Perhaps you're using anger to avoid social contact. 160 | you: 161 | We were discussing you-- not me. 162 | Oh, I* 163 | You're not really talking about me, are you? 164 | yes: 165 | Are you sure? 166 | I see. 167 | I understand. 168 | no: 169 | Are you saying that just to be negative? 170 | You are being a bit negative. 171 | Why not? 172 | Are you sure? 173 | Why no? 174 | i need: 175 | Why do you need* 176 | Is need not too strong a word? 177 | What would be wrong with not having* 178 | Tell me more about* 179 | i remember: 180 | Do you often think of* 181 | Why do you remember* 182 | What in the present situation reminds you of* 183 | What is the connection between me and* 184 | do you remember: 185 | Did you think i would forget* 186 | Why do you think i should RECALL* 187 | What about* 188 | if: 189 | Do you think it's likely that if* 190 | god|religion|faith: 191 | Do you believe in a god? 192 | Are you a religious person? 193 | how|what|who|where|when|why: 194 | Why do you ask? 195 | Does that question interest you? 196 | What answer would please you the most? 197 | What do you think? 198 | Are such questions on your mind often? 199 | What is it you really want to know? 200 | Have you asked anyone else? 201 | Have you asked such questions before? 202 | What else comes to mind when you ask that? 203 | : 204 | Say, do you have any psychological problems? 205 | What does that suggest to you? 206 | I see. 207 | I'm not sure I understand you fully. 208 | Come, come, elucidate your thoughts. 209 | Can you elaborate on that? 210 | That is quite interesting. 211 | You are being short with me. 212 | -------------------------------------------------------------------------------- /projects/scala.txt: -------------------------------------------------------------------------------- 1 | In this course, I plan to use the Scala programming language. 2 | 3 | In my experience, students develop a style of programming in their 4 | first programming language. They find it difficult to learn a 5 | different style later, even if they switch to a different 6 | language. This means that students should start early to use a modern 7 | language that encourages writing clean and elegant code, and supports 8 | a good object-oriented and functional style. 9 | 10 | I therefore want to try using Scala this semester. Scala is not yet a 11 | popular or successful language (although I believe it will be), and so 12 | most students will have to learn C++ and/or Java later during 13 | their studies--but I believe that after getting programming practice 14 | in Scala, they will be able to write better code in those languages as 15 | well. 16 | 17 | -------------------------------------------------------------------------------- /swing/clock1.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | import java.awt.{Font,Color} 3 | 4 | object Time { 5 | private val form = new java.text.SimpleDateFormat("HH:mm:ss") 6 | def current = form.format(java.util.Calendar.getInstance().getTime) 7 | } 8 | 9 | object Timer { 10 | def apply(interval: Int, repeats: Boolean = true)(op: => Unit) { 11 | val timeOut = new javax.swing.AbstractAction() { 12 | def actionPerformed(e : java.awt.event.ActionEvent) = op 13 | } 14 | val t = new javax.swing.Timer(interval, timeOut) 15 | t.setRepeats(repeats) 16 | t.start() 17 | } 18 | } 19 | 20 | class UI extends MainFrame { 21 | title = "Clock #1" 22 | preferredSize = new Dimension(320, 160) 23 | private var lastTime = Time.current 24 | private val clock = new Label(lastTime) { 25 | foreground = new Color(0, 0, 160) 26 | font = new Font("SansSerif", Font.PLAIN, 64) 27 | } 28 | contents = clock 29 | Timer(200) { tick() } 30 | Timer(10000, false) { println("Clock has been running for 10 seconds!") } 31 | 32 | def tick() { 33 | // this method is called every 100 milliseconds 34 | val newTime = Time.current 35 | if (newTime != lastTime) { 36 | clock.text = newTime 37 | lastTime = newTime 38 | } 39 | } 40 | } 41 | 42 | object ClockOne { 43 | def main(args: Array[String]) { 44 | val ui = new UI 45 | ui.visible = true 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /swing/crossword1.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | import scala.swing.event._ 3 | 4 | class Solver { 5 | private val words = scala.io.Source.fromFile("words.txt").getLines().toSet 6 | 7 | private def matches(pattern: String, word: String): Boolean = { 8 | if (word.length != pattern.length) 9 | return false 10 | for (i <- 0 until word.length) { 11 | val p = pattern(i) 12 | if (p != '?' && p != word(i)) 13 | return false 14 | } 15 | true 16 | } 17 | 18 | def findWords(pattern: String): List[String] = { 19 | var w = List[String]() 20 | for (e <- words) { 21 | if (matches(pattern, e)) 22 | w = e :: w 23 | } 24 | w 25 | } 26 | } 27 | 28 | class UI(val solver: Solver) extends MainFrame { 29 | private def restrictHeight(s: Component) { 30 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 31 | } 32 | 33 | title = "Crossword Puzzle Helper" 34 | val searchField = new TextField { columns = 32 } 35 | val searchButton = new Button("Search") 36 | val searchLine = new BoxPanel(Orientation.Horizontal) { 37 | contents += searchField 38 | contents += Swing.HStrut(20) 39 | contents += searchButton 40 | } 41 | val resultField = new TextArea { 42 | rows = 10 43 | lineWrap = true 44 | wordWrap = true 45 | editable = false 46 | } 47 | 48 | // make sure that resizing only changes the resultField: 49 | restrictHeight(searchLine) 50 | 51 | contents = new BoxPanel(Orientation.Vertical) { 52 | contents += searchLine 53 | contents += Swing.VStrut(10) 54 | contents += new ScrollPane(resultField) 55 | border = Swing.EmptyBorder(10, 10, 10, 10) 56 | } 57 | 58 | listenTo(searchField) 59 | listenTo(searchButton) 60 | reactions += { 61 | case EditDone(`searchField`) => searchNow() 62 | case ButtonClicked(`searchButton`) => searchNow() 63 | } 64 | 65 | def searchNow() { 66 | val pattern = searchField.text.toLowerCase 67 | val words = solver.findWords(pattern) 68 | if (words.length == 0) { 69 | resultField.text = "\n\nSorry, no words found." 70 | } else { 71 | resultField.text = words.sorted mkString "\n" 72 | resultField.caret.position = 0 73 | } 74 | } 75 | } 76 | 77 | object Crossword { 78 | def main(args: Array[String]) { 79 | val solver = new Solver 80 | val ui = new UI(solver) 81 | ui.visible = true 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /swing/crossword2.scala: -------------------------------------------------------------------------------- 1 | import java.awt.Font 2 | import scala.swing._ 3 | import scala.swing.event._ 4 | 5 | class Solver { 6 | private val allWords = scala.io.Source.fromFile("words.txt").getLines().toSet 7 | private val scrabble = 8 | (scala.io.Source.fromFile("scrabble.txt").getLines().toSet 9 | map ((s: String) => s.toLowerCase)) 10 | 11 | private def matches(pattern: String, word: String): Boolean = { 12 | if (word.length != pattern.length) 13 | return false 14 | for (i <- 0 until word.length) { 15 | val p = pattern(i) 16 | if (p != '?' && p != word(i)) 17 | return false 18 | } 19 | true 20 | } 21 | 22 | def findWords(pattern: String, dictNo: Int): List[String] = { 23 | var w = List[String]() 24 | val words = if (dictNo == 1) allWords else scrabble 25 | for (e <- words) { 26 | if (matches(pattern, e)) 27 | w = e :: w 28 | } 29 | w 30 | } 31 | } 32 | 33 | class UI(val solver: Solver) extends MainFrame { 34 | private def restrictHeight(s: Component) { 35 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 36 | } 37 | 38 | title = "Crossword Puzzle Helper" 39 | val searchField = new TextField { columns = 32 } 40 | val searchButton = new Button("Search") 41 | val searchLine = new BoxPanel(Orientation.Horizontal) { 42 | contents += searchField 43 | contents += Swing.HStrut(20) 44 | contents += searchButton 45 | } 46 | val resultField = new TextArea { 47 | rows = 10 48 | lineWrap = true 49 | wordWrap = true 50 | editable = false 51 | } 52 | val dict = new ComboBox(List("Scrabble words", "All words")) 53 | val largerFont = Button("+") { fontChange(+1) } 54 | val smallerFont = Button("-") { fontChange(-1) } 55 | var fontSize = 12 56 | fontChange(0) 57 | 58 | // make sure that resizing only changes the resultField: 59 | restrictHeight(searchLine) 60 | 61 | contents = new BoxPanel(Orientation.Vertical) { 62 | contents += searchLine 63 | contents += Swing.VStrut(10) 64 | contents += new ScrollPane(resultField) 65 | contents += Swing.VStrut(10) 66 | contents += new BoxPanel(Orientation.Horizontal) { 67 | contents += dict 68 | contents += Swing.HStrut(10) 69 | contents += largerFont 70 | contents += Swing.HStrut(10) 71 | contents += smallerFont 72 | } 73 | border = Swing.EmptyBorder(10, 10, 10, 10) 74 | } 75 | 76 | listenTo(searchField) 77 | listenTo(searchButton) 78 | reactions += { 79 | case EditDone(`searchField`) => searchNow() 80 | case ButtonClicked(`searchButton`) => searchNow() 81 | } 82 | 83 | def fontChange(d: Int) { 84 | fontSize += d 85 | resultField.font = new Font(null, Font.PLAIN, fontSize) 86 | } 87 | 88 | def searchNow() { 89 | val pattern = searchField.text.toLowerCase 90 | val words = solver.findWords(pattern, dict.selection.index) 91 | if (words.length == 0) { 92 | resultField.text = "\n\nSorry, no words found." 93 | } else { 94 | resultField.text = words.sorted mkString "\n" 95 | resultField.caret.position = 0 96 | } 97 | } 98 | } 99 | 100 | object Crossword { 101 | def main(args: Array[String]) { 102 | val solver = new Solver 103 | val ui = new UI(solver) 104 | ui.visible = true 105 | } 106 | } 107 | 108 | -------------------------------------------------------------------------------- /swing/floodit.scala: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------- 2 | // Flood-It! Game 3 | // -------------------------------------------------------------------- 4 | 5 | import java.awt.{Graphics2D,Color} 6 | import scala.swing._ 7 | 8 | // -------------------------------------------------------------------- 9 | 10 | case class Pos(val x: Int, val y: Int) 11 | 12 | class Blocks(val width: Int, val height: Int) { 13 | private val data = Array.ofDim[Int](width, height) 14 | resetData() 15 | 16 | // Create initial pattern 17 | def resetData() = { 18 | for (x <- 0 until width) 19 | for (y <- 0 until height) 20 | data(x)(y) = (math.random * FloodIt.NumColors).toInt 21 | } 22 | 23 | // Return color of the pixel. 24 | def get(pos: Pos): Int = data(pos.x)(pos.y) 25 | 26 | // Set color of pixel. 27 | def set(pos: Pos, color: Int) = { 28 | require(0 <= color && color <= FloodIt.NumColors) 29 | data(pos.x)(pos.y) = color 30 | } 31 | 32 | // Return array with neighbors of a pixel 33 | def neighbors(p: Pos): List[Pos] = { 34 | var nb = List[Pos]() 35 | val Pos(x, y) = p 36 | if (x > 0) 37 | nb = Pos(x-1, y) :: nb 38 | if (y > 0) 39 | nb = Pos(x, y-1) :: nb 40 | if (x + 1 < width) 41 | nb = Pos(x+1, y) :: nb 42 | if (y + 1 < height) 43 | nb = Pos(x, y+1) :: nb 44 | nb 45 | } 46 | 47 | def allFilled(): Boolean = { 48 | val col = data(0)(0) 49 | for (x <- 0 until width; y <- 0 until height) 50 | if (data(x)(y) != col) 51 | return false 52 | true 53 | } 54 | 55 | def flood(start: Pos, color: Int) { 56 | val A = new scala.collection.mutable.Queue[Pos] 57 | 58 | val oldCol = get(start) 59 | if (oldCol == color) 60 | return 61 | 62 | set(start, color) 63 | A += start 64 | 65 | while (!A.isEmpty) { 66 | val q = A.dequeue() 67 | val nb = neighbors(q) 68 | for (r <- nb) { 69 | if (get(r) == oldCol) { 70 | set(r, color) 71 | A += r 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | // -------------------------------------------------------------------- 79 | 80 | class Canvas(val blocks: Blocks) extends Component { 81 | 82 | override def paintComponent(g : Graphics2D) { 83 | val d = size 84 | g.setColor(Color.white); 85 | g.fillRect(0,0, d.width, d.height); 86 | val rowWid = d.height / blocks.height 87 | val colWid = d.width / blocks.width 88 | val wid = rowWid min colWid 89 | val x0 = (d.width - blocks.width * wid)/2 90 | val y0 = (d.height - blocks.height * wid)/2 91 | for (x <- 0 until blocks.width) { 92 | for (y <- 0 until blocks.height) { 93 | g.setColor(FloodIt.colorFor(blocks.get(Pos(x, y)))) 94 | g.fillRect(x0 + x * wid, y0 + y * wid, wid, wid) 95 | } 96 | } 97 | } 98 | } 99 | 100 | // -------------------------------------------------------------------- 101 | 102 | class FloodUI extends MainFrame { 103 | val turns = new Label("Turns: 0") 104 | var counter = 0 105 | 106 | val blocks = new Blocks(FloodIt.size, FloodIt.size) 107 | val canvas = new Canvas(blocks) 108 | 109 | title = FloodIt.Title 110 | preferredSize = new Dimension(640, 480) 111 | contents = new BorderPanel { 112 | border = Swing.MatteBorder(8, 8, 8, 8, Color.white) 113 | add(canvas, BorderPanel.Position.Center) 114 | val buttons = new BoxPanel(Orientation.Horizontal) { 115 | border = Swing.EmptyBorder(8, 0, 0, 0) 116 | background = Color.white 117 | contents += Button("New Game") { newGame() } 118 | contents += Swing.HGlue 119 | for (i <- 0 until FloodIt.NumColors) { 120 | val b = Button(" ") { colorClick(i) } 121 | b.background = FloodIt.colorFor(i) 122 | contents += b 123 | } 124 | contents += Swing.HGlue 125 | contents += turns 126 | contents += Swing.HGlue 127 | contents += Button("Quit") { System.exit(0) } 128 | } 129 | add(buttons, BorderPanel.Position.South) 130 | } 131 | 132 | private def setTurns() { turns.text = "Turns: %d".format(counter) } 133 | 134 | private def restartGame() { 135 | counter = 0 136 | setTurns() 137 | blocks.resetData() 138 | canvas.repaint() 139 | } 140 | 141 | def newGame() { 142 | if (Dialog.showConfirmation(canvas, "Do you want to start a new game", 143 | title=FloodIt.Title) == Dialog.Result.Ok) 144 | restartGame() 145 | } 146 | 147 | def colorClick(color: Int) { 148 | if (color == blocks.get(Pos(0,0))) { 149 | Dialog.showMessage(canvas, "You must be kidding!", title=FloodIt.Title) 150 | } else { 151 | counter += 1 152 | setTurns() 153 | blocks.flood(Pos(0,0), color) 154 | canvas.repaint() 155 | if (blocks.allFilled()) { 156 | val s = "Congratulations, you made it in %d turns".format(counter) 157 | Dialog.showMessage(canvas, s, title=FloodIt.Title) 158 | restartGame() 159 | } 160 | } 161 | } 162 | } 163 | 164 | object FloodIt { 165 | var size = 19 166 | val NumColors = 6 167 | val Title = "Flood It!" 168 | 169 | def colorFor(n: Int): Color = { 170 | n match { 171 | case 0 => Color.red 172 | case 1 => Color.green 173 | case 2 => Color.blue 174 | case 3 => Color.yellow 175 | case 4 => Color.pink 176 | case 5 => Color.cyan 177 | case _ => Color.white // should not happen 178 | } 179 | } 180 | 181 | def main(args: Array[String]) { 182 | if (args.length == 1) 183 | size = args(0).toInt 184 | 185 | val ui = new FloodUI 186 | ui.visible = true 187 | } 188 | } 189 | 190 | // -------------------------------------------------------------------- 191 | -------------------------------------------------------------------------------- /swing/gui1.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "GUI Program #1" 5 | preferredSize = new Dimension(320, 240) 6 | contents = new Label("Here is the contents!") 7 | } 8 | 9 | object GuiProgramOne { 10 | def main(args: Array[String]) { 11 | val ui = new UI 12 | ui.visible = true 13 | println("End of main function") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /swing/gui2.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "GUI Program #2" 5 | preferredSize = new Dimension(320, 240) 6 | contents = Button("Press me, please") { println("Thank you") } 7 | } 8 | 9 | object GuiProgramTwo { 10 | def main(args: Array[String]) { 11 | val ui = new UI 12 | ui.visible = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /swing/gui3.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "GUI Program #3" 5 | contents = new BoxPanel(Orientation.Vertical) { 6 | contents += new Label("Look at me!") 7 | contents += Button("Press me, please") { println("Thank you") } 8 | contents += Button("Close") { sys.exit(0) } 9 | } 10 | } 11 | 12 | object GuiProgramThree { 13 | def main(args: Array[String]) { 14 | val ui = new UI 15 | ui.visible = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /swing/gui3a.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "GUI Program #3" 5 | val box = new BoxPanel(Orientation.Vertical) 6 | box.contents += new Label("Look at me!") 7 | box.contents += Button("Press me, please") { println("Thank you") } 8 | box.contents += Button("Close") { sys.exit(0) } 9 | contents = box 10 | } 11 | 12 | object GuiProgramThree { 13 | def main(args: Array[String]) { 14 | val ui = new UI 15 | ui.visible = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /swing/gui3b.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "GUI Program #3" 5 | contents = new BoxPanel(Orientation.Vertical) { 6 | contents += new Label("Look at me!") 7 | contents += Swing.VStrut(10) 8 | contents += Swing.Glue 9 | contents += Button("Press me, please") { println("Thank you") } 10 | contents += Swing.VStrut(5) 11 | contents += Button("Close") { sys.exit(0) } 12 | border = Swing.EmptyBorder(10, 10, 10, 10) 13 | } 14 | } 15 | 16 | object GuiProgramThree { 17 | def main(args: Array[String]) { 18 | val ui = new UI 19 | ui.visible = true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /swing/gui3c.scala: -------------------------------------------------------------------------------- 1 | import java.awt.Color 2 | import scala.swing._ 3 | 4 | class UI extends MainFrame { 5 | title = "GUI Program #3" 6 | contents = new BoxPanel(Orientation.Vertical) { 7 | val la = new Label("Look at me!", Swing.EmptyIcon, Alignment.Center) 8 | la.foreground = Color.BLUE 9 | contents += la 10 | contents += Swing.VStrut(10) 11 | contents += Swing.Glue 12 | contents += Button("Press me, please") { println("Thank you") } 13 | contents += Swing.VStrut(5) 14 | contents += Button("Close") { sys.exit(0) } 15 | for (e <- contents) 16 | e.xLayoutAlignment = 0.5 17 | border = Swing.EmptyBorder(10, 10, 10, 10) 18 | } 19 | } 20 | 21 | object GuiProgramThree { 22 | def main(args: Array[String]) { 23 | val ui = new UI 24 | ui.visible = true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /swing/gui3d.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "GUI Program #3" 5 | contents = new BoxPanel(Orientation.Vertical) { 6 | val la = new Label("Look at me!") 7 | la.foreground = java.awt.Color.BLUE 8 | la.xLayoutAlignment = 0.5 9 | contents += la 10 | contents += Swing.VStrut(10) 11 | contents += Swing.Glue 12 | contents += new BoxPanel(Orientation.Horizontal) { 13 | contents += Swing.HGlue 14 | contents += Button("Press me, please") { println("Thank you") } 15 | contents += Swing.HStrut(5) 16 | contents += Button("Close") { sys.exit(0) } 17 | for (e <- contents) 18 | e.yLayoutAlignment = 1.0 19 | } 20 | border = Swing.EmptyBorder(10, 10, 10, 10) 21 | } 22 | } 23 | 24 | object GuiProgramThree { 25 | def main(args: Array[String]) { 26 | val ui = new UI 27 | ui.visible = true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /swing/gui4.scala: -------------------------------------------------------------------------------- 1 | import java.awt.Color 2 | import scala.swing._ 3 | 4 | class UI extends MainFrame { 5 | val la = new Label("Look at me!") 6 | 7 | la.foreground = Color.BLUE 8 | title = "GUI Program #4" 9 | 10 | contents = new BoxPanel(Orientation.Vertical) { 11 | contents += la 12 | contents += Swing.VStrut(10) 13 | contents += Swing.Glue 14 | contents += Button("Press me, please") { pressMe() } 15 | contents += Swing.VStrut(5) 16 | contents += Button("Change text") { changeText() } 17 | contents += Swing.VStrut(5) 18 | contents += Button("Close") { closeMe() } 19 | border = Swing.EmptyBorder(10, 10, 10, 10) 20 | } 21 | 22 | def pressMe() { 23 | Dialog.showMessage(contents.head, "Thank you!", title="You pressed me") 24 | } 25 | 26 | def changeText() { 27 | val r = Dialog.showInput(contents.head, "New label text", initial=la.text) 28 | r match { 29 | case Some(s) => la.text = s 30 | case None => 31 | } 32 | } 33 | 34 | def closeMe() { 35 | val res = Dialog.showConfirmation(contents.head, 36 | "Do you really want to quit?", 37 | optionType=Dialog.Options.YesNo, 38 | title=title) 39 | if (res == Dialog.Result.Ok) 40 | sys.exit(0) 41 | } 42 | } 43 | 44 | object GuiProgramFour { 45 | def main(args: Array[String]) { 46 | val ui = new UI 47 | ui.visible = true 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /swing/gui5.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | def restrictHeight(s: Component) { 5 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 6 | } 7 | 8 | title = "GUI Program #5" 9 | 10 | val nameField = new TextField { columns = 32 } 11 | val likeScala = new CheckBox("I like Scala") 12 | likeScala.selected = true 13 | val status1 = new RadioButton("학부생") 14 | val status2 = new RadioButton("대학원생") 15 | val status3 = new RadioButton("교수") 16 | status3.selected = true 17 | val statusGroup = new ButtonGroup(status1, status2, status3) 18 | val gender = new ComboBox(List("don't know", "female", "male")) 19 | val commentField = new TextArea { rows = 8; lineWrap = true; wordWrap = true } 20 | val pressMe = new ToggleButton("Press me!") 21 | pressMe.selected = true 22 | 23 | restrictHeight(nameField) 24 | restrictHeight(gender) 25 | 26 | contents = new BoxPanel(Orientation.Vertical) { 27 | contents += new BoxPanel(Orientation.Horizontal) { 28 | contents += new Label("My name") 29 | contents += Swing.HStrut(5) 30 | contents += nameField 31 | } 32 | contents += Swing.VStrut(5) 33 | contents += likeScala 34 | contents += Swing.VStrut(5) 35 | contents += new BoxPanel(Orientation.Horizontal) { 36 | contents += status1 37 | contents += Swing.HStrut(10) 38 | contents += status2 39 | contents += Swing.HStrut(10) 40 | contents += status3 41 | } 42 | contents += Swing.VStrut(5) 43 | contents += new BoxPanel(Orientation.Horizontal) { 44 | contents += new Label("Gender") 45 | contents += Swing.HStrut(20) 46 | contents += gender 47 | } 48 | contents += Swing.VStrut(5) 49 | contents += new Label("Comments") 50 | contents += Swing.VStrut(3) 51 | contents += new ScrollPane(commentField) 52 | contents += Swing.VStrut(5) 53 | contents += new BoxPanel(Orientation.Horizontal) { 54 | contents += pressMe 55 | contents += Swing.HGlue 56 | contents += Button("Close") { reportAndClose() } 57 | } 58 | for (e <- contents) 59 | e.xLayoutAlignment = 0.0 60 | border = Swing.EmptyBorder(10, 10, 10, 10) 61 | } 62 | 63 | def reportAndClose() { 64 | println("Your name: " + nameField.text) 65 | println("You like Scala: " + likeScala.selected) 66 | println("Undergraduate: " + status1.selected) 67 | println("Graduate: " + status2.selected) 68 | println("Professor: " + status3.selected) 69 | println("Gender: " + gender.selection.item + 70 | " (Index: " + gender.selection.index + ")") 71 | println("Comments: " + commentField.text) 72 | println("'Press me' is pressed: " + pressMe.selected) 73 | sys.exit(0) 74 | } 75 | } 76 | 77 | object GuiProgramFive { 78 | def main(args: Array[String]) { 79 | val ui = new UI 80 | ui.visible = true 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /swing/gui6.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | import scala.swing.event._ 3 | 4 | class UI extends MainFrame { 5 | def restrictHeight(s: Component) { 6 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 7 | } 8 | 9 | title = "GUI Program #6" 10 | 11 | val nameField = new TextField { columns = 32 } 12 | val likeScala = new CheckBox("I like Scala") 13 | likeScala.selected = true 14 | val status1 = new RadioButton("학부생") 15 | val status2 = new RadioButton("대학원생") 16 | val status3 = new RadioButton("교수") 17 | status3.selected = true 18 | val statusGroup = new ButtonGroup(status1, status2, status3) 19 | val gender = new ComboBox(List("don't know", "female", "male")) 20 | val commentField = new TextArea { rows = 8; lineWrap = true; wordWrap = true } 21 | val pressMe = new ToggleButton("Press me!") 22 | pressMe.selected = true 23 | pressMe.tooltip = "This button wants to be pressed" 24 | 25 | restrictHeight(nameField) 26 | restrictHeight(gender) 27 | 28 | contents = new BoxPanel(Orientation.Vertical) { 29 | contents += new BoxPanel(Orientation.Horizontal) { 30 | contents += new Label("My name") 31 | contents += Swing.HStrut(5) 32 | contents += nameField 33 | } 34 | contents += Swing.VStrut(5) 35 | contents += likeScala 36 | contents += Swing.VStrut(5) 37 | contents += new BoxPanel(Orientation.Horizontal) { 38 | contents += status1 39 | contents += Swing.HStrut(10) 40 | contents += status2 41 | contents += Swing.HStrut(10) 42 | contents += status3 43 | } 44 | contents += Swing.VStrut(5) 45 | contents += new BoxPanel(Orientation.Horizontal) { 46 | contents += new Label("Gender") 47 | contents += Swing.HStrut(20) 48 | contents += gender 49 | } 50 | contents += Swing.VStrut(5) 51 | contents += new Label("Comments") 52 | contents += Swing.VStrut(3) 53 | contents += new ScrollPane(commentField) 54 | contents += Swing.VStrut(5) 55 | contents += new BoxPanel(Orientation.Horizontal) { 56 | contents += pressMe 57 | contents += Swing.HGlue 58 | contents += Button("Close") { reportAndClose() } 59 | } 60 | for (e <- contents) 61 | e.xLayoutAlignment = 0.0 62 | border = Swing.EmptyBorder(10, 10, 10, 10) 63 | } 64 | 65 | listenTo(nameField) 66 | listenTo(commentField) 67 | listenTo(gender.selection) 68 | listenTo(likeScala) 69 | listenTo(status1) 70 | listenTo(status2) 71 | listenTo(status3) 72 | listenTo(pressMe) 73 | 74 | reactions += { 75 | case EditDone(`nameField`) => 76 | println("Your name is now: " + nameField.text) 77 | case EditDone(`commentField`) => 78 | println("You changed the comments") 79 | case SelectionChanged(`gender`) => 80 | println("Your gender is now: " + gender.selection.item) 81 | case ButtonClicked(`likeScala`) => 82 | if (!likeScala.selected) { 83 | if (Dialog.showConfirmation(contents.head, 84 | "Are you sure you don't like Scala?") 85 | != Dialog.Result.Yes) 86 | likeScala.selected = true 87 | } 88 | case ButtonClicked(s) => 89 | println("Button click on button: '" + s.text + "'") 90 | } 91 | 92 | def reportAndClose() { 93 | println("Your name: " + nameField.text) 94 | println("You like Scala: " + likeScala.selected) 95 | println("Undergraduate: " + status1.selected) 96 | println("Graduate: " + status2.selected) 97 | println("Professor: " + status3.selected) 98 | println("Gender: " + gender.selection.item + 99 | " (Index: " + gender.selection.index + ")") 100 | println("Comments: " + commentField.text) 101 | println("'Press me' is pressed: " + pressMe.selected) 102 | sys.exit(0) 103 | } 104 | } 105 | 106 | object GuiProgramSix { 107 | def main(args: Array[String]) { 108 | val ui = new UI 109 | ui.visible = true 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /swing/panel1.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "Flow Panel" 5 | contents = new FlowPanel { 6 | contents += new Label("A Label") 7 | contents += Swing.HStrut(30) 8 | contents += new Button("A Button") 9 | contents += new Button("Another Button") 10 | contents += Button("Close") { sys.exit(0) } 11 | } 12 | } 13 | 14 | object PanelOne { 15 | def main(args: Array[String]) { 16 | val ui = new UI 17 | ui.visible = true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /swing/panel2.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "Border Panel" 5 | contents = new BorderPanel { 6 | add(new Button("North"), BorderPanel.Position.North) 7 | add(new Button("Center"), BorderPanel.Position.Center) 8 | add(new Button("East"), BorderPanel.Position.East) 9 | add(new Button("West"), BorderPanel.Position.West) 10 | add(Button("South: Close") { sys.exit(0) }, BorderPanel.Position.South) 11 | } 12 | } 13 | 14 | object PanelTwo { 15 | def main(args: Array[String]) { 16 | val ui = new UI 17 | ui.visible = true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /swing/panel3.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "Grid Panel" 5 | contents = new GridPanel(3, 2) { 6 | contents += new Label("A Label") 7 | contents += new Button("A Button") 8 | contents += new Button("Another Button") 9 | contents += new Button("Button Three") 10 | contents += new CheckBox("Check me!") 11 | contents += Button("Close") { sys.exit(0) } 12 | } 13 | } 14 | 15 | object PanelThree { 16 | def main(args: Array[String]) { 17 | val ui = new UI 18 | ui.visible = true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /swing/panel4.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | 3 | class UI extends MainFrame { 4 | title = "GridBagPanel" 5 | contents = new GridBagPanel { 6 | def constraints(x: Int, y: Int, 7 | gridwidth: Int = 1, gridheight: Int = 1, 8 | weightx: Double = 0.0, weighty: Double = 0.0, 9 | fill: GridBagPanel.Fill.Value = GridBagPanel.Fill.None) 10 | : Constraints = { 11 | val c = new Constraints 12 | c.gridx = x 13 | c.gridy = y 14 | c.gridwidth = gridwidth 15 | c.gridheight = gridheight 16 | c.weightx = weightx 17 | c.weighty = weighty 18 | c.fill = fill 19 | c 20 | } 21 | 22 | add(new Label("Label @ (0,0)") {border=Swing.EtchedBorder(Swing.Lowered) }, 23 | constraints(0, 0, gridheight=2, fill=GridBagPanel.Fill.Both)) 24 | add(new ToggleButton("Button @ (2,0)"), 25 | constraints(2, 0)) 26 | add(new Button("Button @ (2,1)"), 27 | constraints(2, 1)) 28 | add(new Button("Button @ (2,2)"), 29 | constraints(2, 2)) 30 | add(new CheckBox("Check me!"), 31 | constraints(0, 2)) 32 | add(new TextField { columns = 32 }, 33 | constraints(1, 0, weightx=1.0, fill=GridBagPanel.Fill.Horizontal)) 34 | add(new ScrollPane(new TextArea), 35 | constraints(1, 1, gridheight=3, weighty = 1.0, 36 | fill=GridBagPanel.Fill.Both)) 37 | add(Button("Close") { sys.exit(0) }, 38 | constraints(0, 4, gridwidth=3, fill=GridBagPanel.Fill.Horizontal)) 39 | } 40 | } 41 | 42 | object PanelFour { 43 | def main(args: Array[String]) { 44 | val ui = new UI 45 | ui.visible = true 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /swing/tictactoe1.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | import scala.swing.event._ 3 | import java.awt.{Color,Graphics2D,BasicStroke} 4 | import java.awt.geom._ 5 | 6 | // -------------------------------------------------------------------- 7 | 8 | class Board { 9 | private val grid = Array(0, 1, 2, 10 | 0, 1, 0, 11 | 0, 2, 0) 12 | 13 | def apply(x: Int, y: Int): Int = grid(3 * y + x) 14 | } 15 | 16 | // -------------------------------------------------------------------- 17 | 18 | class Canvas(val board: Board) extends Component { 19 | preferredSize = new Dimension(320, 320) 20 | 21 | override def paintComponent(g : Graphics2D) { 22 | val d = size 23 | g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, 24 | java.awt.RenderingHints.VALUE_ANTIALIAS_ON) 25 | g.setColor(Color.WHITE); 26 | g.fillRect(0,0, d.width, d.height); 27 | val squareSide = d.height min d.width 28 | val wid = squareSide / 3 29 | val x0 = (d.width - squareSide)/2 30 | val y0 = (d.height - squareSide)/2 31 | g.setColor(Color.BLACK) 32 | // vertical lines 33 | for (x <- 1 to 2) 34 | g.draw(new Line2D.Double(x0 + x * wid, y0, x0 + x * wid, y0 + squareSide)) 35 | // horizontal lines 36 | for (y <- 1 to 2) 37 | g.draw(new Line2D.Double(x0, y0 + y * wid, x0 + squareSide, y0 + y * wid)) 38 | g.setStroke(new BasicStroke(3f)) 39 | for (x <- 0 until 3) { 40 | for (y <- 0 until 3) { 41 | board(x, y) match { 42 | case 1 => 43 | g.setColor(Color.RED) 44 | g.draw(new Ellipse2D.Double(x0 + x * wid + 10, y0 + y * wid + 10, 45 | wid - 20, wid - 20)) 46 | case 2 => 47 | g.setColor(new Color(0, 160, 0)) 48 | val x1 = x0 + x * wid + 10 49 | val y1 = y0 + y * wid + 10 50 | g.draw(new Line2D.Double(x1, y1, x1 + wid - 20, y1 + wid - 20)) 51 | g.draw(new Line2D.Double(x1, y1 + wid - 20, x1 + wid - 20, y1)) 52 | case _ => // draw nothing 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | // -------------------------------------------------------------------- 60 | 61 | class UI(val board: Board) extends MainFrame { 62 | private def restrictHeight(s: Component) { 63 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 64 | } 65 | 66 | title = "Tic Tac Toe #1" 67 | 68 | val canvas = new Canvas(board) 69 | val newGameButton = Button("New Game") { newGame() } 70 | val quitButton = Button("Quit") { sys.exit(0) } 71 | val buttonLine = new BoxPanel(Orientation.Horizontal) { 72 | contents += newGameButton 73 | contents += Swing.HGlue 74 | contents += quitButton 75 | } 76 | 77 | // make sure that resizing only changes the TicTacToeDisplay 78 | restrictHeight(buttonLine) 79 | 80 | contents = new BoxPanel(Orientation.Vertical) { 81 | contents += canvas 82 | contents += Swing.VStrut(10) 83 | contents += buttonLine 84 | border = Swing.EmptyBorder(10, 10, 10, 10) 85 | } 86 | 87 | def newGame() { 88 | println("New Game!") 89 | } 90 | } 91 | 92 | object TicTacToeOne { 93 | def main(args: Array[String]) { 94 | val board = new Board 95 | val ui = new UI(board) 96 | ui.visible = true 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /swing/tictactoe2.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | import scala.swing.event._ 3 | import java.awt.{Color,Graphics2D,BasicStroke} 4 | import java.awt.geom._ 5 | 6 | // -------------------------------------------------------------------- 7 | 8 | class Board { 9 | private val grid = Array(0, 1, 2, 10 | 0, 1, 0, 11 | 0, 2, 0) 12 | 13 | def apply(x: Int, y: Int): Int = grid(3 * y + x) 14 | } 15 | 16 | // -------------------------------------------------------------------- 17 | 18 | class Canvas(val board: Board) extends Component { 19 | preferredSize = new Dimension(320, 320) 20 | 21 | listenTo(mouse.clicks) 22 | reactions += { 23 | case MouseClicked(_, p, _, _, _) => mouseClick(p.x, p.y) 24 | } 25 | 26 | // returns squareSide, x0, y0, wid 27 | private def squareGeometry: (Int, Int, Int, Int) = { 28 | val d = size 29 | val squareSide = d.height min d.width 30 | val x0 = (d.width - squareSide)/2 31 | val y0 = (d.height - squareSide)/2 32 | (squareSide, x0, y0, squareSide/3) 33 | } 34 | 35 | private def mouseClick(x: Int, y: Int) { 36 | val (squareSide, x0, y0, wid) = squareGeometry 37 | if (x0 <= x && x < x0 + squareSide && 38 | y0 <= y && y < y0 + squareSide) { 39 | val col = (x - x0) / wid 40 | val row = (y - y0) / wid 41 | printf("Mouse pressed in field %d, %d\n", col, row) 42 | } 43 | } 44 | 45 | override def paintComponent(g : Graphics2D) { 46 | g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, 47 | java.awt.RenderingHints.VALUE_ANTIALIAS_ON) 48 | g.setColor(Color.WHITE); 49 | val d = size 50 | g.fillRect(0,0, d.width, d.height) 51 | val (squareSide, x0, y0, wid) = squareGeometry 52 | g.setColor(Color.BLACK) 53 | // vertical lines 54 | for (x <- 1 to 2) 55 | g.draw(new Line2D.Double(x0 + x * wid, y0, x0 + x * wid, y0 + squareSide)) 56 | // horizontal lines 57 | for (y <- 1 to 2) 58 | g.draw(new Line2D.Double(x0, y0 + y * wid, x0 + squareSide, y0 + y * wid)) 59 | g.setStroke(new BasicStroke(3f)) 60 | for (x <- 0 until 3) { 61 | for (y <- 0 until 3) { 62 | board(x, y) match { 63 | case 1 => 64 | g.setColor(Color.RED) 65 | g.draw(new Ellipse2D.Double(x0 + x * wid + 10, y0 + y * wid + 10, 66 | wid - 20, wid - 20)) 67 | case 2 => 68 | g.setColor(new Color(0, 160, 0)) 69 | val x1 = x0 + x * wid + 10 70 | val y1 = y0 + y * wid + 10 71 | g.draw(new Line2D.Double(x1, y1, x1 + wid - 20, y1 + wid - 20)) 72 | g.draw(new Line2D.Double(x1, y1 + wid - 20, x1 + wid - 20, y1)) 73 | case _ => // draw nothing 74 | } 75 | } 76 | } 77 | } 78 | } 79 | 80 | // -------------------------------------------------------------------- 81 | 82 | class UI(val board: Board) extends MainFrame { 83 | private def restrictHeight(s: Component) { 84 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 85 | } 86 | 87 | title = "Tic Tac Toe #2" 88 | 89 | val canvas = new Canvas(board) 90 | val newGameButton = Button("New Game") { newGame() } 91 | val quitButton = Button("Quit") { sys.exit(0) } 92 | val buttonLine = new BoxPanel(Orientation.Horizontal) { 93 | contents += newGameButton 94 | contents += Swing.HGlue 95 | contents += quitButton 96 | } 97 | 98 | // make sure that resizing only changes the TicTacToeDisplay 99 | restrictHeight(buttonLine) 100 | 101 | contents = new BoxPanel(Orientation.Vertical) { 102 | contents += canvas 103 | contents += Swing.VStrut(10) 104 | contents += buttonLine 105 | border = Swing.EmptyBorder(10, 10, 10, 10) 106 | } 107 | 108 | def newGame() { 109 | println("New Game!") 110 | } 111 | } 112 | 113 | object TicTacToeTwo { 114 | def main(args: Array[String]) { 115 | val board = new Board 116 | val ui = new UI(board) 117 | ui.visible = true 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /swing/tictactoe3.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | import scala.swing.event._ 3 | import java.awt.{Color,Graphics2D,BasicStroke} 4 | import java.awt.geom._ 5 | 6 | // -------------------------------------------------------------------- 7 | 8 | class Board { 9 | private var player = 1 10 | private val grid = Array(0, 0, 0, 11 | 0, 0, 0, 12 | 0, 0, 0) 13 | 14 | def apply(x: Int, y: Int): Int = grid(3 * y + x) 15 | def currentPlayer: Int = player 16 | def play(x: Int, y: Int) { 17 | if (this(x, y) == 0) { 18 | grid(3 * y + x) = player 19 | player = 3 - player 20 | } 21 | } 22 | def restart() { 23 | for (i <- 0 until 9) 24 | grid(i) = 0 25 | player = 1 26 | } 27 | } 28 | 29 | // -------------------------------------------------------------------- 30 | 31 | case class TicTacToeEvent(x: Int, y: Int) extends Event 32 | 33 | // -------------------------------------------------------------------- 34 | 35 | class Canvas(val board: Board) extends Component { 36 | preferredSize = new Dimension(320, 320) 37 | 38 | listenTo(mouse.clicks) 39 | reactions += { 40 | case MouseClicked(_, p, _, _, _) => mouseClick(p.x, p.y) 41 | } 42 | 43 | // returns squareSide, x0, y0, wid 44 | private def squareGeometry: (Int, Int, Int, Int) = { 45 | val d = size 46 | val squareSide = d.height min d.width 47 | val x0 = (d.width - squareSide)/2 48 | val y0 = (d.height - squareSide)/2 49 | (squareSide, x0, y0, squareSide/3) 50 | } 51 | 52 | private def mouseClick(x: Int, y: Int) { 53 | val (squareSide, x0, y0, wid) = squareGeometry 54 | if (x0 <= x && x < x0 + squareSide && 55 | y0 <= y && y < y0 + squareSide) { 56 | val col = (x - x0) / wid 57 | val row = (y - y0) / wid 58 | publish(TicTacToeEvent(col, row)) 59 | } 60 | } 61 | 62 | override def paintComponent(g : Graphics2D) { 63 | g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, 64 | java.awt.RenderingHints.VALUE_ANTIALIAS_ON) 65 | g.setColor(Color.WHITE); 66 | val d = size 67 | g.fillRect(0,0, d.width, d.height) 68 | val (squareSide, x0, y0, wid) = squareGeometry 69 | g.setColor(Color.BLACK) 70 | // vertical lines 71 | for (x <- 1 to 2) 72 | g.draw(new Line2D.Double(x0 + x * wid, y0, x0 + x * wid, y0 + squareSide)) 73 | // horizontal lines 74 | for (y <- 1 to 2) 75 | g.draw(new Line2D.Double(x0, y0 + y * wid, x0 + squareSide, y0 + y * wid)) 76 | g.setStroke(new BasicStroke(3f)) 77 | for (x <- 0 until 3) { 78 | for (y <- 0 until 3) { 79 | board(x, y) match { 80 | case 1 => 81 | g.setColor(Color.RED) 82 | g.draw(new Ellipse2D.Double(x0 + x * wid + 10, y0 + y * wid + 10, 83 | wid - 20, wid - 20)) 84 | case 2 => 85 | g.setColor(new Color(0, 160, 0)) 86 | val x1 = x0 + x * wid + 10 87 | val y1 = y0 + y * wid + 10 88 | g.draw(new Line2D.Double(x1, y1, x1 + wid - 20, y1 + wid - 20)) 89 | g.draw(new Line2D.Double(x1, y1 + wid - 20, x1 + wid - 20, y1)) 90 | case _ => // draw nothing 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | // -------------------------------------------------------------------- 98 | 99 | class UI(val board: Board) extends MainFrame { 100 | private def restrictHeight(s: Component) { 101 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 102 | } 103 | 104 | title = "Tic Tac Toe #3" 105 | 106 | val canvas = new Canvas(board) 107 | val newGameButton = Button("New Game") { newGame() } 108 | val turnLabel = new Label("Player 1's turn") 109 | turnLabel.foreground = Color.BLUE 110 | val quitButton = Button("Quit") { sys.exit(0) } 111 | val buttonLine = new BoxPanel(Orientation.Horizontal) { 112 | contents += newGameButton 113 | contents += Swing.HGlue 114 | contents += turnLabel 115 | contents += Swing.HGlue 116 | contents += quitButton 117 | } 118 | 119 | // make sure that resizing only changes the TicTacToeDisplay 120 | restrictHeight(buttonLine) 121 | 122 | contents = new BoxPanel(Orientation.Vertical) { 123 | contents += canvas 124 | contents += Swing.VStrut(10) 125 | contents += buttonLine 126 | border = Swing.EmptyBorder(10, 10, 10, 10) 127 | } 128 | 129 | listenTo(canvas) 130 | reactions += { 131 | case TicTacToeEvent(x, y) => 132 | board.play(x, y) 133 | updateLabelAndBoard() 134 | } 135 | 136 | def updateLabelAndBoard() { 137 | turnLabel.text = "Player %d's turn".format(board.currentPlayer) 138 | canvas.repaint() 139 | } 140 | 141 | def newGame() { 142 | board.restart() 143 | updateLabelAndBoard() 144 | } 145 | } 146 | 147 | object TicTacToeThree { 148 | def main(args: Array[String]) { 149 | val board = new Board 150 | val ui = new UI(board) 151 | ui.visible = true 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /swing/tictactoe4.scala: -------------------------------------------------------------------------------- 1 | import scala.swing._ 2 | import scala.swing.event._ 3 | import java.awt.{Color,Graphics2D,BasicStroke} 4 | import java.awt.geom._ 5 | 6 | // -------------------------------------------------------------------- 7 | 8 | class Board { 9 | private var player = 1 10 | private val grid = Array(0, 0, 0, 11 | 0, 0, 0, 12 | 0, 0, 0) 13 | 14 | def apply(x: Int, y: Int): Int = grid(3 * y + x) 15 | def currentPlayer: Int = player 16 | def play(x: Int, y: Int) { 17 | if (this(x, y) == 0) { 18 | grid(3 * y + x) = player 19 | player = 3 - player 20 | } 21 | } 22 | def restart() { 23 | for (i <- 0 until 9) 24 | grid(i) = 0 25 | player = 1 26 | } 27 | } 28 | 29 | // -------------------------------------------------------------------- 30 | 31 | case class TicTacToeEvent(x: Int, y: Int) extends Event 32 | 33 | // -------------------------------------------------------------------- 34 | 35 | class Canvas(val board: Board) extends Component { 36 | preferredSize = new Dimension(320, 320) 37 | 38 | focusable = true 39 | listenTo(mouse.clicks) 40 | listenTo(keys) 41 | reactions += { 42 | case MouseClicked(_, p, _, _, _) => mouseClick(p.x, p.y) 43 | case KeyTyped(_, c, _, _) => 44 | if ('1' <= c && c <= '9') { 45 | val idx = c - '1' 46 | publish(TicTacToeEvent(idx % 3, idx / 3)) 47 | } 48 | } 49 | 50 | // returns squareSide, x0, y0, wid 51 | private def squareGeometry: (Int, Int, Int, Int) = { 52 | val d = size 53 | val squareSide = d.height min d.width 54 | val x0 = (d.width - squareSide)/2 55 | val y0 = (d.height - squareSide)/2 56 | (squareSide, x0, y0, squareSide/3) 57 | } 58 | 59 | private def mouseClick(x: Int, y: Int) { 60 | val (squareSide, x0, y0, wid) = squareGeometry 61 | if (x0 <= x && x < x0 + squareSide && 62 | y0 <= y && y < y0 + squareSide) { 63 | val col = (x - x0) / wid 64 | val row = (y - y0) / wid 65 | publish(TicTacToeEvent(col, row)) 66 | } 67 | } 68 | 69 | override def paintComponent(g : Graphics2D) { 70 | g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, 71 | java.awt.RenderingHints.VALUE_ANTIALIAS_ON) 72 | g.setColor(Color.WHITE); 73 | val d = size 74 | g.fillRect(0,0, d.width, d.height) 75 | val (squareSide, x0, y0, wid) = squareGeometry 76 | g.setColor(Color.BLACK) 77 | // vertical lines 78 | for (x <- 1 to 2) 79 | g.draw(new Line2D.Double(x0 + x * wid, y0, x0 + x * wid, y0 + squareSide)) 80 | // horizontal lines 81 | for (y <- 1 to 2) 82 | g.draw(new Line2D.Double(x0, y0 + y * wid, x0 + squareSide, y0 + y * wid)) 83 | g.setStroke(new BasicStroke(3f)) 84 | for (x <- 0 until 3) { 85 | for (y <- 0 until 3) { 86 | board(x, y) match { 87 | case 1 => 88 | g.setColor(Color.RED) 89 | g.draw(new Ellipse2D.Double(x0 + x * wid + 10, y0 + y * wid + 10, 90 | wid - 20, wid - 20)) 91 | case 2 => 92 | g.setColor(new Color(0, 160, 0)) 93 | val x1 = x0 + x * wid + 10 94 | val y1 = y0 + y * wid + 10 95 | g.draw(new Line2D.Double(x1, y1, x1 + wid - 20, y1 + wid - 20)) 96 | g.draw(new Line2D.Double(x1, y1 + wid - 20, x1 + wid - 20, y1)) 97 | case _ => // draw nothing 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | // -------------------------------------------------------------------- 105 | 106 | class UI(val board: Board) extends MainFrame { 107 | private def restrictHeight(s: Component) { 108 | s.maximumSize = new Dimension(Short.MaxValue, s.preferredSize.height) 109 | } 110 | 111 | title = "Tic Tac Toe #4" 112 | 113 | val canvas = new Canvas(board) 114 | val newGameButton = Button("New Game") { newGame() } 115 | val turnLabel = new Label("Player 1's turn") 116 | turnLabel.foreground = Color.BLUE 117 | val quitButton = Button("Quit") { sys.exit(0) } 118 | val buttonLine = new BoxPanel(Orientation.Horizontal) { 119 | contents += newGameButton 120 | contents += Swing.HGlue 121 | contents += turnLabel 122 | contents += Swing.HGlue 123 | contents += quitButton 124 | } 125 | 126 | // make sure that resizing only changes the TicTacToeDisplay 127 | restrictHeight(buttonLine) 128 | 129 | contents = new BoxPanel(Orientation.Vertical) { 130 | contents += canvas 131 | contents += Swing.VStrut(10) 132 | contents += buttonLine 133 | border = Swing.EmptyBorder(10, 10, 10, 10) 134 | } 135 | 136 | listenTo(canvas) 137 | reactions += { 138 | case TicTacToeEvent(x, y) => 139 | board.play(x, y) 140 | updateLabelAndBoard() 141 | } 142 | 143 | def updateLabelAndBoard() { 144 | turnLabel.text = "Player %d's turn".format(board.currentPlayer) 145 | canvas.repaint() 146 | } 147 | 148 | def newGame() { 149 | board.restart() 150 | updateLabelAndBoard() 151 | } 152 | } 153 | 154 | object TicTacToeFour { 155 | def main(args: Array[String]) { 156 | val board = new Board 157 | val ui = new UI(board) 158 | ui.visible = true 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /tutorial/05-basic/arguments.scala: -------------------------------------------------------------------------------- 1 | for (s <- args) 2 | println(s) 3 | -------------------------------------------------------------------------------- /tutorial/05-basic/overloading.scala: -------------------------------------------------------------------------------- 1 | def f(n: Int) { 2 | println("Int " + n) 3 | } 4 | 5 | def f(s: String) { 6 | println("String " + s) 7 | } 8 | 9 | f(17) 10 | f("CS109") 11 | 12 | -------------------------------------------------------------------------------- /tutorial/05-basic/triangle1.scala: -------------------------------------------------------------------------------- 1 | def triangle(n: Int) { 2 | for (i <- 1 to n) { 3 | for (j <- 1 to i) 4 | print("*") 5 | println() 6 | } 7 | } 8 | 9 | val size = 5 10 | triangle(size) 11 | -------------------------------------------------------------------------------- /tutorial/05-basic/triangle2.scala: -------------------------------------------------------------------------------- 1 | def triangle(n: Int) { 2 | for (i <- 1 to n) { 3 | for (j <- 1 to i) 4 | print("*") 5 | println() 6 | } 7 | } 8 | 9 | val size = args(0).toInt 10 | triangle(size) 11 | -------------------------------------------------------------------------------- /tutorial/05-basic/triangle3.scala: -------------------------------------------------------------------------------- 1 | def triangle(n: Int) { 2 | for (i <- 1 to n) { 3 | for (j <- 1 to i) 4 | print("*") 5 | println() 6 | } 7 | } 8 | 9 | if (args.length == 1) { 10 | val size = args(0).toInt 11 | triangle(size) 12 | } else 13 | println("Usage: scala triangle.scala ") 14 | -------------------------------------------------------------------------------- /tutorial/07-collatz/collatz1.scala: -------------------------------------------------------------------------------- 1 | 2 | def next(n: Int): Int = { 3 | if (n % 2 == 0) 4 | n / 2 5 | else 6 | 3 * n + 1 7 | } 8 | -------------------------------------------------------------------------------- /tutorial/07-collatz/collatz2.scala: -------------------------------------------------------------------------------- 1 | 2 | def next(n: Int): Int = { 3 | if (n % 2 == 0) 4 | n / 2 5 | else 6 | 3 * n + 1 7 | } 8 | 9 | def collatz(n0: Int) { 10 | var n = n0 11 | while (n != 1) { 12 | print(n) 13 | print(" ") 14 | n = next(n) 15 | } 16 | println(1) 17 | } 18 | -------------------------------------------------------------------------------- /tutorial/07-collatz/collatz3.scala: -------------------------------------------------------------------------------- 1 | 2 | def next(n: Int): Int = { 3 | if (n % 2 == 0) 4 | n / 2 5 | else 6 | 3 * n + 1 7 | } 8 | 9 | def collatzCount(n0: Int): Int = { 10 | var n = n0 11 | var count = 0 12 | while (n != 1) { 13 | n = next(n) 14 | count += 1 15 | } 16 | count 17 | } 18 | 19 | def findMax(n: Int) { 20 | var maxCount = 0 21 | var maxStart = 1 22 | for (i <- 2 to n) { 23 | val count = collatzCount(i) 24 | if (count > maxCount) { 25 | maxCount = count 26 | maxStart = i 27 | } 28 | } 29 | printf("Starting at %d needs %d steps.\n", maxStart, maxCount) 30 | } 31 | -------------------------------------------------------------------------------- /tutorial/07-collatz/collatz4.scala: -------------------------------------------------------------------------------- 1 | 2 | def next(n: Int): Int = { 3 | if (n % 2 == 0) 4 | n / 2 5 | else 6 | 3 * n + 1 7 | } 8 | 9 | def collatzBounded(n0: Int, steps: Int): Int = { 10 | var n = n0 11 | var count = 0 12 | while (n != 1 && count < steps) { 13 | n = next(n) 14 | count += 1 15 | } 16 | count 17 | } 18 | 19 | def findLong(n: Int, steps: Int) { 20 | for (i <- 2 to n) { 21 | val count = collatzBounded(i, steps) 22 | if (count >= steps) { 23 | printf("Starting at %d needs %d steps.\n", i, count) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tutorial/07-collatz/collatz5.scala: -------------------------------------------------------------------------------- 1 | 2 | def next(n: Int): Int = { 3 | if (n % 2 == 0) 4 | n / 2 5 | else 6 | 3 * n + 1 7 | } 8 | 9 | def collatzBounded(n0: Int, steps: Int) { 10 | var n = n0 11 | var count = 0 12 | while (n != 1 && count < steps) { 13 | print(n) 14 | print(" ") 15 | n = next(n) 16 | count += 1 17 | } 18 | println 19 | } 20 | -------------------------------------------------------------------------------- /tutorial/10-objects/test.scala: -------------------------------------------------------------------------------- 1 | 2 | case class Point(x: Int, y: Int, color: String) 3 | 4 | def more(l: Array[Point]) { 5 | for (i <- 0 until l.length) { 6 | l(i) = Point(l(i).y, l(i).x, l(i).color) 7 | } 8 | // HERE 9 | } 10 | 11 | def test(m: Int, s: String) { 12 | val a = Point(1, m, s) 13 | val b = Array(a, Point(2, 7, "blue")) 14 | val c = b(1) 15 | more(b) 16 | } 17 | -------------------------------------------------------------------------------- /tutorial/13-sets/sieve1.scala: -------------------------------------------------------------------------------- 1 | 2 | def sieve(n: Int): Set[Int] = { 3 | var s = Set[Int]() 4 | for (i <- 2 to n) 5 | s = s + i 6 | val sqrtn = math.sqrt(n).toInt 7 | for (i <- 2 to sqrtn) { 8 | if (s contains i) { 9 | var k = i * i 10 | while (k <= n) { 11 | s = s - k 12 | k += i 13 | } 14 | } 15 | } 16 | s 17 | } 18 | 19 | val num = if (args.nonEmpty) args(0).toInt else 1000 20 | 21 | val primes = sieve(num).toArray.sorted 22 | 23 | for (i <- primes) 24 | print(i + " ") 25 | println() 26 | -------------------------------------------------------------------------------- /tutorial/13-sets/sieve2.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.collection.mutable.Set 3 | 4 | def sieve(n: Int): Set[Int] = { 5 | var s = Set[Int]() 6 | for (i <- 2 to n) 7 | s += i 8 | val sqrtn = math.sqrt(n).toInt 9 | for (i <- 2 to sqrtn) { 10 | if (s contains i) { 11 | var k = i * i 12 | while (k <= n) { 13 | s -= k 14 | k += i 15 | } 16 | } 17 | } 18 | s 19 | } 20 | 21 | val num = if (args.nonEmpty) args(0).toInt else 1000 22 | 23 | val primes = sieve(num).toArray.sorted 24 | 25 | for (i <- primes) 26 | print(i + " ") 27 | println() 28 | -------------------------------------------------------------------------------- /tutorial/13-sets/spell1.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.io.Source 3 | import scala.io.StdIn.readLine 4 | 5 | val fname = "words.txt" 6 | 7 | val F = Source.fromFile(fname) 8 | val words = F.getLines().toSet 9 | 10 | while (true) { 11 | val w = readLine("Enter a word> ").trim 12 | if (w == "") 13 | sys.exit() 14 | if (words contains w) 15 | println(w + " is a word") 16 | else 17 | printf("Error: %s is not a word\n", w) 18 | } 19 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/catch1.scala: -------------------------------------------------------------------------------- 1 | import scala.io.StdIn.readLine 2 | 3 | val str = readLine("Enter a number> ") 4 | try { 5 | val x = str.toInt 6 | printf("You said: %d\n", x) 7 | } catch { 8 | case e: NumberFormatException => 9 | printf("'%s' is not a number\n", str); 10 | } 11 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/catch2.scala: -------------------------------------------------------------------------------- 1 | def test(s: String): Int = { 2 | (s.toDouble * 100).toInt 3 | } 4 | 5 | def show(s: String) { 6 | try { 7 | println(test(s)) 8 | } catch { 9 | case e: NumberFormatException => 10 | println("Incorrect input") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/except1.scala: -------------------------------------------------------------------------------- 1 | import scala.io.StdIn.readLine 2 | 3 | def f(n: Int) { 4 | printf("Starting f(%d) ... \n", n) 5 | g(n) 6 | printf("Ending f(%d) ... \n", n) 7 | } 8 | 9 | def g(n: Int) { 10 | printf("Starting g(%d) ... \n", n) 11 | val m = 100 / n 12 | printf("The result is %d\n", m) 13 | printf("Ending g(%d) ... \n", n) 14 | } 15 | 16 | def main() { 17 | while (true) { 18 | val s = readLine("Enter a number> ") 19 | if (s.isEmpty) 20 | return 21 | try { 22 | println("Beginning of try block") 23 | val n = s.toInt 24 | f(n) 25 | println("End of try block") 26 | } catch { 27 | case e: NumberFormatException 28 | => println("Please enter a number!") 29 | case e: ArithmeticException 30 | => println("I can't handle this value!") 31 | } 32 | } 33 | } 34 | 35 | main() 36 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/except2.scala: -------------------------------------------------------------------------------- 1 | import scala.io.StdIn.readLine 2 | 3 | def f(n: Int) { 4 | printf("Starting f(%d) ... \n", n) 5 | g(n) 6 | printf("Ending f(%d) ... \n", n) 7 | } 8 | 9 | def g(n: Int) { 10 | printf("Starting g(%d) ... \n", n) 11 | if (n < 0) 12 | throw new IllegalArgumentException 13 | printf("The value is %d\n", n) 14 | printf("Ending g(%d) ... \n", n) 15 | } 16 | 17 | def main() { 18 | while (true) { 19 | val s = readLine("Enter a number> ") 20 | if (s.isEmpty) 21 | return 22 | try { 23 | println("Beginning of try block") 24 | val n = s.toInt 25 | f(n) 26 | println("End of try block") 27 | } catch { 28 | case e: NumberFormatException 29 | => println("Please enter a number!") 30 | case e: IllegalArgumentException 31 | => println("I can't handle this value!") 32 | } 33 | } 34 | } 35 | 36 | main() 37 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/except3.scala: -------------------------------------------------------------------------------- 1 | import scala.io.StdIn.readLine 2 | 3 | def f(n: Int) { 4 | printf("Starting f(%d) ... \n", n) 5 | g(n) 6 | printf("Ending f(%d) ... \n", n) 7 | } 8 | 9 | def g(n: Int) { 10 | printf("Starting g(%d) ... \n", n) 11 | if (n < 0) 12 | throw new IllegalArgumentException 13 | printf("The value is %d\n", n) 14 | printf("Ending g(%d) ... \n", n) 15 | } 16 | 17 | def main() { 18 | while (true) { 19 | val s = readLine("Enter a number> ") 20 | if (s.isEmpty) 21 | return 22 | try { 23 | println("Beginning of try block") 24 | val n = s.toInt 25 | f(n) 26 | println("End of try block") 27 | } catch { 28 | case e: NumberFormatException 29 | => println("Please enter a number!") 30 | case e: IllegalArgumentException 31 | => e.printStackTrace() 32 | } 33 | } 34 | } 35 | 36 | main() 37 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/quiz.scala: -------------------------------------------------------------------------------- 1 | 2 | def g(s: String, n: Int) { 3 | if (n > 10) 4 | throw new IllegalArgumentException 5 | for (i <- 1 to n) 6 | println(s) 7 | } 8 | 9 | def f(s: String) { 10 | val t = s + " World" 11 | g(t, 3) 12 | } 13 | 14 | def main(m: Int) { 15 | try { 16 | val r = 13 * m 17 | f("Hello") 18 | } catch { 19 | case e: IllegalArgumentException => 20 | println("Oops, something was wrong") 21 | } 22 | } 23 | 24 | main(3) 25 | 26 | 27 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/read1.scala: -------------------------------------------------------------------------------- 1 | var F: scala.io.Source = null 2 | try { 3 | F = scala.io.Source.fromFile("project.txt") 4 | for (line <- F.getLines()) 5 | printf("%4d %s\n", line.length, line) 6 | F.close() 7 | } catch { 8 | case e: java.io.FileNotFoundException => 9 | println("Project file does not exist!") 10 | case e: java.io.IOException => { 11 | println("Error reading project file!") 12 | F.close() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tutorial/16-exceptions/require1.scala: -------------------------------------------------------------------------------- 1 | def factorial(n: Int): Long = { 2 | require(n >= 0) 3 | var result = 1L 4 | for (i <- 1 to n) 5 | result *= i 6 | result 7 | } 8 | 9 | println(factorial(args(0).toInt)) 10 | 11 | -------------------------------------------------------------------------------- /tutorial/18-buffers/makestring1.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.compat.Platform.currentTime 3 | 4 | def makestring(A: Array[Int]): String = { 5 | var s = "" 6 | for (e <- A) { 7 | if (s.isEmpty) 8 | s = e.toString 9 | else 10 | s = s + ", " + e.toString 11 | } 12 | s 13 | } 14 | 15 | val n = args(0).toInt 16 | val A = (1 to n).toArray 17 | 18 | println("Starting...") 19 | val t0 = currentTime 20 | val str = makestring(A) 21 | val t1 = currentTime 22 | //println(str) 23 | printf("Making a string of %d numbers took %d milliseconds\n", n, t1 - t0) 24 | -------------------------------------------------------------------------------- /tutorial/18-buffers/makestring2.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.compat.Platform.currentTime 3 | 4 | def makestring(A: Array[Int]): String = { 5 | var s = new StringBuilder 6 | for (e <- A) { 7 | if (s.isEmpty) 8 | s ++= e.toString 9 | else 10 | s ++= ", " + e.toString 11 | } 12 | s.toString 13 | } 14 | 15 | val n = args(0).toInt 16 | val A = (1 to n).toArray 17 | 18 | println("Starting...") 19 | val t0 = currentTime 20 | val str = makestring(A) 21 | val t1 = currentTime 22 | // println(str) 23 | printf("Making a string of %d numbers took %d milliseconds\n", n, t1 - t0) 24 | -------------------------------------------------------------------------------- /tutorial/18-buffers/readwords1.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.compat.Platform.currentTime 3 | import scala.io.Source 4 | 5 | val fname = "words.txt" 6 | 7 | def readWords(): Array[String] = { 8 | val F = Source.fromFile(fname) 9 | var A = new Array[String](0) 10 | for (line <- F.getLines()) { 11 | A = A :+ line 12 | } 13 | A 14 | } 15 | 16 | println("Starting...") 17 | val t0 = currentTime 18 | val A = readWords() 19 | val t1 = currentTime 20 | printf("Reading all %d words took %d milliseconds\n", A.length, t1 - t0) 21 | 22 | println() 23 | println("The first ten words are:") 24 | for (i <- 0 until 10) 25 | println(A(i)) 26 | 27 | -------------------------------------------------------------------------------- /tutorial/18-buffers/readwords2.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.compat.Platform.currentTime 3 | import scala.io.Source 4 | 5 | val fname = "words.txt" 6 | 7 | def readWords(): Array[String] = { 8 | val F = Source.fromFile(fname) 9 | val A = new Array[String](200000) 10 | var count = 0 11 | for (line <- F.getLines()) { 12 | A(count) = line 13 | count += 1 14 | } 15 | val B = new Array[String](count) 16 | for (i <- 0 until count) 17 | B(i) = A(i) 18 | B 19 | } 20 | 21 | println("Starting...") 22 | val t0 = currentTime 23 | val A = readWords() 24 | val t1 = currentTime 25 | printf("Reading all %d words took %d milliseconds\n", A.length, t1 - t0) 26 | 27 | println() 28 | println("The first ten words are:") 29 | for (i <- 0 until 10) 30 | println(A(i)) 31 | 32 | -------------------------------------------------------------------------------- /tutorial/18-buffers/readwords3.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.compat.Platform.currentTime 3 | import scala.io.Source 4 | 5 | val fname = "words.txt" 6 | 7 | def readWords(): Array[String] = { 8 | val F = Source.fromFile(fname) 9 | var A = new scala.collection.mutable.ArrayBuffer[String] 10 | for (line <- F.getLines()) { 11 | A += line 12 | } 13 | A.toArray 14 | } 15 | 16 | println("Starting...") 17 | val t0 = currentTime 18 | val A = readWords() 19 | val t1 = currentTime 20 | printf("Reading all %d words took %d milliseconds\n", A.length, t1 - t0) 21 | 22 | println() 23 | println("The first ten words are:") 24 | for (i <- 0 until 10) 25 | println(A(i)) 26 | 27 | -------------------------------------------------------------------------------- /tutorial/30-maps/anagrams.scala: -------------------------------------------------------------------------------- 1 | 2 | val wordFile = "words.txt" 3 | 4 | def anagramMap(): Map[String, Set[String]] = { 5 | val words = scala.io.Source.fromFile(wordFile).getLines.toSet 6 | var m = scala.collection.mutable.Map[String, Set[String]]() 7 | for (word <- words) { 8 | val s = word.sorted 9 | if (m contains s) { 10 | m(s) += word 11 | } else 12 | m(s) = Set(word) 13 | } 14 | m.toMap 15 | } 16 | 17 | val anagrams = anagramMap() 18 | 19 | def findAnagrams(w: String): Set[String] = anagrams.getOrElse(w.sorted, Set()) 20 | 21 | def showLargeSets(k: Int, m: Int) { 22 | val b = new scala.collection.mutable.ArrayBuffer[String] 23 | for ((w, s) <- anagrams) { 24 | if (s.size >= k && w.length >= m) 25 | b += w 26 | } 27 | val a = b.toArray.sorted 28 | for (w <- a) 29 | println(anagrams(w) mkString ", ") 30 | } 31 | -------------------------------------------------------------------------------- /tutorial/30-maps/cmudict1.scala: -------------------------------------------------------------------------------- 1 | 2 | def readPronounciations(): Map[String,String] = { 3 | val F = scala.io.Source.fromFile("cmudict.txt") 4 | var M = Map[String,String]() 5 | for (l <- F.getLines()) { 6 | if (l(0).isLetter) { 7 | val p = l.trim.split("\\s+", 2) 8 | val word = p(0).toLowerCase 9 | if (!(word contains '(')) { 10 | val pro = p(1) 11 | M = M + (word -> pro) 12 | } 13 | } 14 | } 15 | M 16 | } 17 | 18 | def reverseMap(M: Map[String,String]): Map[String,Set[String]] = { 19 | var R = Map[String,Set[String]]() 20 | for ((word, pro) <- M) { 21 | val S = R.getOrElse(pro, Set()) 22 | R = R + (pro -> (S + word)) 23 | } 24 | R 25 | } 26 | 27 | def showHomophones1(k: Int) { 28 | val m = readPronounciations() 29 | var r = reverseMap(m) 30 | var homophones = r.toArray.sortWith((x,y) => x._2.size > y._2.size) 31 | for ((pro, words) <- homophones) { 32 | if (words.size >= k) { 33 | printf("%s (%d words):\n", pro, words.size) 34 | println(" " + words.mkString(" ")) 35 | } 36 | } 37 | } 38 | 39 | def showHomophones(k: Int) { 40 | val m = readPronounciations() 41 | var r = reverseMap(m) 42 | for ((pro, words) <- r) { 43 | if (words.size >= k) { 44 | printf("%s (%d words):\n", pro, words.size) 45 | println(" " + words.mkString(" ")) 46 | } 47 | } 48 | } 49 | 50 | def findWords() { 51 | val m = readPronounciations() 52 | for ((word, pro) <- m) { 53 | val ord = word.substring(1) 54 | if (pro == m.getOrElse(ord, "")) 55 | println(word) 56 | } 57 | } 58 | 59 | def solvePuzzle() { 60 | val m = readPronounciations() 61 | for ((word, pro) <- m) { 62 | if (word.length > 2 && word(0) != word(1)) { 63 | val ord1 = word.substring(1) 64 | val ord2 = word(0) + word.substring(2) 65 | if (pro == m.getOrElse(ord1, "") && 66 | pro == m.getOrElse(ord2, "")) 67 | println(word) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tutorial/30-maps/cmudict2.scala: -------------------------------------------------------------------------------- 1 | 2 | def readPronounciations(): Map[String,Set[String]] = { 3 | val F = scala.io.Source.fromFile("cmudict.txt") 4 | var M = Map[String,Set[String]]() 5 | for (l <- F.getLines()) { 6 | if (l(0).isLetter) { 7 | val p = l.trim.split("\\s+", 2) 8 | val i = p(0).indexOf('(') 9 | val word = (if (i >= 0) p(0).substring(0,i) else p(0)).toLowerCase 10 | val pro = p(1) 11 | val S = M.getOrElse(word, Set()) 12 | M = M + (word -> (S + pro)) 13 | } 14 | } 15 | M 16 | } 17 | 18 | def reverseMap(M: Map[String,Set[String]]): Map[String,Set[String]] = { 19 | var R = Map[String,Set[String]]() 20 | for ((key, vals) <- M) { 21 | for (w <- vals) { 22 | val S = R.getOrElse(w, Set()) 23 | R = R + (w -> (S + key)) 24 | } 25 | } 26 | R 27 | } 28 | 29 | def showHomophones() { 30 | val M = readPronounciations() 31 | var R = reverseMap(M) 32 | var homophones = List[Set[String]]() 33 | for ((pro, words) <- R) { 34 | if (words.size > 1) 35 | homophones = words :: homophones 36 | } 37 | homophones = homophones.sortWith((x, y) => x.size > y.size) 38 | var count = 0 39 | for (words <- homophones) { 40 | count += 1 41 | printf("Group %d (%d words):\n", count, words.size) 42 | println(" " + words.mkString(" ")) 43 | } 44 | } 45 | 46 | def findWords() { 47 | val M = readPronounciations() 48 | for ((word, pro1) <- M) { 49 | val ord = word.substring(1) 50 | if ((M contains ord) && (pro1 intersect M(ord)).nonEmpty) 51 | println(word) 52 | } 53 | } 54 | 55 | def solvePuzzle() { 56 | val M = readPronounciations() 57 | for ((word, pro1) <- M) { 58 | val ord = word.substring(1) 59 | val wor = word.substring(0, word.length-1) 60 | if ((M contains ord) && (M contains wor) && 61 | (pro1 intersect M(ord) intersect M(wor)).nonEmpty) 62 | println(word) 63 | } 64 | } 65 | 66 | // showHomophones() 67 | 68 | 69 | -------------------------------------------------------------------------------- /tutorial/30-maps/histogram1.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.collection.mutable.Map 3 | 4 | def histogram(fname: String): Map[String, Int] = { 5 | val F = scala.io.Source.fromFile(fname) 6 | val hist = Map[String, Int]() 7 | 8 | for (line <- F.getLines()) { 9 | if (line != "") { 10 | val words = line.split("[ ,:;.?!()-]+") 11 | for (word <- words) { 12 | val upword = word.toUpperCase 13 | if (hist contains upword) 14 | hist(upword) += 1 15 | else 16 | hist(upword) = 1 17 | } 18 | } 19 | } 20 | hist 21 | } 22 | 23 | if (args.length != 1) { 24 | println("Usage: scala histogram1.scala ") 25 | sys.exit(1) 26 | } 27 | 28 | val fname = args(0) 29 | val hist = histogram(fname) 30 | println(hist) 31 | -------------------------------------------------------------------------------- /tutorial/30-maps/histogram2.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.collection.mutable.Map 3 | 4 | def histogram(fname: String): Map[String, Int] = { 5 | val F = scala.io.Source.fromFile(fname) 6 | val hist = Map[String, Int]() 7 | 8 | for (line <- F.getLines()) { 9 | if (line != "") { 10 | val words = line.split("[ ,:;.?!()-]+") 11 | for (word <- words) { 12 | val upword = word.toUpperCase 13 | if (hist contains upword) 14 | hist(upword) += 1 15 | else 16 | hist(upword) = 1 17 | } 18 | } 19 | } 20 | hist 21 | } 22 | 23 | def printHistogram(h: Map[String, Int]) { 24 | for ((word, count) <- h) 25 | printf("%20s: %d\n", word, count) 26 | } 27 | 28 | if (args.length != 1) { 29 | println("Usage: scala histogram1.scala ") 30 | sys.exit(1) 31 | } 32 | 33 | val fname = args(0) 34 | val hist = histogram(fname) 35 | printHistogram(hist) 36 | -------------------------------------------------------------------------------- /tutorial/30-maps/histogram3.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.collection.mutable.Map 3 | 4 | def histogram(fname: String): Map[String, Int] = { 5 | val F = scala.io.Source.fromFile(fname) 6 | val hist = Map[String, Int]() 7 | 8 | for (line <- F.getLines()) { 9 | if (line != "") { 10 | val words = line.split("[ ,:;.?!()-]+") 11 | for (word <- words) { 12 | val upword = word.toUpperCase 13 | if (hist contains upword) 14 | hist(upword) += 1 15 | else 16 | hist(upword) = 1 17 | } 18 | } 19 | } 20 | hist 21 | } 22 | 23 | def printHistogram(h: Map[String, Int]) { 24 | val sorted = h.toArray.sorted 25 | for ((word, count) <- sorted) 26 | printf("%20s: %d\n", word, count) 27 | } 28 | 29 | if (args.length != 1) { 30 | println("Usage: scala histogram1.scala ") 31 | sys.exit(1) 32 | } 33 | 34 | val fname = args(0) 35 | val hist = histogram(fname) 36 | printHistogram(hist) 37 | -------------------------------------------------------------------------------- /tutorial/30-maps/histogram4.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.collection.mutable.Map 3 | 4 | def histogram(fname: String): Map[String, Int] = { 5 | val F = scala.io.Source.fromFile(fname) 6 | val hist = Map[String, Int]() 7 | 8 | for (line <- F.getLines()) { 9 | if (line != "") { 10 | val words = line.split("[ ,:;.?!()-]+") 11 | for (word <- words) { 12 | val upword = word.toUpperCase 13 | if (hist contains upword) 14 | hist(upword) += 1 15 | else 16 | hist(upword) = 1 17 | } 18 | } 19 | } 20 | hist 21 | } 22 | 23 | def printHistogram(h: Map[String, Int]) { 24 | val sorted = h.toArray.sortWith((x,y) => (x._2 > y._2)) 25 | for ((word, count) <- sorted) 26 | if (count > 1) 27 | printf("%20s: %d\n", word, count) 28 | } 29 | 30 | if (args.length != 1) { 31 | println("Usage: scala histogram1.scala ") 32 | sys.exit(1) 33 | } 34 | 35 | val fname = args(0) 36 | val hist = histogram(fname) 37 | printHistogram(hist) 38 | -------------------------------------------------------------------------------- /tutorial/30-maps/scala.txt: -------------------------------------------------------------------------------- 1 | In this course, I plan to use the Scala programming language. 2 | 3 | In my experience, students develop a style of programming in their 4 | first programming language. They find it difficult to learn a 5 | different style later, even if they switch to a different 6 | language. This means that students should start early to use a modern 7 | language that encourages writing clean and elegant code, and supports 8 | a good object-oriented and functional style. 9 | 10 | I therefore want to try using Scala this semester. Scala is not yet a 11 | popular or successful language (although I believe it will be), and so 12 | most students will have to learn C++ and/or Java later during 13 | their studies--but I believe that after getting programming practice 14 | in Scala, they will be able to write better code in those languages as 15 | well. 16 | 17 | -------------------------------------------------------------------------------- /tutorial/35-lists/readwords4.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.compat.Platform.currentTime 3 | import scala.io.Source 4 | 5 | val fname = "words.txt" 6 | 7 | def readWords(): List[String] = { 8 | val F = Source.fromFile(fname) 9 | var A = List[String]() 10 | for (line <- F.getLines()) { 11 | A = line :: A 12 | } 13 | A 14 | } 15 | 16 | println("Starting...") 17 | val t0 = currentTime 18 | val A = readWords() 19 | val t1 = currentTime 20 | printf("Reading all %d words took %d milliseconds\n", A.length, t1 - t0) 21 | 22 | println() 23 | println("The first ten words are:") 24 | for (i <- 0 until 10) 25 | println(A(i)) 26 | 27 | -------------------------------------------------------------------------------- /tutorial/35-lists/squarelist.scala: -------------------------------------------------------------------------------- 1 | def square(x: Int): Int = x * x 2 | 3 | def squareList(s: List[Int]): List[Int] = 4 | if (s == Nil) Nil else square(s.head) :: squareList(s.tail) 5 | 6 | -------------------------------------------------------------------------------- /tutorial/35-lists/squarelist2.scala: -------------------------------------------------------------------------------- 1 | def square(x: Int): Int = x * x 2 | 3 | def squareList(s: List[Int]): List[Int] = 4 | s match { 5 | case Nil => Nil 6 | case x :: xs => square(x) :: squareList(xs) 7 | } 8 | -------------------------------------------------------------------------------- /tutorial/45-higher-order/higher1.scala: -------------------------------------------------------------------------------- 1 | 2 | def cube(x: Int): Int = x * x * x 3 | 4 | def fact(x: Int): Int = { 5 | var f = 1 6 | for (i <- 1 to x) 7 | f *= i 8 | f 9 | } 10 | 11 | def sumInt(a: Int, b: Int): Int = { 12 | var s = 0 13 | for (i <- a to b) 14 | s += i 15 | s 16 | } 17 | 18 | def sumCubes(a: Int, b: Int): Int = { 19 | var s = 0 20 | for (i <- a to b) 21 | s += cube(i) 22 | s 23 | } 24 | 25 | def sumFact(a: Int, b: Int): Int = { 26 | var s = 0 27 | for (i <- a to b) 28 | s += fact(i) 29 | s 30 | } 31 | 32 | -------------------------------------------------------------------------------- /tutorial/45-higher-order/higher2.scala: -------------------------------------------------------------------------------- 1 | 2 | def id(x: Int): Int = x 3 | 4 | def cube(x: Int): Int = x * x * x 5 | 6 | def fact(x: Int): Int = { 7 | var f = 1 8 | for (i <- 1 to x) 9 | f *= i 10 | f 11 | } 12 | 13 | def sum(f: Int => Int, a: Int, b: Int): Int = { 14 | var s = 0 15 | for (i <- a to b) 16 | s += f(i) 17 | s 18 | } 19 | 20 | def sumInt(a: Int, b: Int): Int = sum(id, a, b) 21 | def sumCubes(a: Int, b: Int): Int = sum(cube, a, b) 22 | def sumFact(a: Int, b: Int): Int = sum(fact, a, b) 23 | 24 | -------------------------------------------------------------------------------- /tutorial/45-higher-order/higher3.scala: -------------------------------------------------------------------------------- 1 | 2 | def fact(x: Int): Int = { 3 | var f = 1 4 | for (i <- 1 to x) 5 | f *= i 6 | f 7 | } 8 | 9 | def sum(f: Int => Int, a: Int, b: Int): Int = { 10 | var s = 0 11 | for (i <- a to b) 12 | s += f(i) 13 | s 14 | } 15 | 16 | def sumInt(a: Int, b: Int): Int = sum((x: Int) => x, a, b) 17 | def sumCubes(a: Int, b: Int): Int = sum((x : Int) => x * x * x, a, b) 18 | def sumFact(a: Int, b: Int): Int = sum(fact, a, b) 19 | 20 | -------------------------------------------------------------------------------- /tutorial/45-higher-order/higher4.scala: -------------------------------------------------------------------------------- 1 | 2 | def fact(x: Int): Int = { 3 | var f = 1 4 | for (i <- 1 to x) 5 | f *= i 6 | f 7 | } 8 | 9 | def sum(f: Int => Int, a: Int, b: Int): Int = { 10 | var s = 0 11 | for (i <- a to b) 12 | s += f(i) 13 | s 14 | } 15 | 16 | def sumInt(a: Int, b: Int): Int = sum(x => x, a, b) 17 | def sumCubes(a: Int, b: Int): Int = sum(x => x * x * x, a, b) 18 | def sumFact(a: Int, b: Int): Int = sum(fact, a, b) 19 | 20 | -------------------------------------------------------------------------------- /tutorial/45-higher-order/integrate.scala: -------------------------------------------------------------------------------- 1 | 2 | val K = 100 // number of intervals to approximate 3 | 4 | def integrate(f: Double => Double, a: Double, b: Double): Double = { 5 | require(b > a) 6 | val delta = (b - a)/ K 7 | var total = 0.0 8 | var x = a 9 | for (i <- 1 to K) { 10 | total += (f(x) + f(x+delta)) * 0.5 * delta 11 | x += delta 12 | } 13 | total 14 | } 15 | -------------------------------------------------------------------------------- /tutorial/45-higher-order/primes.scala: -------------------------------------------------------------------------------- 1 | 2 | val n = args(0).toInt 3 | val sqrtn = math.sqrt(n).toInt 4 | 5 | var s = (2 to n).toList 6 | 7 | while (s.head < sqrtn) { 8 | print(s.head + " ") 9 | s = s.tail filter (_ % s.head != 0) 10 | } 11 | println(s mkString " ") 12 | -------------------------------------------------------------------------------- /tutorial/45-higher-order/table.scala: -------------------------------------------------------------------------------- 1 | 2 | def printTable(f: Int => Int, a: Int, b: Int) { 3 | for (i <- a to b) { 4 | printf("%4d: %d\n", i, f(i)) 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tutorial/50-objects/days1.scala: -------------------------------------------------------------------------------- 1 | 2 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 3 | 4 | class Date(val year: Int, val month: Int, val day: Int) { 5 | require(1901 <= year && year <= 2099) 6 | require(1 <= month && month <= 12) 7 | require(1 <= day && day <= monthLength(month - 1)) 8 | require(month != 2 || day <= 28 || (year % 4) == 0) 9 | } 10 | -------------------------------------------------------------------------------- /tutorial/50-objects/days2.scala: -------------------------------------------------------------------------------- 1 | 2 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 3 | 4 | class Date(val year: Int, val month: Int, val day: Int) { 5 | require(1901 <= year && year <= 2099) 6 | require(1 <= month && month <= 12) 7 | require(1 <= day && day <= monthLength(month - 1)) 8 | require(month != 2 || day <= 28 || (year % 4) == 0) 9 | 10 | // returns the number of days since 1901/01/01 (day 0) 11 | def dayIndex: Int = { 12 | val fourY = (365 + 365 + 365 + 366) 13 | val yearn = year - 1901 14 | var total = 0 15 | total += fourY * (yearn / 4) 16 | total += 365 * (yearn % 4) 17 | for (m <- 0 until month - 1) 18 | total += monthLength(m) 19 | total += day - 1 20 | if (year%4 != 0 && month > 2) 21 | total -= 1 22 | total 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tutorial/50-objects/days3.scala: -------------------------------------------------------------------------------- 1 | 2 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 3 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 4 | "Friday", "Saturday", "Sunday") 5 | 6 | class Date(val year: Int, val month: Int, val day: Int) { 7 | require(1901 <= year && year <= 2099) 8 | require(1 <= month && month <= 12) 9 | require(1 <= day && day <= monthLength(month - 1)) 10 | require(month != 2 || day <= 28 || (year % 4) == 0) 11 | 12 | // returns the number of days since 1901/01/01 (day 0) 13 | def dayIndex: Int = { 14 | val fourY = (365 + 365 + 365 + 366) 15 | val yearn = year - 1901 16 | var total = 0 17 | total += fourY * (yearn / 4) 18 | total += 365 * (yearn % 4) 19 | for (m <- 0 until month - 1) 20 | total += monthLength(m) 21 | total += day - 1 22 | if (year%4 != 0 && month > 2) 23 | total -= 1 24 | total 25 | } 26 | 27 | def dayOfWeek: String = weekday((dayIndex + 1) % 7) 28 | } 29 | -------------------------------------------------------------------------------- /tutorial/50-objects/days4.scala: -------------------------------------------------------------------------------- 1 | 2 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 3 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 4 | "Friday", "Saturday", "Sunday") 5 | val monthname = Array("January", "February", "March", 6 | "April", "May", "June", 7 | "July", "August", "September", 8 | "October", "November", "December") 9 | 10 | class Date(val year: Int, val month: Int, val day: Int) { 11 | require(1901 <= year && year <= 2099) 12 | require(1 <= month && month <= 12) 13 | require(1 <= day && day <= monthLength(month - 1)) 14 | require(month != 2 || day <= 28 || (year % 4) == 0) 15 | 16 | // returns the number of days since 1901/01/01 (day 0) 17 | def dayIndex: Int = { 18 | val fourY = (365 + 365 + 365 + 366) 19 | val yearn = year - 1901 20 | var total = 0 21 | total += fourY * (yearn / 4) 22 | total += 365 * (yearn % 4) 23 | for (m <- 0 until month - 1) 24 | total += monthLength(m) 25 | total += day - 1 26 | if (year%4 != 0 && month > 2) 27 | total -= 1 28 | total 29 | } 30 | 31 | def dayOfWeek: String = weekday((dayIndex + 1) % 7) 32 | 33 | override def toString: String = 34 | "%s, %s %d, %d".format(dayOfWeek, 35 | monthname(month-1), 36 | day, 37 | year) 38 | } 39 | -------------------------------------------------------------------------------- /tutorial/50-objects/days5.scala: -------------------------------------------------------------------------------- 1 | 2 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 3 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 4 | "Friday", "Saturday", "Sunday") 5 | val monthname = Array("January", "February", "March", 6 | "April", "May", "June", 7 | "July", "August", "September", 8 | "October", "November", "December") 9 | 10 | class Date(val year: Int, val month: Int, val day: Int) { 11 | require(1901 <= year && year <= 2099) 12 | require(1 <= month && month <= 12) 13 | require(1 <= day && day <= monthLength(month - 1)) 14 | require(month != 2 || day <= 28 || (year % 4) == 0) 15 | 16 | // returns the number of days since 1901/01/01 (day 0) 17 | def dayIndex: Int = { 18 | val fourY = (365 + 365 + 365 + 366) 19 | val yearn = year - 1901 20 | var total = 0 21 | total += fourY * (yearn / 4) 22 | total += 365 * (yearn % 4) 23 | for (m <- 0 until month - 1) 24 | total += monthLength(m) 25 | total += day - 1 26 | if (year%4 != 0 && month > 2) 27 | total -= 1 28 | total 29 | } 30 | 31 | def dayOfWeek: String = weekday((dayIndex + 1) % 7) 32 | 33 | override def toString: String = 34 | "%s, %s %d, %d".format(dayOfWeek, 35 | monthname(month-1), 36 | day, 37 | year) 38 | 39 | def diff(rhs: Date) = dayIndex - rhs.dayIndex 40 | } 41 | -------------------------------------------------------------------------------- /tutorial/50-objects/days6.scala: -------------------------------------------------------------------------------- 1 | 2 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 3 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 4 | "Friday", "Saturday", "Sunday") 5 | val monthname = Array("January", "February", "March", 6 | "April", "May", "June", 7 | "July", "August", "September", 8 | "October", "November", "December") 9 | 10 | class Date(val year: Int, val month: Int, val day: Int) { 11 | require(1901 <= year && year <= 2099) 12 | require(1 <= month && month <= 12) 13 | require(1 <= day && day <= monthLength(month - 1)) 14 | require(month != 2 || day <= 28 || (year % 4) == 0) 15 | 16 | // returns the number of days since 1901/01/01 (day 0) 17 | def dayIndex: Int = { 18 | val fourY = (365 + 365 + 365 + 366) 19 | val yearn = year - 1901 20 | var total = 0 21 | total += fourY * (yearn / 4) 22 | total += 365 * (yearn % 4) 23 | for (m <- 0 until month - 1) 24 | total += monthLength(m) 25 | total += day - 1 26 | if (year%4 != 0 && month > 2) 27 | total -= 1 28 | total 29 | } 30 | 31 | def dayOfWeek: String = weekday((dayIndex + 1) % 7) 32 | 33 | override def toString: String = 34 | "%s, %s %d, %d".format(dayOfWeek, 35 | monthname(month-1), 36 | day, 37 | year) 38 | 39 | def -(rhs: Date) = dayIndex - rhs.dayIndex 40 | } 41 | -------------------------------------------------------------------------------- /tutorial/50-objects/days7.scala: -------------------------------------------------------------------------------- 1 | 2 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 3 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 4 | "Friday", "Saturday", "Sunday") 5 | val monthname = Array("January", "February", "March", 6 | "April", "May", "June", 7 | "July", "August", "September", 8 | "October", "November", "December") 9 | 10 | class Date(val year: Int, val month: Int, val day: Int) { 11 | require(1901 <= year && year <= 2099) 12 | require(1 <= month && month <= 12) 13 | require(1 <= day && day <= monthLength(month - 1)) 14 | require(month != 2 || day <= 28 || (year % 4) == 0) 15 | 16 | // returns the number of days since 1901/01/01 (day 0) 17 | def dayIndex: Int = { 18 | val fourY = (365 + 365 + 365 + 366) 19 | val yearn = year - 1901 20 | var total = 0 21 | total += fourY * (yearn / 4) 22 | total += 365 * (yearn % 4) 23 | for (m <- 0 until month - 1) 24 | total += monthLength(m) 25 | total += day - 1 26 | if (year % 4 != 0 && month > 2) 27 | total -= 1 28 | total 29 | } 30 | 31 | def dayOfWeek: String = weekday((dayIndex + 1) % 7) 32 | 33 | override def toString: String = 34 | "%s, %s %d, %d".format(dayOfWeek, 35 | monthname(month-1), 36 | day, 37 | year) 38 | 39 | def num2date(n: Int): Date = { 40 | val fourY = (365 + 365 + 365 + 366) 41 | var year = 1901 + (n / fourY) * 4 42 | var day = n % fourY 43 | if (day >= 365 + 365 + 365 + 59) { 44 | year += 3 45 | day -= 365 + 365 + 365 46 | } else { 47 | year += (day / 365) 48 | day = day % 365 49 | if (day >= 59) 50 | day += 1 51 | } 52 | var month = 1 53 | while (day >= monthLength(month-1)) { 54 | day -= monthLength(month-1) 55 | month += 1 56 | } 57 | new Date(year, month, day+1) 58 | } 59 | 60 | def -(rhs: Date) = dayIndex - rhs.dayIndex 61 | 62 | def +(n: Int): Date = num2date(dayIndex + n) 63 | def -(n: Int): Date = num2date(dayIndex - n) 64 | } 65 | 66 | def testDays() { 67 | val maxDate = new Date(2099, 12, 31) 68 | val maxDay = maxDate.dayIndex 69 | var s = scala.collection.mutable.Set.empty[Date] 70 | for (i <- 0 to maxDay) { 71 | val d = maxDate.num2date(i) 72 | s += d 73 | assert(i == d.dayIndex, i) 74 | } 75 | println(s.size) 76 | } 77 | -------------------------------------------------------------------------------- /tutorial/55-objects/accum1.scala: -------------------------------------------------------------------------------- 1 | class Accumulator { 2 | var sum = 0 3 | def add(n: Int) { 4 | sum += n 5 | } 6 | } 7 | 8 | var acc1 = new Accumulator 9 | acc1.add(7) 10 | acc1.add(13) 11 | println(acc1.sum) 12 | -------------------------------------------------------------------------------- /tutorial/55-objects/accum2.scala: -------------------------------------------------------------------------------- 1 | class Accumulator { 2 | private var current = 0 3 | def add(n: Int) { 4 | current += n 5 | } 6 | def sum: Int = current 7 | } 8 | 9 | var acc1 = new Accumulator 10 | acc1.add(7) 11 | acc1.add(13) 12 | println(acc1.sum) 13 | 14 | -------------------------------------------------------------------------------- /tutorial/55-objects/blackjack-game.scala: -------------------------------------------------------------------------------- 1 | 2 | val Suits = Array("Clubs", "Spades", "Hearts", "Diamonds") 3 | val Faces = Array("2", "3", "4", "5", "6", "7", "8", "9", "10", 4 | "Jack", "Queen", "King", "Ace") 5 | 6 | class Card(val face: String, val suit: String) { 7 | require(Suits contains suit) 8 | require(Faces contains face) 9 | 10 | override def toString: String = { 11 | val a = if (face == "Ace" || face == "8") "an " else "a " 12 | a + face + " of " + suit 13 | } 14 | 15 | def value: Int = face match { 16 | case "Ace" => 11 17 | case "Jack" => 10 18 | case "Queen" => 10 19 | case "King" => 10 20 | case _ => face.toInt 21 | } 22 | } 23 | 24 | class Deck { 25 | private val cards = new Array[Card](52) 26 | private var count = 52 27 | generateDeck() 28 | shuffleDeck() 29 | 30 | private def generateDeck() { 31 | var i = 0 32 | for (suit <- Suits) { 33 | for (face <- Faces) { 34 | cards(i) = new Card(face, suit) 35 | i += 1 36 | } 37 | } 38 | } 39 | private def shuffleDeck() { 40 | for (i <- 1 to 52) { 41 | // 0..i-2 already shuffled 42 | val j = (math.random * i).toInt 43 | val cj = cards(j) 44 | cards(j) = cards(i-1) 45 | cards(i-1) = cj 46 | } 47 | } 48 | def draw(): Card = { 49 | assert(count > 0) 50 | count -= 1 51 | cards(count) 52 | } 53 | } 54 | 55 | // Compute the value of a hand of cards. 56 | def handValue(hand: Array[Card]): Int = { 57 | var value = 0 58 | for (card <- hand) 59 | value += card.value 60 | value 61 | } 62 | 63 | /* Display the text prompt and let's the user enter a string. If the 64 | user enters "y", the function returns "true", and if the user enters 65 | "n", the function returns "false" If the user enters anything else, 66 | the function prints "I beg your pardon!", and asks again, repeating 67 | this until the user has entered a correct string. */ 68 | def askYesNo(prompt: String): Boolean = { 69 | while (true) { 70 | val user_input = readLine(prompt) 71 | user_input match { 72 | case "y" => return true 73 | case "n" => return false 74 | case _ => println("I beg your pardon!") 75 | } 76 | } 77 | true // to make compiler happy 78 | } 79 | 80 | // Play one round of Blackjack 81 | // Returns 1 if player wins, -1 if dealer wins, and 0 for a tie. 82 | def blackjack(): Int = { 83 | val deck = new Deck() 84 | 85 | // initial cards 86 | var player = Array(deck.draw()) 87 | println("You are dealt " + player.head) 88 | var dealer = Array(deck.draw()) 89 | println("Dealer is dealt a hidden card") 90 | 91 | player = player :+ deck.draw() 92 | println("You are dealt " + player.last) 93 | dealer = dealer :+ deck.draw() 94 | println("Dealer is dealt " + dealer.last) 95 | printf("Your total is %d\n", handValue(player)) 96 | 97 | // player's turn to draw cards 98 | var want = true 99 | while (want && handValue(player) < 21) { 100 | want = askYesNo("Would you like another card? (y/n) ") 101 | if (want) { 102 | player = player :+ deck.draw() 103 | println("You are dealt " + player.last) 104 | printf("Your total is %d\n", handValue(player)) 105 | 106 | // if the player's score is over 21, the player loses immediately. 107 | if (handValue(player) > 21) { 108 | println("You went over 21! You lost!") 109 | return -1 110 | } 111 | } 112 | } 113 | 114 | println("The dealer's hidden card was " + dealer.head) 115 | while (handValue(dealer) < 17) { 116 | dealer = dealer :+ deck.draw() 117 | println("Dealer is dealt " + dealer.last) 118 | } 119 | printf("The dealer's total is %d\n", handValue(dealer)) 120 | 121 | // summary 122 | val player_total = handValue(player) 123 | val dealer_total = handValue(dealer) 124 | printf("\nYour total is %d\n", player_total) 125 | printf("The dealer's total is %d\n", dealer_total) 126 | 127 | if (dealer_total > 21) { 128 | println("The dealer went over 21! You win!") 129 | 1 130 | } else if (player_total > dealer_total) { 131 | println("You win!") 132 | 1 133 | } else if (player_total < dealer_total) { 134 | println("You lost!") 135 | -1 136 | } else { 137 | println("You have a tie!") 138 | 0 139 | } 140 | } 141 | 142 | def gameLoop() { 143 | println("Welcome to Blackjack!") 144 | while (true) { 145 | println() 146 | blackjack() 147 | if (!askYesNo("\nPlay another round? (y/n) ")) 148 | return 149 | } 150 | } 151 | 152 | gameLoop() 153 | -------------------------------------------------------------------------------- /tutorial/55-objects/blackjack1.scala: -------------------------------------------------------------------------------- 1 | 2 | val Suits = Array("Clubs", "Spades", "Hearts", "Diamonds") 3 | val Faces = Array("2", "3", "4", "5", "6", "7", "8", "9", "10", 4 | "Jack", "Queen", "King", "Ace") 5 | 6 | class Card(val face: String, val suit: String) { 7 | require(Suits contains suit) 8 | require(Faces contains face) 9 | 10 | override def toString: String = { 11 | val a = if (face == "Ace" || face == "8") "an " else "a " 12 | a + face + " of " + suit 13 | } 14 | 15 | def value: Int = face match { 16 | case "Ace" => 11 17 | case "Jack" => 10 18 | case "Queen" => 10 19 | case "King" => 10 20 | case _ => face.toInt 21 | } 22 | } 23 | 24 | val c1 = new Card("Ace", "Diamonds") 25 | val c2 = new Card("Jack", "Spades") 26 | val c3 = new Card("8", "Hearts") 27 | 28 | val hand = Array(c1, c2, c3) 29 | 30 | for (c <- hand) 31 | printf("Card %s has value %d\n", c, c.value) 32 | -------------------------------------------------------------------------------- /tutorial/55-objects/blackjack2.scala: -------------------------------------------------------------------------------- 1 | 2 | val Suits = Array("Clubs", "Spades", "Hearts", "Diamonds") 3 | val Faces = Array("2", "3", "4", "5", "6", "7", "8", "9", "10", 4 | "Jack", "Queen", "King", "Ace") 5 | 6 | class Card(val face: String, val suit: String) { 7 | require(Suits contains suit) 8 | require(Faces contains face) 9 | 10 | override def toString: String = { 11 | val a = if (face == "Ace" || face == "8") "an " else "a " 12 | a + face + " of " + suit 13 | } 14 | 15 | def value: Int = face match { 16 | case "Ace" => 11 17 | case "Jack" => 10 18 | case "Queen" => 10 19 | case "King" => 10 20 | case _ => face.toInt 21 | } 22 | } 23 | 24 | class Deck { 25 | private val cards = new Array[Card](52) 26 | private var count = 52 27 | generateDeck() 28 | shuffleDeck() 29 | 30 | private def generateDeck() { 31 | var i = 0 32 | for (suit <- Suits) { 33 | for (face <- Faces) { 34 | cards(i) = new Card(face, suit) 35 | i += 1 36 | } 37 | } 38 | } 39 | private def shuffleDeck() { 40 | for (i <- 1 to 52) { 41 | // 0..i-2 already shuffled 42 | val j = (math.random * i).toInt 43 | val cj = cards(j) 44 | cards(j) = cards(i-1) 45 | cards(i-1) = cj 46 | } 47 | } 48 | 49 | def draw(): Card = { 50 | assert(count > 0) 51 | count -= 1 52 | cards(count) 53 | } 54 | } 55 | 56 | val deck = new Deck 57 | for (i <- 1 to 10) 58 | println(deck.draw()) 59 | 60 | -------------------------------------------------------------------------------- /tutorial/55-objects/blackjack3.scala: -------------------------------------------------------------------------------- 1 | 2 | val Suits = Array("Clubs", "Spades", "Hearts", "Diamonds") 3 | val Faces = Array("2", "3", "4", "5", "6", "7", "8", "9", "10", 4 | "Jack", "Queen", "King", "Ace") 5 | 6 | class Card(val face: String, val suit: String) { 7 | require(Suits contains suit) 8 | require(Faces contains face) 9 | 10 | override def toString: String = { 11 | val a = if (face == "Ace" || 12 | face == "8") 13 | "an " else "a " 14 | a + face + " of " + suit 15 | } 16 | 17 | def value: Int = face match { 18 | case "Ace" => 11 19 | case "Jack" => 10 20 | case "Queen" => 10 21 | case "King" => 10 22 | case _ => face.toInt 23 | } 24 | } 25 | 26 | class Deck { 27 | private val cards = new Array[Card](52) 28 | private var count = 52 29 | generateDeck() 30 | shuffleDeck() 31 | 32 | private def generateDeck() { 33 | var i = 0 34 | for (suit <- Suits) { 35 | for (face <- Faces) { 36 | cards(i) = new Card(face, suit) 37 | i += 1 38 | } 39 | } 40 | } 41 | 42 | private def shuffleDeck() { 43 | for (i <- 1 to 52) { 44 | // 0..i-2 already shuffled 45 | val j = (math.random * i).toInt 46 | val cj = cards(j) 47 | cards(j) = cards(i-1) 48 | cards(i-1) = cj 49 | } 50 | } 51 | 52 | def draw(): Card = { 53 | assert(count > 0) 54 | count -= 1 55 | cards(count) 56 | } 57 | 58 | def draw(n: Int): Array[Card] = { 59 | require(n <= count) 60 | val A = new Array[Card](n) 61 | for (i <- 0 until n) 62 | A(i) = draw() 63 | A 64 | } 65 | 66 | def draw(A: Array[Card]) { 67 | require(A.length <= count) 68 | for (i <- 0 until A.length) 69 | A(i) = draw() 70 | } 71 | } 72 | 73 | val deck = new Deck 74 | for (i <- 1 to 10) 75 | println(deck.draw()) 76 | println() 77 | val hand1 = deck.draw(5) 78 | for (card <- hand1) 79 | println(card) 80 | println() 81 | val hand2 = new Array[Card](5) 82 | deck.draw(hand2) 83 | for (card <- hand2) 84 | println(card) 85 | -------------------------------------------------------------------------------- /tutorial/55-objects/rectangle1.scala: -------------------------------------------------------------------------------- 1 | 2 | class Point(val x: Int, val y: Int) { 3 | override def toString: String = "(%d, %d)".format(x, y) 4 | } 5 | 6 | class Rect(var corner: Point, var width: Int, var height: Int) { 7 | require(width > 0 && height > 0) 8 | override def toString: String = 9 | "[%d ~ %d, %d ~ %d]".format(corner.x, corner.x + width, 10 | corner.y, corner.y + height) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /tutorial/55-objects/rectangle2.scala: -------------------------------------------------------------------------------- 1 | 2 | class Point(val x: Int, val y: Int) { 3 | override def toString: String = "(%d, %d)".format(x, y) 4 | } 5 | 6 | class Rect(x: Int, y: Int, var width: Int, var height: Int) { 7 | require(width > 0 && height > 0) 8 | var corner = new Point(x, y) 9 | override def toString: String = 10 | "[%d ~ %d, %d ~ %d]".format(corner.x, corner.x + width, 11 | corner.y, corner.y + height) 12 | } 13 | 14 | -------------------------------------------------------------------------------- /tutorial/56-dads-puzzle/puzzle1.scala: -------------------------------------------------------------------------------- 1 | 2 | val NRows = 5 3 | val NCols = 4 4 | val NSubrows = 3 5 | val NSubcols = 5 6 | 7 | class Block(val width: Int, val height: Int, 8 | val x: Int, val y: Int) { 9 | 10 | override def toString: String = 11 | "Block(%d, %d) @ (%d, %d)".format(width, height, x, y) 12 | 13 | def draw(row: Int, col: Int, subrow: Int): Boolean = { 14 | if (col < x || x + width <= col || 15 | row < y || y + height <= row) 16 | false 17 | else { 18 | val top = (subrow == 0 && row == y + height - 1) 19 | val bottom = (subrow == NSubrows-1 && row == y) 20 | val left = (col == x) 21 | val right = (col == x + width - 1) 22 | if (top || bottom) { 23 | print(if (left) "+" else "-") 24 | print("-" * (NSubcols - 2)) 25 | print(if (right) "+" else "-") 26 | } else { 27 | print(if (left) "|" else " ") 28 | print(" " * (NSubcols - 2)) 29 | print(if (right) "|" else " ") 30 | } 31 | true 32 | } 33 | } 34 | } 35 | 36 | class Board { 37 | val blocks = new Array[Block](9) 38 | blocks(0) = new Block(2, 2, 0, 3) 39 | blocks(1) = new Block(2, 1, 2, 4) 40 | blocks(2) = new Block(2, 1, 2, 3) 41 | blocks(3) = new Block(2, 1, 2, 1) 42 | blocks(4) = new Block(2, 1, 2, 0) 43 | blocks(5) = new Block(1, 1, 0, 2) 44 | blocks(6) = new Block(1, 1, 1, 2) 45 | blocks(7) = new Block(1, 2, 0, 0) 46 | blocks(8) = new Block(1, 2, 1, 0) 47 | 48 | def draw() { 49 | for (row <- NRows - 1 to 0 by -1) { 50 | for (subrow <- 0 until NSubrows) { 51 | for (col <- 0 until NCols) { 52 | if (!blocks.exists(x => x.draw(row, col, subrow))) 53 | print(" " * NSubcols) 54 | } 55 | println() 56 | } 57 | } 58 | } 59 | } 60 | 61 | val board = new Board 62 | board.draw() 63 | -------------------------------------------------------------------------------- /tutorial/56-dads-puzzle/puzzle2.scala: -------------------------------------------------------------------------------- 1 | 2 | val NRows = 5 3 | val NCols = 4 4 | val NSubrows = 3 5 | val NSubcols = 5 6 | 7 | class Block(val width: Int, val height: Int, 8 | val x: Int, val y: Int) { 9 | 10 | override def toString: String = 11 | "Block(%d, %d) @ (%d, %d)".format(width, height, x, y) 12 | 13 | def draw(row: Int, col: Int, subrow: Int): Boolean = { 14 | if (col < x || x + width <= col || 15 | row < y || y + height <= row) 16 | false 17 | else { 18 | val top = (subrow == 0 && row == y + height - 1) 19 | val bottom = (subrow == NSubrows-1 && row == y) 20 | val left = (col == x) 21 | val right = (col == x + width - 1) 22 | if (top || bottom) { 23 | print(if (left) "+" else "-") 24 | print("-" * (NSubcols - 2)) 25 | print(if (right) "+" else "-") 26 | } else { 27 | print(if (left) "|" else " ") 28 | print(" " * (NSubcols - 2)) 29 | print(if (right) "|" else " ") 30 | } 31 | true 32 | } 33 | } 34 | 35 | def canMove(dir: (Int, Int)): Boolean = { 36 | val (dx, dy) = dir 37 | (0 <= x + dx && x + width + dx <= NCols && 38 | 0 <= y + dy && y + height + dy <= NRows) 39 | } 40 | 41 | def move(dir: (Int, Int)): Block = { 42 | require(canMove(dir)) 43 | val (dx, dy) = dir 44 | new Block(width, height, x + dx, y + dy) 45 | } 46 | } 47 | 48 | class Board { 49 | val blocks = new Array[Block](9) 50 | blocks(0) = new Block(2, 2, 0, 3) 51 | blocks(1) = new Block(2, 1, 2, 4) 52 | blocks(2) = new Block(2, 1, 2, 3) 53 | blocks(3) = new Block(2, 1, 2, 1) 54 | blocks(4) = new Block(2, 1, 2, 0) 55 | blocks(5) = new Block(1, 1, 0, 2) 56 | blocks(6) = new Block(1, 1, 1, 2) 57 | blocks(7) = new Block(1, 2, 0, 0) 58 | blocks(8) = new Block(1, 2, 1, 0) 59 | 60 | def draw() { 61 | for (row <- NRows - 1 to 0 by -1) { 62 | for (subrow <- 0 until NSubrows) { 63 | for (col <- 0 until NCols) { 64 | if (!blocks.exists(x => x.draw(row, col, subrow))) 65 | print(" " * NSubcols) 66 | } 67 | println() 68 | } 69 | } 70 | } 71 | } 72 | 73 | val board = new Board 74 | board.draw() 75 | println() 76 | board.blocks(3) = board.blocks(3).move((0,1)) 77 | board.draw() 78 | -------------------------------------------------------------------------------- /tutorial/56-dads-puzzle/puzzle3.scala: -------------------------------------------------------------------------------- 1 | 2 | val NRows = 5 3 | val NCols = 4 4 | val NSubrows = 3 5 | val NSubcols = 5 6 | 7 | class Block(val width: Int, val height: Int, 8 | val x: Int, val y: Int) { 9 | 10 | override def toString: String = 11 | "Block(%d, %d) @ (%d, %d)".format(width, height, x, y) 12 | 13 | def draw(row: Int, col: Int, subrow: Int): Boolean = { 14 | if (col < x || x + width <= col || 15 | row < y || y + height <= row) 16 | false 17 | else { 18 | val top = (subrow == 0 && row == y + height - 1) 19 | val bottom = (subrow == NSubrows-1 && row == y) 20 | val left = (col == x) 21 | val right = (col == x + width - 1) 22 | if (top || bottom) { 23 | print(if (left) "+" else "-") 24 | print("-" * (NSubcols - 2)) 25 | print(if (right) "+" else "-") 26 | } else { 27 | print(if (left) "|" else " ") 28 | print(" " * (NSubcols - 2)) 29 | print(if (right) "|" else " ") 30 | } 31 | true 32 | } 33 | } 34 | 35 | def canMove(dir: (Int, Int)): Boolean = { 36 | val (dx, dy) = dir 37 | (0 <= x + dx && x + width + dx <= NCols && 38 | 0 <= y + dy && y + height + dy <= NRows) 39 | } 40 | 41 | def move(dir: (Int, Int)): Block = { 42 | require(canMove(dir)) 43 | val (dx, dy) = dir 44 | new Block(width, height, x + dx, y + dy) 45 | } 46 | 47 | def overlaps(other: Block): Boolean = 48 | !(x + width <= other.x || x >= other.x + other.width || 49 | y + height <= other.y || y >= other.y + other.height) 50 | } 51 | 52 | class Board { 53 | val blocks = new Array[Block](9) 54 | blocks(0) = new Block(2, 2, 0, 3) 55 | blocks(1) = new Block(2, 1, 2, 4) 56 | blocks(2) = new Block(2, 1, 2, 3) 57 | blocks(3) = new Block(2, 1, 2, 1) 58 | blocks(4) = new Block(2, 1, 2, 0) 59 | blocks(5) = new Block(1, 1, 0, 2) 60 | blocks(6) = new Block(1, 1, 1, 2) 61 | blocks(7) = new Block(1, 2, 0, 0) 62 | blocks(8) = new Block(1, 2, 1, 0) 63 | 64 | def draw() { 65 | for (row <- NRows - 1 to 0 by -1) { 66 | for (subrow <- 0 until NSubrows) { 67 | for (col <- 0 until NCols) { 68 | if (!blocks.exists(x => x.draw(row, col, subrow))) 69 | print(" " * NSubcols) 70 | } 71 | println() 72 | } 73 | } 74 | } 75 | 76 | def canMove(b: Block, dir: (Int, Int)): Boolean = { 77 | b.canMove(dir) && { 78 | val bm = b.move(dir) 79 | !blocks.exists(x => x != b && bm.overlaps(x)) 80 | } 81 | } 82 | } 83 | 84 | val board = new Board 85 | board.draw() 86 | for (dir <- List((1,0), (-1, 0), (0, 1), (0, -1))) { 87 | for (i <- 0 until 9) 88 | println("Block %d can move in dir %s: %s".format 89 | (i, dir, board.canMove(board.blocks(i), dir))) 90 | } 91 | 92 | -------------------------------------------------------------------------------- /tutorial/56-dads-puzzle/puzzle4.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.io.StdIn.readLine 3 | 4 | val NRows = 5 5 | val NCols = 4 6 | val NSubrows = 3 7 | val NSubcols = 5 8 | 9 | class Block(val width: Int, val height: Int, 10 | val x: Int, val y: Int) { 11 | 12 | override def toString: String = 13 | "Block(%d, %d) @ (%d, %d)".format(width, height, x, y) 14 | 15 | def draw(row: Int, col: Int, subrow: Int): Boolean = { 16 | if (col < x || x + width <= col || 17 | row < y || y + height <= row) 18 | false 19 | else { 20 | val top = (subrow == 0 && row == y + height - 1) 21 | val bottom = (subrow == NSubrows-1 && row == y) 22 | val left = (col == x) 23 | val right = (col == x + width - 1) 24 | if (top || bottom) { 25 | print(if (left) "+" else "-") 26 | print("-" * (NSubcols - 2)) 27 | print(if (right) "+" else "-") 28 | } else { 29 | print(if (left) "|" else " ") 30 | print(" " * (NSubcols - 2)) 31 | print(if (right) "|" else " ") 32 | } 33 | true 34 | } 35 | } 36 | 37 | def canMove(dir: (Int, Int)): Boolean = { 38 | val (dx, dy) = dir 39 | (0 <= x + dx && x + width + dx <= NCols && 40 | 0 <= y + dy && y + height + dy <= NRows) 41 | } 42 | 43 | def move(dir: (Int, Int)): Block = { 44 | require(canMove(dir)) 45 | val (dx, dy) = dir 46 | new Block(width, height, x + dx, y + dy) 47 | } 48 | 49 | def overlaps(other: Block): Boolean = 50 | !(x + width <= other.x || x >= other.x + other.width || 51 | y + height <= other.y || y >= other.y + other.height) 52 | } 53 | 54 | class Board { 55 | val blocks = new Array[Block](9) 56 | blocks(0) = new Block(2, 2, 0, 3) 57 | blocks(1) = new Block(2, 1, 2, 4) 58 | blocks(2) = new Block(2, 1, 2, 3) 59 | blocks(3) = new Block(2, 1, 2, 1) 60 | blocks(4) = new Block(2, 1, 2, 0) 61 | blocks(5) = new Block(1, 1, 0, 2) 62 | blocks(6) = new Block(1, 1, 1, 2) 63 | blocks(7) = new Block(1, 2, 0, 0) 64 | blocks(8) = new Block(1, 2, 1, 0) 65 | 66 | def draw() { 67 | for (row <- NRows - 1 to 0 by -1) { 68 | for (subrow <- 0 until NSubrows) { 69 | for (col <- 0 until NCols) { 70 | if (!blocks.exists(x => x.draw(row, col, subrow))) 71 | print(" " * NSubcols) 72 | } 73 | println() 74 | } 75 | } 76 | } 77 | 78 | def canMove(b: Block, dir: (Int, Int)): Boolean = { 79 | b.canMove(dir) && { 80 | val bm = b.move(dir) 81 | !blocks.exists(x => x != b && bm.overlaps(x)) 82 | } 83 | } 84 | 85 | def done: Boolean = (blocks(0).x == 0 && blocks(0).y == 0) 86 | 87 | def update(dir: (Int, Int)) { 88 | val can = blocks map (x => canMove(x, dir)) 89 | for (i <- 0 until blocks.length) { 90 | if (can(i)) 91 | blocks(i) = blocks(i).move(dir) 92 | } 93 | } 94 | } 95 | 96 | def askDirection(prompt: String): (Int, Int) = { 97 | while (true) { 98 | val user_input = readLine(prompt) 99 | user_input.toLowerCase match { 100 | case "x" => sys.exit(0) 101 | case "l" => return (-1, 0) 102 | case "r" => return (1, 0) 103 | case "u" => return (0, 1) 104 | case "d" => return (0, -1) 105 | case _ => println("I beg your pardon!") 106 | } 107 | } 108 | (0, 0) // to make compiler happy 109 | } 110 | 111 | 112 | def main() { 113 | val board = new Board 114 | while (!board.done) { 115 | board.draw() 116 | val dir = askDirection("Which way do you want to move (u/d/l/r)? ") 117 | board.update(dir) 118 | } 119 | println("Congratulations!") 120 | } 121 | 122 | main() 123 | -------------------------------------------------------------------------------- /tutorial/56-dads-puzzle/puzzle5.scala: -------------------------------------------------------------------------------- 1 | 2 | import scala.io.StdIn.readLine 3 | 4 | val NRows = 5 5 | val NCols = 4 6 | val NSubrows = 3 7 | val NSubcols = 5 8 | 9 | class Block(val width: Int, val height: Int, 10 | val x: Int, val y: Int) { 11 | 12 | override def toString: String = 13 | "Block(%d, %d) @ (%d, %d)".format(width, height, x, y) 14 | 15 | def draw(row: Int, col: Int, subrow: Int): Boolean = { 16 | if (col < x || x + width <= col || 17 | row < y || y + height <= row) 18 | false 19 | else { 20 | val top = (subrow == 0 && row == y + height - 1) 21 | val bottom = (subrow == NSubrows-1 && row == y) 22 | val left = (col == x) 23 | val right = (col == x + width - 1) 24 | if (top || bottom) { 25 | print(if (left) "+" else "-") 26 | print("-" * (NSubcols - 2)) 27 | print(if (right) "+" else "-") 28 | } else { 29 | print(if (left) "|" else " ") 30 | print(" " * (NSubcols - 2)) 31 | print(if (right) "|" else " ") 32 | } 33 | true 34 | } 35 | } 36 | 37 | def canMove(dir: (Int, Int)): Boolean = { 38 | val (dx, dy) = dir 39 | (0 <= x + dx && x + width + dx <= NCols && 40 | 0 <= y + dy && y + height + dy <= NRows) 41 | } 42 | 43 | def move(dir: (Int, Int)): Block = { 44 | require(canMove(dir)) 45 | val (dx, dy) = dir 46 | new Block(width, height, x + dx, y + dy) 47 | } 48 | 49 | def overlaps(other: Block): Boolean = 50 | !(x + width <= other.x || x >= other.x + other.width || 51 | y + height <= other.y || y >= other.y + other.height) 52 | } 53 | 54 | class Board { 55 | val blocks = new Array[Block](9) 56 | blocks(0) = new Block(2, 2, 0, 3) 57 | blocks(1) = new Block(2, 1, 2, 4) 58 | blocks(2) = new Block(2, 1, 2, 3) 59 | blocks(3) = new Block(2, 1, 2, 1) 60 | blocks(4) = new Block(2, 1, 2, 0) 61 | blocks(5) = new Block(1, 1, 0, 2) 62 | blocks(6) = new Block(1, 1, 1, 2) 63 | blocks(7) = new Block(1, 2, 0, 0) 64 | blocks(8) = new Block(1, 2, 1, 0) 65 | 66 | def draw() { 67 | for (row <- NRows - 1 to 0 by -1) { 68 | for (subrow <- 0 until NSubrows) { 69 | for (col <- 0 until NCols) { 70 | if (!blocks.exists(x => x.draw(row, col, subrow))) 71 | print(" " * NSubcols) 72 | } 73 | println() 74 | } 75 | } 76 | } 77 | 78 | def canMove(b: Block, dir: (Int, Int)): Boolean = { 79 | b.canMove(dir) && { 80 | val bm = b.move(dir) 81 | !blocks.exists(x => x != b && bm.overlaps(x)) 82 | } 83 | } 84 | 85 | def done: Boolean = (blocks(0).x == 0 && blocks(0).y == 0) 86 | 87 | def movableBlocks(dir: (Int, Int)): Seq[(Int, Block)] = 88 | ((0 until blocks.length) zip blocks) filter (x => canMove(x._2, dir)) 89 | 90 | def update(i: Int, dir: (Int, Int)) { 91 | blocks(i) = blocks(i).move(dir) 92 | } 93 | } 94 | 95 | def askDirection(prompt: String): (Int, Int) = { 96 | while (true) { 97 | val user_input = readLine(prompt) 98 | user_input.toLowerCase match { 99 | case "x" => sys.exit(0) 100 | case "l" => return (-1, 0) 101 | case "r" => return (1, 0) 102 | case "u" => return (0, 1) 103 | case "d" => return (0, -1) 104 | case _ => println("I beg your pardon!") 105 | } 106 | } 107 | (0, 0) // to make compiler happy 108 | } 109 | 110 | def askIndex(prompt: String, maxVal: Int): Int = { 111 | while (true) { 112 | val user_input = readLine(prompt) 113 | try { 114 | val k = user_input.toInt - 1 115 | if (0 <= k && k < maxVal) 116 | return k 117 | println("Enter a number between 1 and " + maxVal) 118 | } catch { 119 | case e: NumberFormatException => 120 | println("I beg your pardon!") 121 | } 122 | } 123 | 0 // to make compiler happy 124 | } 125 | 126 | def main() { 127 | val board = new Board 128 | while (!board.done) { 129 | board.draw() 130 | val dir = askDirection("Which way do you want to move (u/d/l/r)? ") 131 | val b = board.movableBlocks(dir) 132 | b.length match { 133 | case 0 => println("No such move is possible") 134 | case 1 => board.update(b(0)._1, dir) 135 | case _ => { 136 | println("Select block to move: ") 137 | for (i <- 0 until b.length) 138 | println(" [%d] (%d,%d)".format(i+1, b(i)._2.x, b(i)._2.y)) 139 | val k = askIndex("Move which block? ", b.length) 140 | board.update(b(k)._1, dir) 141 | } 142 | } 143 | } 144 | println("Congratulations!") 145 | } 146 | 147 | main() 148 | -------------------------------------------------------------------------------- /tutorial/60-compiling/blackjack-app.scala: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------- 2 | // BlackJack Game as a compiled application 3 | // -------------------------------------------------------------------- 4 | 5 | import scala.io.StdIn.readLine 6 | 7 | class Card(val face: String, val suit: String) { 8 | override def toString: String = { 9 | val a = if (face == "Ace" || face == "8") "an " else "a " 10 | a + face + " of " + suit 11 | } 12 | def value: Int = face match { 13 | case "Ace" => 11 14 | case "Jack" => 10 15 | case "Queen" => 10 16 | case "King" => 10 17 | case _ => face.toInt 18 | } 19 | } 20 | 21 | class Deck { 22 | private val cards = new Array[Card](52) 23 | private var count = 52 24 | generateDeck() 25 | shuffleDeck() 26 | 27 | private def generateDeck() { 28 | var i = 0 29 | for (suit <- BlackJack.Suits) { 30 | for (face <- BlackJack.Faces) { 31 | cards(i) = new Card(face, suit) 32 | i += 1 33 | } 34 | } 35 | } 36 | private def shuffleDeck() { 37 | for (i <- 1 to 52) { 38 | // 0..i-2 already shuffled 39 | val j = (math.random * i).toInt 40 | val cj = cards(j) 41 | cards(j) = cards(i-1) 42 | cards(i-1) = cj 43 | } 44 | } 45 | def draw(): Card = { 46 | assert(count > 0) 47 | count -= 1 48 | cards(count) 49 | } 50 | } 51 | 52 | object BlackJack { 53 | val Suits = Array("Clubs", "Spades", "Hearts", "Diamonds") 54 | val Faces = Array("2", "3", "4", "5", "6", "7", "8", "9", "10", 55 | "Jack", "Queen", "King", "Ace") 56 | 57 | // Compute the value of a hand of cards. 58 | def handValue(hand: Array[Card]): Int = { 59 | var value = 0 60 | for (card <- hand) 61 | value += card.value 62 | value 63 | } 64 | 65 | /* Display the text prompt and let's the user enter a string. If the 66 | user enters "y", the function returns "true", and if the user enters 67 | "n", the function returns "false" If the user enters anything else, 68 | the function prints "I beg your pardon!", and asks again, repeating 69 | this until the user has entered a correct string. */ 70 | def askYesNo(prompt: String): Boolean = { 71 | while (true) { 72 | val user_input = readLine(prompt) 73 | user_input match { 74 | case "y" => return true 75 | case "n" => return false 76 | case _ => println("I beg your pardon!") 77 | } 78 | } 79 | true // to make compiler happy 80 | } 81 | 82 | // Play one round of Blackjack 83 | // Returns 1 if player wins, -1 if dealer wins, and 0 for a tie. 84 | def blackjack(): Int = { 85 | val deck = new Deck() 86 | 87 | // initial cards 88 | var player = Array(deck.draw()) 89 | println("You are dealt " + player.head) 90 | var dealer = Array(deck.draw()) 91 | println("Dealer is dealt a hidden card") 92 | 93 | player = player :+ deck.draw() 94 | println("You are dealt " + player.last) 95 | dealer = dealer :+ deck.draw() 96 | println("Dealer is dealt " + dealer.last) 97 | printf("Your total is %d\n", handValue(player)) 98 | 99 | // player's turn to draw cards 100 | var want = true 101 | while (want && handValue(player) < 21) { 102 | want = askYesNo("Would you like another card? (y/n) ") 103 | if (want) { 104 | player = player :+ deck.draw() 105 | println("You are dealt " + player.last) 106 | printf("Your total is %d\n", handValue(player)) 107 | 108 | // if the player's score is over 21, the player loses immediately. 109 | if (handValue(player) > 21) { 110 | println("You went over 21! You lost!") 111 | return -1 112 | } 113 | } 114 | } 115 | 116 | println("The dealer's hidden card was " + dealer.head) 117 | while (handValue(dealer) < 17) { 118 | dealer = dealer :+ deck.draw() 119 | println("Dealer is dealt " + dealer.last) 120 | } 121 | printf("The dealer's total is %d\n", handValue(dealer)) 122 | 123 | // summary 124 | val player_total = handValue(player) 125 | val dealer_total = handValue(dealer) 126 | printf("\nYour total is %d\n", player_total) 127 | printf("The dealer's total is %d\n", dealer_total) 128 | 129 | if (dealer_total > 21) { 130 | println("The dealer went over 21! You win!") 131 | 1 132 | } else if (player_total > dealer_total) { 133 | println("You win!") 134 | 1 135 | } else if (player_total < dealer_total) { 136 | println("You lost!") 137 | -1 138 | } else { 139 | println("You have a tie!") 140 | 0 141 | } 142 | } 143 | 144 | def main(args: Array[String]) { 145 | println("Welcome to Blackjack 206!") 146 | while (true) { 147 | println 148 | blackjack() 149 | if (!askYesNo("\nPlay another round? (y/n) ")) 150 | return 151 | } 152 | } 153 | } 154 | 155 | // -------------------------------------------------------------------- 156 | -------------------------------------------------------------------------------- /tutorial/60-compiling/date1.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * This source file does not compile, since it has global variables. 3 | */ 4 | 5 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 6 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 7 | "Friday", "Saturday", "Sunday") 8 | val monthname = Array("January", "February", "March", 9 | "April", "May", "June", 10 | "July", "August", "September", 11 | "October", "November", "December") 12 | 13 | class Date(val year: Int, val month: Int, val day: Int) { 14 | require(1901 <= year && year <= 2099) 15 | require(1 <= month && month <= 12) 16 | require(1 <= day && day <= monthLength(month - 1)) 17 | require(month != 2 || day <= 28 || (year % 4) == 0) 18 | 19 | // returns the number of days since 1901/01/01 (day 0) 20 | def dayIndex: Int = { 21 | val fourY = (365 + 365 + 365 + 366) 22 | val yearn = year - 1901 23 | var total = 0 24 | total += fourY * (yearn / 4) 25 | total += 365 * (yearn % 4) 26 | for (m <- 0 until month - 1) 27 | total += monthLength(m) 28 | total += day - 1 29 | if (year % 4 != 0 && month > 2) 30 | total -= 1 31 | total 32 | } 33 | 34 | def dayOfWeek: String = weekday((dayIndex + 1) % 7) 35 | 36 | override def toString: String = 37 | "%s, %s %d, %d".format(dayOfWeek, 38 | monthname(month-1), 39 | day, 40 | year) 41 | 42 | def num2date(n: Int): Date = { 43 | val fourY = (365 + 365 + 365 + 366) 44 | var year = 1901 + (n / fourY) * 4 45 | var day = n % fourY 46 | if (day >= 365 + 365 + 365 + 59) { 47 | year += 3 48 | day -= 365 + 365 + 365 49 | } else { 50 | year += (day / 365) 51 | day = day % 365 52 | if (day >= 59) 53 | day += 1 54 | } 55 | var month = 1 56 | while (day >= monthLength(month-1)) { 57 | day -= monthLength(month-1) 58 | month += 1 59 | } 60 | new Date(year, month, day+1) 61 | } 62 | 63 | def -(rhs: Date) = dayIndex - rhs.dayIndex 64 | 65 | def +(n: Int): Date = num2date(dayIndex + n) 66 | def -(n: Int): Date = num2date(dayIndex - n) 67 | } 68 | -------------------------------------------------------------------------------- /tutorial/60-compiling/date2.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Compiles, but makes HEAVY Date objects 3 | */ 4 | 5 | class Date(val year: Int, val month: Int, val day: Int) { 6 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 7 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 8 | "Friday", "Saturday", "Sunday") 9 | val monthname = Array("January", "February", "March", 10 | "April", "May", "June", 11 | "July", "August", "September", 12 | "October", "November", "December") 13 | 14 | require(1901 <= year && year <= 2099) 15 | require(1 <= month && month <= 12) 16 | require(1 <= day && day <= monthLength(month - 1)) 17 | require(month != 2 || day <= 28 || (year % 4) == 0) 18 | 19 | 20 | // returns the number of days since 1901/01/01 (day 0) 21 | def dayIndex: Int = { 22 | val fourY = (365 + 365 + 365 + 366) 23 | val yearn = year - 1901 24 | var total = 0 25 | total += fourY * (yearn / 4) 26 | total += 365 * (yearn % 4) 27 | for (m <- 0 until month - 1) 28 | total += monthLength(m) 29 | total += day - 1 30 | if (year % 4 != 0 && month > 2) 31 | total -= 1 32 | total 33 | } 34 | 35 | def dayOfWeek: String = weekday((dayIndex + 1) % 7) 36 | 37 | override def toString: String = 38 | "%s, %s %d, %d".format(dayOfWeek, 39 | monthname(month-1), 40 | day, 41 | year) 42 | 43 | def num2date(n: Int): Date = { 44 | val fourY = (365 + 365 + 365 + 366) 45 | var year = 1901 + (n / fourY) * 4 46 | var day = n % fourY 47 | if (day >= 365 + 365 + 365 + 59) { 48 | year += 3 49 | day -= 365 + 365 + 365 50 | } else { 51 | year += (day / 365) 52 | day = day % 365 53 | if (day >= 59) 54 | day += 1 55 | } 56 | var month = 1 57 | while (day >= monthLength(month-1)) { 58 | day -= monthLength(month-1) 59 | month += 1 60 | } 61 | new Date(year, month, day+1) 62 | } 63 | 64 | def -(rhs: Date) = dayIndex - rhs.dayIndex 65 | 66 | def +(n: Int): Date = num2date(dayIndex + n) 67 | def -(n: Int): Date = num2date(dayIndex - n) 68 | } 69 | -------------------------------------------------------------------------------- /tutorial/60-compiling/date3.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * With singleton object "Date". 3 | */ 4 | 5 | object Date { 6 | val monthLength = Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 7 | val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 8 | "Friday", "Saturday", "Sunday") 9 | val monthname = Array("January", "February", "March", 10 | "April", "May", "June", 11 | "July", "August", "September", 12 | "October", "November", "December") 13 | } 14 | 15 | class Date(val year: Int, val month: Int, val day: Int) { 16 | require(1901 <= year && year <= 2099) 17 | require(1 <= month && month <= 12) 18 | require(1 <= day && day <= Date.monthLength(month - 1)) 19 | require(month != 2 || day <= 28 || (year % 4) == 0) 20 | 21 | 22 | // returns the number of days since 1901/01/01 (day 0) 23 | def dayIndex: Int = { 24 | val fourY = (365 + 365 + 365 + 366) 25 | val yearn = year - 1901 26 | var total = 0 27 | total += fourY * (yearn / 4) 28 | total += 365 * (yearn % 4) 29 | for (m <- 0 until month - 1) 30 | total += Date.monthLength(m) 31 | total += day - 1 32 | if (year % 4 != 0 && month > 2) 33 | total -= 1 34 | total 35 | } 36 | 37 | def dayOfWeek: String = Date.weekday((dayIndex + 1) % 7) 38 | 39 | override def toString: String = 40 | "%s, %s %d, %d".format(dayOfWeek, 41 | Date.monthname(month-1), 42 | day, 43 | year) 44 | 45 | def num2date(n: Int): Date = { 46 | val fourY = (365 + 365 + 365 + 366) 47 | var year = 1901 + (n / fourY) * 4 48 | var day = n % fourY 49 | if (day >= 365 + 365 + 365 + 59) { 50 | year += 3 51 | day -= 365 + 365 + 365 52 | } else { 53 | year += (day / 365) 54 | day = day % 365 55 | if (day >= 59) 56 | day += 1 57 | } 58 | var month = 1 59 | while (day >= Date.monthLength(month-1)) { 60 | day -= Date.monthLength(month-1) 61 | month += 1 62 | } 63 | new Date(year, month, day+1) 64 | } 65 | 66 | def -(rhs: Date) = dayIndex - rhs.dayIndex 67 | 68 | def +(n: Int): Date = num2date(dayIndex + n) 69 | def -(n: Int): Date = num2date(dayIndex - n) 70 | } 71 | -------------------------------------------------------------------------------- /tutorial/60-compiling/date4.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Fields of Date object are now private. 3 | */ 4 | 5 | object Date { 6 | private val monthLength = Array(31, 29, 31, 30, 31, 30, 7 | 31, 31, 30, 31, 30, 31) 8 | private val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 9 | "Friday", "Saturday", "Sunday") 10 | private val monthname = Array("January", "February", "March", 11 | "April", "May", "June", 12 | "July", "August", "September", 13 | "October", "November", "December") 14 | } 15 | 16 | class Date(val year: Int, val month: Int, val day: Int) { 17 | require(1901 <= year && year <= 2099) 18 | require(1 <= month && month <= 12) 19 | require(1 <= day && day <= Date.monthLength(month - 1)) 20 | require(month != 2 || day <= 28 || (year % 4) == 0) 21 | 22 | // returns the number of days since 1901/01/01 (day 0) 23 | def dayIndex: Int = { 24 | val fourY = (365 + 365 + 365 + 366) 25 | val yearn = year - 1901 26 | var total = 0 27 | total += fourY * (yearn / 4) 28 | total += 365 * (yearn % 4) 29 | for (m <- 0 until month - 1) 30 | total += Date.monthLength(m) 31 | total += day - 1 32 | if (year % 4 != 0 && month > 2) 33 | total -= 1 34 | total 35 | } 36 | 37 | def dayOfWeek: String = Date.weekday((dayIndex + 1) % 7) 38 | 39 | override def toString: String = 40 | "%s, %s %d, %d".format(dayOfWeek, 41 | Date.monthname(month-1), 42 | day, 43 | year) 44 | 45 | def num2date(n: Int): Date = { 46 | val fourY = (365 + 365 + 365 + 366) 47 | var year = 1901 + (n / fourY) * 4 48 | var day = n % fourY 49 | if (day >= 365 + 365 + 365 + 59) { 50 | year += 3 51 | day -= 365 + 365 + 365 52 | } else { 53 | year += (day / 365) 54 | day = day % 365 55 | if (day >= 59) 56 | day += 1 57 | } 58 | var month = 1 59 | while (day >= Date.monthLength(month-1)) { 60 | day -= Date.monthLength(month-1) 61 | month += 1 62 | } 63 | new Date(year, month, day+1) 64 | } 65 | 66 | def -(rhs: Date) = dayIndex - rhs.dayIndex 67 | 68 | def +(n: Int): Date = num2date(dayIndex + n) 69 | def -(n: Int): Date = num2date(dayIndex - n) 70 | } 71 | -------------------------------------------------------------------------------- /tutorial/60-compiling/date5.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Moved "num2date" to Date.fromDayIndex 3 | */ 4 | 5 | object Date { 6 | private val monthLength = Array(31, 29, 31, 30, 31, 30, 7 | 31, 31, 30, 31, 30, 31) 8 | private val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 9 | "Friday", "Saturday", "Sunday") 10 | private val monthname = Array("January", "February", "March", 11 | "April", "May", "June", 12 | "July", "August", "September", 13 | "October", "November", "December") 14 | 15 | def fromDayIndex(n: Int): Date = { 16 | val fourY = (365 + 365 + 365 + 366) 17 | var year = 1901 + (n / fourY) * 4 18 | var day = n % fourY 19 | if (day >= 365 + 365 + 365 + 59) { 20 | year += 3 21 | day -= 365 + 365 + 365 22 | } else { 23 | year += (day / 365) 24 | day = day % 365 25 | if (day >= 59) 26 | day += 1 27 | } 28 | var month = 1 29 | while (day >= Date.monthLength(month-1)) { 30 | day -= Date.monthLength(month-1) 31 | month += 1 32 | } 33 | new Date(year, month, day+1) 34 | } 35 | 36 | } 37 | 38 | class Date(val year: Int, val month: Int, val day: Int) { 39 | require(1901 <= year && year <= 2099) 40 | require(1 <= month && month <= 12) 41 | require(1 <= day && day <= Date.monthLength(month - 1)) 42 | require(month != 2 || day <= 28 || (year % 4) == 0) 43 | 44 | 45 | // returns the number of days since 1901/01/01 (day 0) 46 | def dayIndex: Int = { 47 | val fourY = (365 + 365 + 365 + 366) 48 | val yearn = year - 1901 49 | var total = 0 50 | total += fourY * (yearn / 4) 51 | total += 365 * (yearn % 4) 52 | for (m <- 0 until month - 1) 53 | total += Date.monthLength(m) 54 | total += day - 1 55 | if (year % 4 != 0 && month > 2) 56 | total -= 1 57 | total 58 | } 59 | 60 | def dayOfWeek: String = Date.weekday((dayIndex + 1) % 7) 61 | 62 | override def toString: String = 63 | "%s, %s %d, %d".format(dayOfWeek, 64 | Date.monthname(month-1), 65 | day, 66 | year) 67 | 68 | def -(rhs: Date) = dayIndex - rhs.dayIndex 69 | 70 | def +(n: Int): Date = Date.fromDayIndex(dayIndex + n) 71 | def -(n: Int): Date = Date.fromDayIndex(dayIndex - n) 72 | } 73 | -------------------------------------------------------------------------------- /tutorial/60-compiling/date6.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Making Dates without "new". 3 | */ 4 | 5 | object Date { 6 | private val monthLength = Array(31, 29, 31, 30, 31, 30, 7 | 31, 31, 30, 31, 30, 31) 8 | private val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 9 | "Friday", "Saturday", "Sunday") 10 | private val monthname = Array("January", "February", "March", 11 | "April", "May", "June", 12 | "July", "August", "September", 13 | "October", "November", "December") 14 | 15 | def apply(year: Int, month: Int, day: Int): Date = 16 | new Date(year, month, day) 17 | 18 | def fromDayIndex(n: Int): Date = { 19 | val fourY = (365 + 365 + 365 + 366) 20 | var year = 1901 + (n / fourY) * 4 21 | var day = n % fourY 22 | if (day >= 365 + 365 + 365 + 59) { 23 | year += 3 24 | day -= 365 + 365 + 365 25 | } else { 26 | year += (day / 365) 27 | day = day % 365 28 | if (day >= 59) 29 | day += 1 30 | } 31 | var month = 1 32 | while (day >= Date.monthLength(month-1)) { 33 | day -= Date.monthLength(month-1) 34 | month += 1 35 | } 36 | new Date(year, month, day+1) 37 | } 38 | 39 | } 40 | 41 | class Date(val year: Int, val month: Int, val day: Int) { 42 | require(1901 <= year && year <= 2099) 43 | require(1 <= month && month <= 12) 44 | require(1 <= day && day <= Date.monthLength(month - 1)) 45 | require(month != 2 || day <= 28 || (year % 4) == 0) 46 | 47 | // returns the number of days since 1901/01/01 (day 0) 48 | def dayIndex: Int = { 49 | val fourY = (365 + 365 + 365 + 366) 50 | val yearn = year - 1901 51 | var total = 0 52 | total += fourY * (yearn / 4) 53 | total += 365 * (yearn % 4) 54 | for (m <- 0 until month - 1) 55 | total += Date.monthLength(m) 56 | total += day - 1 57 | if (year % 4 != 0 && month > 2) 58 | total -= 1 59 | total 60 | } 61 | 62 | def dayOfWeek: String = Date.weekday((dayIndex + 1) % 7) 63 | 64 | override def toString: String = 65 | "%s, %s %d, %d".format(dayOfWeek, 66 | Date.monthname(month-1), 67 | day, 68 | year) 69 | 70 | def -(rhs: Date) = dayIndex - rhs.dayIndex 71 | 72 | def +(n: Int): Date = Date.fromDayIndex(dayIndex + n) 73 | def -(n: Int): Date = Date.fromDayIndex(dayIndex - n) 74 | } 75 | -------------------------------------------------------------------------------- /tutorial/60-compiling/date7.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Making Dates without "new". 3 | */ 4 | 5 | object Date { 6 | private val monthLength = Array(31, 29, 31, 30, 31, 30, 7 | 31, 31, 30, 31, 30, 31) 8 | private val weekday = Array("Monday", "Tuesday", "Wednesday", "Thursday", 9 | "Friday", "Saturday", "Sunday") 10 | private val monthname = Array("January", "February", "March", 11 | "April", "May", "June", 12 | "July", "August", "September", 13 | "October", "November", "December") 14 | 15 | def apply(year: Int, month: Int, day: Int): Date = 16 | new Date(year, month, day) 17 | 18 | def fromDayIndex(n: Int): Date = { 19 | val fourY = (365 + 365 + 365 + 366) 20 | var year = 1901 + (n / fourY) * 4 21 | var day = n % fourY 22 | if (day >= 365 + 365 + 365 + 59) { 23 | year += 3 24 | day -= 365 + 365 + 365 25 | } else { 26 | year += (day / 365) 27 | day = day % 365 28 | if (day >= 59) 29 | day += 1 30 | } 31 | var month = 1 32 | while (day >= Date.monthLength(month-1)) { 33 | day -= Date.monthLength(month-1) 34 | month += 1 35 | } 36 | new Date(year, month, day+1) 37 | } 38 | 39 | } 40 | 41 | class Date private (val year: Int, val month: Int, val day: Int) { 42 | require(1901 <= year && year <= 2099) 43 | require(1 <= month && month <= 12) 44 | require(1 <= day && day <= Date.monthLength(month - 1)) 45 | require(month != 2 || day <= 28 || (year % 4) == 0) 46 | 47 | // returns the number of days since 1901/01/01 (day 0) 48 | def dayIndex: Int = { 49 | val fourY = (365 + 365 + 365 + 366) 50 | val yearn = year - 1901 51 | var total = 0 52 | total += fourY * (yearn / 4) 53 | total += 365 * (yearn % 4) 54 | for (m <- 0 until month - 1) 55 | total += Date.monthLength(m) 56 | total += day - 1 57 | if (year % 4 != 0 && month > 2) 58 | total -= 1 59 | total 60 | } 61 | 62 | def dayOfWeek: String = Date.weekday((dayIndex + 1) % 7) 63 | 64 | override def toString: String = 65 | "%s, %s %d, %d".format(dayOfWeek, 66 | Date.monthname(month-1), 67 | day, 68 | year) 69 | 70 | def -(rhs: Date) = dayIndex - rhs.dayIndex 71 | 72 | def +(n: Int): Date = Date.fromDayIndex(dayIndex + n) 73 | def -(n: Int): Date = Date.fromDayIndex(dayIndex - n) 74 | } 75 | -------------------------------------------------------------------------------- /tutorial/60-compiling/days.scala: -------------------------------------------------------------------------------- 1 | 2 | object Days { 3 | val digits = "0123456789" 4 | 5 | // if s is not a legal date, or is not in range, 6 | // then throws IllegalArgumentException 7 | def getDate(s: String): Date = { 8 | if (s.length != 10 || s(4) != '/' || s(7) != '/') 9 | throw new IllegalArgumentException 10 | for (i <- 0 until s.length) { 11 | if (i != 4 && i != 7 && !digits.contains(s(i))) 12 | throw new IllegalArgumentException 13 | } 14 | val year = s.substring(0, 4).toInt 15 | val month = s.substring(5, 7).toInt 16 | val day = s.substring(8).toInt 17 | Date(year, month, day) 18 | } 19 | 20 | def main(args: Array[String]) { 21 | try { 22 | if (args.length == 1) { 23 | val d = getDate(args(0)) 24 | printf("%s is a %s\n", args(0), d.dayOfWeek) 25 | } else if (args.length == 2) { 26 | val d1 = getDate(args(0)) 27 | val d2 = getDate(args(1)) 28 | printf("There are %d days between %s and %s\n", d2 - d1, d1, d2) 29 | } else if (args.length == 3) { 30 | val d1 = getDate(args(0)) 31 | val sign = if (args(1) == "-") -1 else +1 32 | val dist = args(2).toInt 33 | val d2 = d1 + sign * dist 34 | printf("%s %s %d days = %s\n", d1, args(1), dist, d2) 35 | } else { 36 | Console.err.println("Must have one, two, or three arguments") 37 | } 38 | } catch { 39 | case e: NumberFormatException => 40 | Console.err.println("Illegal number") 41 | case e: IllegalArgumentException => 42 | Console.err.println("Illegal date") 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tutorial/60-compiling/hello.scala: -------------------------------------------------------------------------------- 1 | 2 | println("Hello World") 3 | 4 | -------------------------------------------------------------------------------- /tutorial/60-compiling/kermit.scala: -------------------------------------------------------------------------------- 1 | 2 | object Kermit { 3 | println("Kermit is born") 4 | 5 | def main(args: Array[String]) { 6 | val n = if (args.length == 1) args(0).toInt else 1 7 | for (i <- 1 to n) 8 | println("It's not easy being green!") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tutorial/60-compiling/numbers.scala: -------------------------------------------------------------------------------- 1 | import scala.io.StdIn.readInt 2 | 3 | object NumberGame { 4 | var secret = 0 5 | var guess = -1 6 | 7 | def answerGuess() { 8 | if (guess == secret) 9 | println("You got it") 10 | else if (guess > secret) 11 | println("Too big") 12 | else if (guess < secret) 13 | println("Too small") 14 | } 15 | 16 | def main(args: Array[String]) { 17 | secret = (math.random * 100).toInt 18 | while (guess != secret) { 19 | print("Guess my number> ") 20 | guess = readInt() 21 | answerGuess() 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tutorial/60-compiling/point.scala: -------------------------------------------------------------------------------- 1 | 2 | class Point(val x: Int, val y: Int) { 3 | override def toString: String = 4 | "[%d,%d]".format(x,y) 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tutorial/70-scalatest/checkpoly.scala: -------------------------------------------------------------------------------- 1 | 2 | import org.scalatest.FunSuite 3 | import scala.language.implicitConversions 4 | 5 | class PolynomialCheckSuite extends FunSuite { 6 | implicit def intToPolynomial(a: Int): Polynomial = { 7 | new Polynomial(Array(a)) 8 | } 9 | 10 | test("creating polynomials") { 11 | val p1 = new Polynomial(Array(3)) 12 | assert(p1.degree == 0) 13 | assert(p1.toString == "3") 14 | val p2 = new Polynomial(Array(-1, 3, -4, 0, -6)) 15 | assert(p2.degree == 4) 16 | assert(p2.toString == "-6 * X^4 - 4 * X^2 + 3 * X - 1") 17 | val p3 = new Polynomial(Array(0, 0, 1)) 18 | assert(p3.degree == 2) 19 | assert(p3.toString == "X^2") 20 | 21 | val p0 = new Polynomial(Array(0)) 22 | assert(p0.degree == -1) 23 | } 24 | 25 | test("addition and subtraction") { 26 | val p1 = new Polynomial(Array(3)) 27 | val p2 = new Polynomial(Array(-1, 3, -4, 0, -6)) 28 | val p3 = new Polynomial(Array(5, 0, 4, 0, -6)) 29 | 30 | val q1 = p1 + p2 31 | val q2 = p2 - p3 32 | assert(q1.toString == "-6 * X^4 - 4 * X^2 + 3 * X + 2") 33 | assert(q2.degree == 2) 34 | assert(q2.toString == "-8 * X^2 + 3 * X - 6") 35 | } 36 | 37 | test("multiplication and power") { 38 | val p1 = new Polynomial(Array(3)) 39 | val p2 = new Polynomial(Array(-1, 3, -4, 0, -6)) 40 | val p3 = new Polynomial(Array(0, 0, 5)) 41 | val p4 = new Polynomial(Array(2, -4, 6, 8)) 42 | 43 | val q1 = p1 * p2 44 | val q2 = p1^5 45 | val q3 = p3^5 46 | val q4 = p2 * p3 47 | val q5 = p2 * p4 48 | assert(q1.toString == "-18 * X^4 - 12 * X^2 + 9 * X - 3") 49 | assert(q2.degree == 0) 50 | assert(q2.coeff(0) == 3*3*3*3*3) 51 | assert(q3.degree == 10) 52 | assert(q3.toString == "3125 * X^10") 53 | assert(q4.degree == 6) 54 | assert(q4.toString == "-30 * X^6 - 20 * X^4 + 15 * X^3 - 5 * X^2") 55 | assert(q5.toString == "-48 * X^7 - 36 * X^6 - 8 * X^5 - 12 * X^4 + 26 * X^3 - 26 * X^2 + 10 * X - 2") 56 | } 57 | 58 | test("creating polynomials using X") { 59 | val X = new Polynomial(Array(0, 1)) 60 | assert(X.toString == "X") 61 | val p4 = -1 * (X^5) + 3 * (X^3) - (X^2) + 5 62 | assert(p4.toString == "-X^5 + 3 * X^3 - X^2 + 5") 63 | val p5 = (X - 1) * (X - 3) * (X + 5)^2 64 | assert(p5.toString == "X^6 + 2 * X^5 - 33 * X^4 - 4 * X^3 + 319 * X^2 - 510 * X + 225") 65 | } 66 | 67 | test("evaluation") { 68 | val X = new Polynomial(Array(0, 1)) 69 | val p1 = new Polynomial(Array(3)) 70 | val p2 = new Polynomial(Array(-1, 3, -4, 0, -6)) 71 | val p3 = new Polynomial(Array(0, 0, 1)) 72 | val p4 = -1 * (X^5) + 3 * (X^3) - (X^2) + 5 73 | val p5 = (X - 1) * (X - 3) * (X + 5)^2 74 | 75 | assertResult(3.0) { p1(5) } 76 | assertResult(-1.0) { p2(0) } 77 | assertResult(4.0) { p3(2) } 78 | assertResult(0.0) { p5(-5.0) } 79 | } 80 | 81 | test("derivatives") { 82 | val X = new Polynomial(Array(0, 1)) 83 | val p1 = (X - 1) * (X - 3) * ((X + 5)^2) 84 | /* 85 | val q1 = p1.derivative 86 | assert(q1.degree == 3) 87 | assert(q1.toString == "4 * X^3 + 18 * X^2 - 24 * X - 70") 88 | val q2 = q1.derivative 89 | assert(q2.degree == 2) 90 | assert(q2.toString == "12 * X^2 + 36 * X - 24") 91 | */ 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /tutorial/70-scalatest/polynomial1.scala: -------------------------------------------------------------------------------- 1 | class Polynomial(coeffs: Array[Int]) { 2 | 3 | def degree: Int = ??? 4 | 5 | def coeff(i: Int): Int = ??? 6 | 7 | override def toString: String = ??? 8 | 9 | def + (rhs: Polynomial): Polynomial = ??? 10 | 11 | def - (rhs: Polynomial): Polynomial = ??? 12 | 13 | def * (rhs: Polynomial): Polynomial = ??? 14 | 15 | def ^ (ex: Int): Polynomial = ??? 16 | 17 | def apply(x: Double): Double = ??? 18 | } 19 | -------------------------------------------------------------------------------- /tutorial/70-scalatest/polynomial2.scala: -------------------------------------------------------------------------------- 1 | class Polynomial(coeffs: Array[Int]) { 2 | private val A = createCoeffs(coeffs) 3 | 4 | private def createCoeffs(A: Array[Int]): Array[Int] = { 5 | var s = A.length - 1 6 | while (s >= 0 && A(s) == 0) 7 | s -= 1 8 | A take (s+1) 9 | } 10 | 11 | def degree: Int = A.length - 1 12 | 13 | def coeff(i: Int): Int = if (i < A.length) A(i) else 0 14 | 15 | override def toString: String = { 16 | var s = new StringBuilder 17 | var plus = "" 18 | var minus = "-" 19 | for (i <- degree to 0 by -1) { 20 | if (coeff(i) != 0) { 21 | var c = coeff(i) 22 | s ++= (if (c > 0) plus else minus) 23 | plus = " + "; minus = " - " 24 | c = c.abs 25 | if (i == 0) 26 | s ++= c.toString 27 | else { 28 | if (c != 1) 29 | s ++= c.toString + " * " 30 | if (i > 1) 31 | s ++= "X^" + i.toString 32 | else 33 | s ++= "X" 34 | } 35 | } 36 | } 37 | s.toString 38 | } 39 | 40 | def + (rhs: Polynomial): Polynomial = ??? 41 | 42 | def - (rhs: Polynomial): Polynomial = ??? 43 | 44 | def * (rhs: Polynomial): Polynomial = ??? 45 | 46 | def ^ (ex: Int): Polynomial = ??? 47 | 48 | def apply(x: Double): Double = ??? 49 | } 50 | -------------------------------------------------------------------------------- /tutorial/70-scalatest/test1.scala: -------------------------------------------------------------------------------- 1 | import org.scalatest.FunSuite 2 | 3 | class AdditionCheckSuite extends FunSuite { 4 | val two = 2 5 | val three = 3 6 | 7 | test("one plus one") { 8 | assert(1 + 1 == two) 9 | assert(1 + 1 != three) 10 | } 11 | 12 | test("one plus one with result") { 13 | assertResult(two) { 1 + 1 } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tutorial/70-scalatest/test2.scala: -------------------------------------------------------------------------------- 1 | import org.scalatest.FunSuite 2 | 3 | class AdditionCheckSuite extends FunSuite { 4 | val two = 3 5 | val three = 2 6 | 7 | test("one plus one") { 8 | assert(1 + 1 == two) 9 | assert(1 + 1 != three) 10 | } 11 | 12 | test("one plus one with result") { 13 | assertResult(two) { 1 + 1 } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tutorial/70-scalatest/test3.scala: -------------------------------------------------------------------------------- 1 | import org.scalatest.FunSuite 2 | 3 | class AdditionCheckSuite extends FunSuite { 4 | val two = 2 5 | val three = 3 6 | 7 | test("one plus one") { 8 | assert(1 + 1 == two) 9 | assert(1 + 1 != three) 10 | } 11 | 12 | test("one plus one with result") { 13 | assertResult(two) { 1 + 1 } 14 | } 15 | 16 | test("division by zero") { 17 | intercept[ArithmeticException] { 18 | 1 / 0 19 | } 20 | } 21 | } 22 | --------------------------------------------------------------------------------