From d9ee460b20c641a10b191c55eddcc7f553a161e8 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 29 Jul 2016 00:00:12 +0900 Subject: [PATCH] examples/2048: Add tests --- examples/2048/2048/board.go | 17 ++- examples/2048/2048/board_test.go | 199 +++++++++++++++++++++++++++++++ examples/2048/2048/input.go | 14 +++ examples/2048/2048/tile.go | 8 ++ 4 files changed, 232 insertions(+), 6 deletions(-) create mode 100644 examples/2048/2048/board_test.go diff --git a/examples/2048/2048/board.go b/examples/2048/2048/board.go index c30edd3fc..2b13a6157 100644 --- a/examples/2048/2048/board.go +++ b/examples/2048/2048/board.go @@ -80,11 +80,11 @@ func (b *Board) tileAt(x, y int) *Tile { return tileAt(b.tiles, x, y) } -func (b *Board) Move(dir Dir) { +func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) map[*Tile]struct{} { vx, vy := dir.Vector() tx := []int{} ty := []int{} - for i := 0; i < b.size; i++ { + for i := 0; i < size; i++ { tx = append(tx, i) ty = append(ty, i) } @@ -94,11 +94,12 @@ func (b *Board) Move(dir Dir) { if vy > 0 { sort.Sort(sort.Reverse(sort.IntSlice(ty))) } + nextTiles := map[*Tile]struct{}{} merged := map[*Tile]bool{} for _, j := range ty { for _, i := range tx { - t := b.tileAt(i, j) + t := tileAt(tiles, i, j) if t == nil { continue } @@ -107,7 +108,7 @@ func (b *Board) Move(dir Dir) { for { ni := ii + vx nj := jj + vy - if ni < 0 || ni >= b.size || nj < 0 || nj >= b.size { + if ni < 0 || ni >= size || nj < 0 || nj >= size { break } tt := tileAt(nextTiles, ni, nj) @@ -125,7 +126,7 @@ func (b *Board) Move(dir Dir) { } break } - if tt := b.tileAt(ii, jj); tt != t && tt != nil { + if tt := tileAt(tiles, ii, jj); tt != t && tt != nil { t.value += tt.value merged[t] = true delete(nextTiles, tt) @@ -135,7 +136,11 @@ func (b *Board) Move(dir Dir) { nextTiles[t] = struct{}{} } } - b.tiles = nextTiles + return nextTiles +} + +func (b *Board) Move(dir Dir) { + b.tiles = MoveTiles(b.tiles, b.size, dir) b.addRandomTile() } diff --git a/examples/2048/2048/board_test.go b/examples/2048/2048/board_test.go new file mode 100644 index 000000000..07f93f446 --- /dev/null +++ b/examples/2048/2048/board_test.go @@ -0,0 +1,199 @@ +// Copyright 2016 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package twenty48_test + +import ( + . "github.com/hajimehoshi/ebiten/examples/2048/2048" + + "fmt" + "testing" +) + +func cellsToTiles(cells []int, size int) map[*Tile]struct{} { + tiles := map[*Tile]struct{}{} + for j := 0; j < size; j++ { + for i := 0; i < size; i++ { + c := cells[i+j*size] + if c == 0 { + continue + } + t := NewTile(c, i, j) + tiles[t] = struct{}{} + } + } + return tiles +} + +func tilesToCells(tiles map[*Tile]struct{}, size int) []int { + cells := make([]int, size*size) + for t := range tiles { + x, y := t.Pos() + cells[x+y*size] = t.Value() + } + return cells +} + +func TestMoveTiles(t *testing.T) { + const size = 4 + testCases := []struct { + Dir Dir + Input []int + Want []int + }{ + { + Dir: DirUp, + Input: []int{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }, + Want: []int{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }, + }, + { + Dir: DirRight, + Input: []int{ + 2, 0, 0, 0, + 0, 2, 0, 0, + 0, 0, 2, 0, + 0, 0, 0, 2, + }, + Want: []int{ + 0, 0, 0, 2, + 0, 0, 0, 2, + 0, 0, 0, 2, + 0, 0, 0, 2, + }, + }, + { + Dir: DirRight, + Input: []int{ + 0, 0, 0, 2, + 0, 0, 2, 2, + 0, 2, 2, 2, + 2, 2, 2, 2, + }, + Want: []int{ + 0, 0, 0, 2, + 0, 0, 0, 4, + 0, 0, 2, 4, + 0, 0, 4, 4, + }, + }, + { + Dir: DirLeft, + Input: []int{ + 0, 0, 0, 2, + 0, 0, 2, 2, + 0, 2, 2, 2, + 2, 2, 2, 2, + }, + Want: []int{ + 2, 0, 0, 0, + 4, 0, 0, 0, + 4, 2, 0, 0, + 4, 4, 0, 0, + }, + }, + { + Dir: DirRight, + Input: []int{ + 4, 8, 8, 4, + 8, 8, 4, 4, + 4, 4, 8, 8, + 8, 4, 4, 8, + }, + Want: []int{ + 0, 4, 16, 4, + 0, 0, 16, 8, + 0, 0, 8, 16, + 0, 8, 8, 8, + }, + }, + { + Dir: DirDown, + Input: []int{ + 4, 8, 8, 4, + 8, 8, 4, 4, + 4, 4, 8, 8, + 8, 4, 4, 8, + }, + Want: []int{ + 4, 0, 8, 0, + 8, 0, 4, 0, + 4, 16, 8, 8, + 8, 8, 4, 16, + }, + }, + { + Dir: DirLeft, + Input: []int{ + 4, 8, 8, 4, + 8, 8, 4, 4, + 4, 4, 8, 8, + 8, 4, 4, 8, + }, + Want: []int{ + 4, 16, 4, 0, + 16, 8, 0, 0, + 8, 16, 0, 0, + 8, 8, 8, 0, + }, + }, + { + Dir: DirUp, + Input: []int{ + 4, 8, 8, 4, + 8, 8, 4, 4, + 4, 4, 8, 8, + 8, 4, 4, 8, + }, + Want: []int{ + 4, 16, 8, 8, + 8, 8, 4, 16, + 4, 0, 8, 0, + 8, 0, 4, 0, + }, + }, + { + Dir: DirUp, + Input: []int{ + 2, 4, 2, 4, + 4, 2, 4, 2, + 2, 4, 2, 4, + 4, 2, 4, 2, + }, + Want: []int{ + 2, 4, 2, 4, + 4, 2, 4, 2, + 2, 4, 2, 4, + 4, 2, 4, 2, + }, + }, + } + for _, test := range testCases { + tiles := cellsToTiles(test.Input, size) + want := tilesToCells(cellsToTiles(test.Want, size), size) + got := tilesToCells(MoveTiles(tiles, size, test.Dir), size) + if fmt.Sprint(got) != fmt.Sprint(want) { + t.Errorf("dir: %s, input: %v, got %v; want %v", test.Dir.String(), test.Input, got, want) + } + } +} diff --git a/examples/2048/2048/input.go b/examples/2048/2048/input.go index aa1d594d3..11682de43 100644 --- a/examples/2048/2048/input.go +++ b/examples/2048/2048/input.go @@ -27,6 +27,20 @@ const ( DirLeft ) +func (d Dir) String() string { + switch d { + case DirUp: + return "Up" + case DirRight: + return "Right" + case DirDown: + return "Down" + case DirLeft: + return "Left" + } + panic("not reach") +} + func (d Dir) Vector() (x, y int) { switch d { case DirUp: diff --git a/examples/2048/2048/tile.go b/examples/2048/2048/tile.go index b985c3874..835fd6bc6 100644 --- a/examples/2048/2048/tile.go +++ b/examples/2048/2048/tile.go @@ -27,3 +27,11 @@ func NewTile(value int, x, y int) *Tile { y: y, } } + +func (t *Tile) Value() int { + return t.value +} + +func (t *Tile) Pos() (int, int) { + return t.x, t.y +}