examples/2048/2048/tile.go
func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) bool {
	vx, vy := dir.Vector()
	tx := []int{}
	ty := []int{}
	for i := 0; i < 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)))
	}

	moved := false
	for _, j := range ty {
		for _, i := range tx {
			t := tileAt(tiles, i, j)
			if t == nil {
				continue
			}
			if t.next != (TileData{}) {
				panic("not reach")
			}
			if t.IsMoving() {
				panic("not reach")
			}
			// (ii, jj) is the next position for tile t.
			// (ii, jj) is updated until a mergeable tile is found or
			// the tile t can't be moved any more.
			ii := i
			jj := j
			for {
				ni := ii + vx
				nj := jj + vy
				if ni < 0 || ni >= size || nj < 0 || nj >= size {
					break
				}
				tt := currentOrNextTileAt(tiles, ni, nj)
				if tt == nil {
					ii = ni
					jj = nj
					moved = true
					continue
				}
				if t.current.value != tt.current.value {
					break
				}
				if 0 < tt.movingCount && tt.current.value != tt.next.value {
					// tt is already being merged with another tile.
					// Break here without updating (ii, jj).
					break
				}
				ii = ni
				jj = nj
				moved = true
				break
			}
			// next is the next state of the tile t.
			next := TileData{}
			next.value = t.current.value
			// If there is a tile at the next position (ii, jj), this should be
			// mergeable. Let's merge.
			if tt := currentOrNextTileAt(tiles, ii, jj); tt != t && tt != nil {
				next.value = t.current.value + tt.current.value
				tt.next.value = 0
				tt.next.x = ii
				tt.next.y = jj
				tt.movingCount = maxMovingCount
			}
			next.x = ii
			next.y = jj
			if t.current != next {
				t.next = next
				t.movingCount = maxMovingCount
			}
		}
	}
	if !moved {
		for t := range tiles {
			t.next = TileData{}
			t.movingCount = 0
		}
	}
	return moved
}
func MoveTiles(tiles map[*Tile]struct{}, size int, dir Dir) bool {
	vx, vy := dir.Vector()
	tx := []int{}
	ty := []int{}
	for i := 0; i < 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)))
	}

	moved := false
	for _, j := range ty {
		for _, i := range tx {
			t := tileAt(tiles, i, j)
			if t == nil {
				continue
			}
			if t.next != (TileData{}) {
				panic("not reach")
			}
			if t.IsMoving() {
				panic("not reach")
			}
			// (ii, jj) is the next position for tile t.
			// (ii, jj) is updated until a mergeable tile is found or
			// the tile t can't be moved any more.
			ii := i
			jj := j
			for {
				ni := ii + vx
				nj := jj + vy
				if ni < 0 || ni >= size || nj < 0 || nj >= size {
					break
				}
				tt := currentOrNextTileAt(tiles, ni, nj)
				if tt == nil {
					ii = ni
					jj = nj
					moved = true
					continue
				}
				if t.current.value != tt.current.value {
					break
				}
				if 0 < tt.movingCount && tt.current.value != tt.next.value {
					// tt is already being merged with another tile.
					// Break here without updating (ii, jj).
					break
				}
				ii = ni
				jj = nj
				moved = true
				break
			}
			// next is the next state of the tile t.
			next := TileData{}
			next.value = t.current.value
			// If there is a tile at the next position (ii, jj), this should be
			// mergeable. Let's merge.
			if tt := currentOrNextTileAt(tiles, ii, jj); tt != t && tt != nil {
				next.value = t.current.value + tt.current.value
				tt.next.value = 0
				tt.next.x = ii
				tt.next.y = jj
				tt.movingCount = maxMovingCount
			}
			next.x = ii
			next.y = jj
			if t.current != next {
				t.next = next
				t.movingCount = maxMovingCount
			}
		}
	}
	if !moved {
		for t := range tiles {
			t.next = TileData{}
			t.movingCount = 0
		}
	}
	return moved
}
func MoveTiles ( tiles map [ * Tile ] struct { } , size int , dir Dir ) bool { vx , vy := dir . Vector ( ) tx := [ ] int { } ty := [ ] int { } for i := 0 ; i < 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 ) ) ) } moved := false for _ , j := range ty { for _ , i := range tx { t := tileAt ( tiles , i , j ) if t == nil { continue } if t . next != ( TileData { } ) { panic ( " " ) } if t . IsMoving ( ) { panic ( " " ) } // (ii, jj) is the next position for tile t. // (ii, jj) is updated until a mergeable tile is found or // the tile t can't be moved any more. ii := i jj := j for { ni := ii + vx nj := jj + vy if ni < 0 || ni >= size || nj < 0 || nj >= size { break } tt := currentOrNextTileAt ( tiles , ni , nj ) if tt == nil { ii = ni jj = nj moved = true continue } if t . current . value != tt . current . value { break } if 0 < tt . movingCount && tt . current . value != tt . next . value { // tt is already being merged with another tile. // Break here without updating (ii, jj). break } ii = ni jj = nj moved = true break } // next is the next state of the tile t. next := TileData { } next . value = t . current . value // If there is a tile at the next position (ii, jj), this should be // mergeable. Let's merge. if tt := currentOrNextTileAt ( tiles , ii , jj ) ; tt != t && tt != nil { next . value = t . current . value + tt . current . value tt . next . value = 0 tt . next . x = ii tt . next . y = jj tt . movingCount = maxMovingCount } next . x = ii next . y = jj if t . current != next { t . next = next t . movingCount = maxMovingCount } } } if ! moved { for t := range tiles { t . next = TileData { } t . movingCount = 0 } } return moved }
// MoveTiles moves tiles in the given tiles map if possible.
// MoveTiles returns true if there are tiles that are to move, otherwise false.
//
// When MoveTiles is called, all tiles must not be about to move.
MoveTiles moves tiles in the given tiles map if possible . MoveTiles returns true if there are tiles that are to move otherwise false . When MoveTiles is called all tiles must not be about to move .