テトリスをGo言語で作る

テトリスをgo言語で作る

この記事は [ドワンゴ Advent Calendar](http://qiita.com/advent-calendar/2016/dwango) 16日目の記事です。

ニコニコ静画で開発をしている @kazuhei0108 です。

ここ1週間ほどGo言語を触ってみたので、その集大成？としてテトリスを作りました。

# 作ったもの

![Untitled5.gif](https://qiita-image-store.s3.amazonaws.com/0/47882/335c51bc-7fad-661b-5acc-67636f917c34.gif "Untitled5.gif")

ソースコードはこちら https://github.com/kazuhei/go-tetoris

テトリスを作ろうと思ったのは　http://qiita.com/kurehajime/items/a02eaae3f0c17750c07e の記事を見たからです。

2番煎じです。

GoでのCUIのアプリケーションの作り方、goroutineの使い方などとても参考になりました。

# 作ってみた感想

## Go言語について

### for文
日頃SwiftやJavascriptでmapやforeachに慣れてしまっているので、
for文で回さないといけない箇所がたくさん出てきて、辛かったです。

あとappend関数を`.`アクセスして動かない〜ってのを10回はやりましたね

```
// ダメ
list.append(element)

// 良い
list = append(list, element)
```

`[n][m]bool`のスライスが欲しいときに毎回for文回してたんですが、
もっと良いやり方あるんでしょうね...

### テスト
Go言語は`filename.go`に対して`filename_test.go`という名前で
テストファイルを作って、`go test`のコマンドを打つだけですぐテストができます。
しかも`go test -cover`を実行するとカバレッジが表示されるので、
カバレッジを上げるためにテスト書くぞーってなります。

![スクリーンショット 2016-12-15 21.20.37.png](https://qiita-image-store.s3.amazonaws.com/0/47882/45ebca7a-1831-e9c1-627e-ed175520467a.png "スクリーンショット 2016-12-15 21.20.37.png")

あと、Goのテストは外部のライブラリなどを使わずに、testingというライブラリだけを使って、Table Driven Testという入力と出力を表にして順番にやっていくというようなテストが推奨されているようです。

```go

type transformPointsTestCase struct {
	points []point
	expect []point
}

func TestRemoveFilledRows(t *testing.T) {
	var stage = newStage(3, 3)
	testCases := []transformPointsTestCase{
		{ // 列を埋めていないときは何も起きない
			[]point{{X: 0, Y: 0}},
			[]point{{X: 0, Y: 0}},
		},
		{ // 列を埋めていて、さらに上に載っているときはそれが落ちてくる
			[]point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 2, Y: 1}},
			[]point{{X: 0, Y: 1}},
		},
		{ // 2列を埋めているときは2段消えて、上のブロックは2段ずれる
			[]point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 2, Y: 1}, {X: 0, Y: 2}, {X: 1, Y: 2}, {X: 2, Y: 2}},
			[]point{{X: 0, Y: 2}},
		},
	}
	for i, testCase := range testCases {
		actual := stage.removeFilledRows(testCase.points, 1)
		if !reflect.DeepEqual(testCase.expect, actual) {
			t.Errorf("#%d: got:%v expect:%v", i, actual, testCase.expect)
		}
	}
}

```
地道ですが、分かりやすくて良いです。


## Visual Studio Codeについて
今回Go言語を書くにあたって最初はAtomで書こうと思っていたのですが、
Goのプラグイン入れても、`go get`した外部のライブラリの補完が効きませんでした。
`$GOPATH`の設定が悪かったとかなにかあったのかもしれませんが調べるのも面倒だったので、
有識者( @koki_cheese )に聞いたところVisual Studio Codeが良いという話だったので、試しに使ってみました。
結果としては、補完も効いてサクサク書けたので良かったです。

## テトリスについて
### プログラム
ブロック回転させたり, 1列揃ったら消して、その上似合ったブロックを下にずらしたり等
作り始める前の想定よりも割りとめんどくさかったですね。
Javascriptで200行で書くサンプル等があったので、余裕っしょと思ったのですが、
結構大変でした。

### トリビア
プログラム書いているときに、上から降ってくるブロックになんて名前つけようかな、
と思ってググったら、あれは`テトリミノ`という名前がちゃんとついているんだということを知りました。あとテトリスはロシア発らしいです。

# 学ぶのに参考にしたもの

## サイト
- [はじめてのGo言語](http://cuto.unirita.co.jp/gostudy/)
- [はじめてのGo―シンプルな言語仕様，型システム，並行処理](http://gihyo.jp/dev/feature/01/go_4beginners)

## 書籍
- [みんなのGo言語【現場で使える実践テクニック】](http://amzn.to/2hzvBH5)  

テストのところは殆どこの本を見て書きましたが、とても参考になりました。

# 終わりに

いつもWebやアプリを開発していて、ゲーム等は作ったことが無かったので、ゲームを作るということ自体面白かったです。

Goの書き方が分かってきたので、次はWeb書いてみようかなと思っています。

# 宣伝
自分が所属するニコニコ静画では現在コミケC91との連動企画を行っています。

「[ニコニコ漫画＠C91](http://seiga.nicovideo.jp/manga/expo/c91/)」

![image](https://qiita-image-store.s3.amazonaws.com/0/13956/5cebb345-b594-047b-db28-e1d6cef62122.png)

自分はiOSアプリのビューワー部分を担当しています。コミケに行く方はぜひ使ってみてください。