Skip to content

Instantly share code, notes, and snippets.

@wakita
Created October 5, 2019 03:56
Show Gist options
  • Save wakita/39c89d55cbd927474c9cd030239e19d4 to your computer and use it in GitHub Desktop.
Save wakita/39c89d55cbd927474c9cd030239e19d4 to your computer and use it in GitHub Desktop.
xxx
/*
プログラムの実行手順:
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
}
@wakita
Copy link
Author

wakita commented Oct 5, 2019

実行結果

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment