import java.util.Random class TicTacToe(val size:int, val players:List[Player]) { protected val field = new Array[Array[char]](size,size) val len = size*size val lines = _stline((v,v2) => (v,v2))++_stline((v,v2) => (v2,v))++ List(((size-1).until(-1,-1)).map(v=>(v,v))) ++ List((0 until size).map(v=>(v,v))) def _stline(f:(int,int) => Pair[int,int]) = (0 until size).map(v => (0 until size).map(v2 => f(v,v2))) override def toString = { val sep = List.make(size*4+1, "-").mkString("\n", "", "\n") field.map{_.mkString("| ", " | ", " |")}.mkString(sep,sep,sep) } def start:Option[Player] = { for(val i<-(0 until size); val j<-(0 until size)) { field(i)(j) = ' '} Stream.const(players).flatMap(v=>v).take(len).find {player => val p = player.put(this) if(!available_?(p)) error("Oops!") field(p._1)(p._2) = player.mark judge } } def judge = lines.exists(l => l.forall(!available_?(_)) && l.forall(v => field(l(0)._1)(l(0)._2) == field(v._1)(v._2))) def available_?(pos:Pair[int,int]) = field(pos._1)(pos._2) equals ' ' } abstract class Player{ val mark:char val name:String def put(ttt:TicTacToe):Pair[int,int] } class RandomPlayer(override val mark:char, override val name:String) extends Player{ val rnd = new Random override def put(ttt:TicTacToe) = { def _n = (rnd.nextInt(ttt.size), rnd.nextInt(ttt.size)) def next(v:Pair[int,int]):Stream[Pair[int,int]] = Stream.cons(v, next(_n)) next(_n).find(ttt.available_?).get } } object Main extends Application{ val ttt = new TicTacToe(3, List(new RandomPlayer('○', "1"), new RandomPlayer('×', "2"))) val result = Array.make(3,0) (1 to 10000) foreach { i => ttt.start match { case Some(p) if p.name equals "1" => result(0) += 1 case Some(p) if p.name equals "2" => result(1) += 1 case _ => result(2) += 1 } } println("player1 won:\t"+result(0)+"\n"+"player2 won:\t"+result(1)+"\n"+"draw :\t"+result(2)) }