import vector import io import random type Iterator= { hasNext->Boolean get->T next->T} type Vector = { size->Number isEmpty->Boolean clear->Void contains(_:T)->Boolean addFirst(_:T)->Void addLast(_:T)->Void firstElement->T lastElement->T removeFirst->T removeLast->T removeValue(_:T)->T indexOf(_:T)->Number at(_:Number)->T setValue(_:T)at(_:Number)->T add(_:T)at(_:Number)->Void removeFromIndex(_:Number)->T iterator->Iterator asString->String forEachDo(_:Block)->Void map(_:Block)->Vector ensureCapacity(_:Number)->Void capacity->Number copyInto(_)->Void indexOf(_:T)startingFrom(_:Number)->Number setSize(_:Number)->Void trimToSize->Void} type TextCoinStrip = { asString->String isLegalMove(_:Number, _:Number)->Boolean makeMove(_:Number, _:Number)->Boolean gameIsOver->Boolean play->Void} //=================================================== class TextCoinStripClass.new(sq:Number, c:Number){ // the number of coins, 0 < coins < squares var coins:Number is readable := if ((0 > c) || (c >= sq)) then { print "# coins: {c} must be positive and less than # squares: {sq}" print "setting # coins to 1" 1} else{c} // the number of squares, 0 < coins < squares var squares:Number is readable := if (coins >= sq) then { print "Game must be played with fewer coins than squares" print "setting # squares to 2" 2} else{sq} // the strip of coins. A square is occupied by a coin if // the boolean value at thta location is true. var theStrip:Vector is private := vector.withSize(squares) increment(0)initialVal(false) theStrip.setSize(squares) var rand := random.generator while{0 < coins} do { var i:Number := rand.next(squares) + 1 if(!theStrip.at(i)) then{ theStrip.setValue(true)at(i) coins := coins - 1} } // @return string representation of a strip method asString->String is public{ var rep:String := "" for(1..theStrip.size) do {i-> if(theStrip.at(i)) then {rep := rep ++ "o"} else{rep := rep ++ "_"} } return rep} // @param start: location of coin to be moved // @param distance: how far coin is to move // @return true if move is legal method isLegalMove(start:Number, distance:Number)->Boolean is public{ var legal:Boolean := true if((start > theStrip.size) || (start < 1) || (distance < 1)) then {return false} if(!theStrip.at(start) || ((start - distance) <= 0)) then{ return false} for(1..distance) do {i-> if(theStrip.at(start - i)) then {return false} } return legal} // makes a (legal) move // @param start: the location of the coin to be moved // @param distance: how far the coin is to move // @pre the move msut be legal method makeMove(start:Number, distance:Number)->Boolean is public{ theStrip.setValue(false)at(start) theStrip.setValue(true)at(start - distance)} // determines if game is completed // @return true if there are no more moves method gameIsOver->Boolean is public{ var over:Boolean := true var numcoins:Number := 0 for (1..theStrip.size) do {i-> if(theStrip.at(i)) then {numcoins := numcoins + 1} } for (1..numcoins) do {i-> if(!theStrip.at(i)) then {over := false} } return over} // plays the Silver Dollar Game until it is finished method play is public{ var istream := io.input var start:Number := 0 var distance:Number := 0 while {!gameIsOver} do { print(asString ++ " Next move ?") var soFar := "" var chr := istream.next while{chr != "\n"} do { soFar := soFar ++ chr chr := istream.next} start := soFar.asNumber.truncate soFar := "" chr := istream.next while{chr != "\n"} do { soFar := soFar ++ chr chr := istream.next} distance := soFar.asNumber.truncate if(isLegalMove(start, distance)) then { makeMove(start, distance)} else{print "Illegal move!"} } print(asString ++ " You win")} } //================================================= // demonstration of game; constructs 12-square strip // with 5 coins and plays Silver Dollar Game var tcs:TextCoinStrip := TextCoinStripClass.new(12, 5) tcs.play