diff --git a/examples/2048/2048/board.go b/examples/2048/2048/board.go index 58a9c30e1..109ae3d2e 100644 --- a/examples/2048/2048/board.go +++ b/examples/2048/2048/board.go @@ -17,6 +17,7 @@ package twenty48 import ( "fmt" "math/rand" + "sort" "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/ebitenutil" @@ -66,20 +67,81 @@ func (b *Board) addRandomTile() bool { return true } +func tileAt(tiles map[*Tile]struct{}, x, y int) *Tile { + for t := range tiles { + if t.x == x && t.y == y { + return t + } + } + return nil +} + +func (b *Board) tileAt(x, y int) *Tile { + return tileAt(b.tiles, x, y) +} + func (b *Board) Move(dir Dir) { + vx, vy := dir.Vector() + tx := []int{} + ty := []int{} + for i := 0; i < b.size; i++ { + tx = append(tx, i) + ty = append(ty, i) + } + if vx > 0 { + sort.Sort(sort.Reverse(sort.IntSlice(tx))) + } + 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) + if t == nil { + continue + } + ii := i + jj := j + for { + ni := ii + vx + nj := jj + vy + if ni < 0 || ni >= b.size || nj < 0 || nj >= b.size { + break + } + tt := b.tileAt(ni, nj) + if tt == nil { + ii = ni + jj = nj + continue + } + nt := tileAt(nextTiles, ni, nj) + if t.value == tt.value && (nt == nil || !merged[nt]) { + ii = ni + jj = nj + } + break + } + if tt := b.tileAt(ii, jj); tt != t && tt != nil { + t.value += tt.value + merged[t] = true + delete(nextTiles, tt) + } + t.x = ii + t.y = jj + nextTiles[t] = struct{}{} + } + } + b.tiles = nextTiles b.addRandomTile() } func (b *Board) Draw(screen *ebiten.Image) error { - posToTile := map[int]*Tile{} - for t := range b.tiles { - i := t.x + t.y*b.size - posToTile[i] = t - } str := "" for j := 0; j < b.size; j++ { for i := 0; i < b.size; i++ { - t := posToTile[i+j*b.size] + t := b.tileAt(i, j) if t != nil { str += fmt.Sprintf("[%4d]", t.value) } else {