Created
October 5, 2019 03:56
-
-
Save wakita/39c89d55cbd927474c9cd030239e19d4 to your computer and use it in GitHub Desktop.
xxx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
プログラムの実行手順: | |
1. ターミナルを開き、build.sbt がある場所で sbt と入力し、return を押す | |
2. project tetris と入力し、return を押す | |
3. run と入力し、return を押す | |
4. 以降、もう一度コンパイルしたいときは run と入力 | |
*/ | |
package shape | |
import scala.collection.immutable.Range | |
import scala.util.Random | |
import scala.math.max | |
import sdraw._ | |
object ShapeLib { | |
type ColorSymbol = Char | |
val blockSymbols = List('I', 'J', 'T', 'O', 'Z', 'L', 'S') | |
val blockColors = { | |
val n = blockSymbols.length | |
for (i <- Range(0, n)) yield (HSB(360f * i / n, 0.3f, 1)) | |
} | |
val colorSymbols = blockSymbols ++ List('G', 'g') | |
val colors = blockColors ++ List(DarkGray, LightGray) | |
val Color2Sym = colors.zip(colorSymbols).toList | |
val Sym2Color: List[(ColorSymbol, Color)] = | |
Color2Sym.map(cn => (cn._2, cn._1)) | |
type Block = Color | |
type Row = List[Block] | |
type Shape = List[Row] | |
type ShapeSpec = List[String] | |
def show(shape: Shape): String = shape.map(showRow).mkString("\n") | |
def showRow(row: Row): String = row.map(showBlock).mkString | |
def showBlock(block: Block): Char = { | |
Color2Sym.find(_._1 == block) match { | |
case Some((_, sym)) => sym | |
case None => '.' | |
} | |
} | |
val shapeSpecs: List[ShapeSpec] = | |
List( | |
List("I", "I", "I", "I"), | |
List(" J", " J", "JJ"), | |
List(" T", "TT", " T"), | |
List("OO", "OO"), | |
List(" Z", "ZZ", "Z "), | |
List("LL", " L", " L"), | |
List("S ", "SS", " S")) | |
def make(spec: ShapeSpec): Shape = { | |
def color(c: ColorSymbol): Color = | |
Sym2Color.find(p => p._1.equals(c)) match { | |
case Some((_, c)) => c | |
case _ => Transparent | |
} | |
spec.map((row: String) => row.toList.map(color)) | |
} | |
val allShapes: List[Shape] = shapeSpecs.map(make) | |
val List(shapeI, shapeJ, shapeT, shapeO, shapeZ, shapeL, shapeS) = allShapes | |
val r = new Random() | |
def random(): Shape = allShapes(r.nextInt(allShapes.length)) | |
/** 1. makeList | |
* 入力: 自然数 n: Int と任意[T]のデータ a:[T] | |
* 出力: List[T] | |
* | |
* 目的: aがn個連なるリストを返す。 | |
* 契約: 任意の型[T]について (Int, T) -> List[T] | |
* | |
* 関数定義の準備: | |
* def makeList[T](n: Int, a: T): Int[T] = { | |
* Nil | |
* } | |
* | |
* 入出力の例: | |
* {{{ | |
* >>> val S = ShapeLib | |
* | |
* >>> S.makeList(0, 1) == Nil | |
* true | |
* | |
* >>> S.makeList(1, 1) | |
* List(1) | |
* | |
* >>> S.makeList(3, 1) | |
* List(1, 1, 1) | |
* | |
* >>> S.makeList(2, 1.0) | |
* List(1.0, 1.0) | |
* | |
* >>> S.makeList(2, "x") == List("x", "x") | |
* true | |
* | |
* >>> val complex = (0, 1.0, "x") | |
* >>> S.makeList(2, complex) == List(complex, complex) | |
* true | |
* | |
* >>> val complex2 = List(complex, complex) | |
* >>> S.makeList(3, S.makeList(2, complex)) == List(complex2, complex2, complex2) | |
* true | |
* | |
* }}} | |
* | |
* 型紙: | |
* def makeList[T](n: Int, a: T): Int[T] = { | |
* n match { | |
* case 0 => Nil | |
* case _ => n ... a ... makeList(..., ...) ... | |
* } | |
* } | |
**/ | |
def makeList[T](n: Int, a: T): List[T] = { | |
n match { | |
case 0 => Nil | |
case _ => a :: makeList(n - 1, a) | |
} | |
} | |
/** 2. empty | |
* {{{ | |
* >>> import sdraw._ | |
* >>> val S = ShapeLib | |
* | |
* >>> S.empty(0, 0) == Nil | |
* true | |
* | |
* >>> S.empty(0, 1) == Nil | |
* true | |
* | |
* >>> S.empty(0, 2) == Nil | |
* true | |
* | |
* >>> S.empty(1, 0) == List(Nil) | |
* true | |
* | |
* >>> S.empty(2, 0) == List(Nil, Nil) | |
* true | |
* | |
* >>> S.empty(1, 1) == List(List(Transparent)) | |
* true | |
* | |
* >>> S.empty(2, 1) == List(List(Transparent), List(Transparent)) | |
* true | |
* | |
* >>> S.empty(1, 2) == List(List(Transparent, Transparent)) | |
* true | |
* | |
* }}} | |
**/ | |
def empty(rows: Int, cols: Int): Shape = { | |
makeList(rows, makeList(cols, Transparent)) | |
} | |
/** 3. size | |
* {{{ | |
* >>> val S = ShapeLib | |
* >>> import sdraw._ | |
* | |
* 基本的な性質の確認 | |
* >>> S.size(S.empty(0, 0)) == (0, 0) | |
* true | |
* | |
* >>> S.size(S.empty(1, 0)) == (1, 0) | |
* true | |
* | |
* 要注意: 入出力が非対称な例 | |
* >>> S.size(S.empty(0, 1)) == (0, 0) | |
* true | |
* | |
* >>> S.size(S.empty(1, 1)) == (1, 1) | |
* true | |
* | |
* >>> S.size(S.empty(2, 1)) == (2, 1) | |
* true | |
* | |
* >>> S.size(S.empty(1, 2)) == (1, 2) | |
* true | |
* | |
* 以下は与えられた Shape 群についてのテストたち | |
* >>> S.size(S.shapeI) == (4, 1) | |
* true | |
* | |
* >>> S.size(S.shapeJ) == (3, 2) | |
* true | |
* | |
* >>> S.size(S.shapeT) == (3, 2) | |
* true | |
* | |
* >>> S.size(S.shapeO) == (2, 2) | |
* true | |
* | |
* >>> S.size(S.shapeZ) == (3, 2) | |
* true | |
* | |
* >>> S.size(S.shapeL) == (3, 2) | |
* true | |
* | |
* >>> S.size(S.shapeS) == (3, 2) | |
* true | |
* | |
* }}} | |
**/ | |
def size(shape: Shape): (Int, Int) = { | |
def length[T](l: List[T]): Int = { | |
l match { | |
case Nil => 0 | |
case _ :: l => 1 + length(l) | |
} | |
} | |
shape match { | |
case Nil => (0, 0) | |
case _ => (length(shape), length(shape(0))) | |
} | |
} | |
/** 4. blockCount | |
* 入力: 形状 shape: Shape | |
* shape[IJTOZLS] | |
* | |
* 出力: ブロックの数: Int | |
* いずれも4 | |
* | |
* 目的: shapeが含む空でないブロックの数を勘定する | |
* 契約: shape: Shape | |
* | |
* {{{ | |
* >>> import sdraw._ | |
* >>> val S = ShapeLib | |
* >>> val blockCount = ShapeLib.blockCount _ | |
* | |
* >>> blockCount(S.empty(0, 0)) == 0 | |
* true | |
* | |
* >>> blockCount(S.empty(1, 0)) == 0 | |
* true | |
* | |
* >>> blockCount(S.empty(0, 1)) == 0 | |
* true | |
* | |
* >>> blockCount(S.empty(2, 2)) == 0 | |
* true | |
* | |
* >>> blockCount(List(S.colors.toList)) == S.colors.length | |
* true | |
* | |
* >>> blockCount(List(List(Black, White), List(Red, Blue), List(Yellow, Transparent), List(Transparent, Orange))) == 6 | |
* true | |
* | |
* >>> blockCount(S.shapeI) == 4 | |
* true | |
* | |
* >>> blockCount(S.shapeJ) == 4 | |
* true | |
* | |
* >>> blockCount(S.shapeT) == 4 | |
* true | |
* | |
* >>> blockCount(S.shapeO) == 4 | |
* true | |
* | |
* >>> blockCount(S.shapeZ) == 4 | |
* true | |
* | |
* >>> blockCount(S.shapeL) == 4 | |
* true | |
* | |
* >>> blockCount(S.shapeS) == 4 | |
* true | |
* | |
* }}} | |
**/ | |
def blockCount(shape: Shape): Int = { | |
def countInRow(row: List[Color]): Int = { | |
row match { | |
case Nil => 0 | |
case Transparent :: row => countInRow(row) | |
case _ :: row => 1 + countInRow(row) | |
} | |
} | |
shape match { | |
case Nil => 0 | |
case row :: rows => countInRow(row) + blockCount(rows) | |
} | |
} | |
// 5. wellStructured | |
// 6 & 7. rotate | |
// 8. shiftSE | |
// 9. shiftNW | |
// 10. padTo | |
// 11. overlap | |
// 12. combine | |
} |
Author
wakita
commented
Oct 5, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment