Created
September 19, 2015 03:41
-
-
Save itarato/01a7f02300e2b9fd9374 to your computer and use it in GitHub Desktop.
Unblock Me iOS game level 605 solver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "log" | |
| "math/rand" | |
| ) | |
| const MOVE_VERTICALLY = true | |
| const MOVE_HORIZONTALLY = !MOVE_VERTICALLY | |
| const MOVE_UPLEFT = -1 | |
| const MOVE_DOWNRIGHT = 1 | |
| const m_size_w = 6 | |
| const m_size_h = 6 | |
| var matrix [][]uint = [][]uint{ | |
| []uint{1, 2, 3, 3, 3, 0}, | |
| []uint{1, 2, 0, 4, 5, 0}, | |
| []uint{1, 6, 6, 4, 5, 0}, | |
| []uint{7, 7, 8, 0, 5, 0}, | |
| []uint{0, 0, 8, 9, 9, 0}, | |
| []uint{0, 10, 10, 11, 11, 0}, | |
| } | |
| type Point struct { | |
| X uint | |
| Y uint | |
| } | |
| var point_map_h = &Point{Y: 0, X: MOVE_DOWNRIGHT} | |
| var point_map_v = &Point{Y: MOVE_DOWNRIGHT, X: 0} | |
| var point_map map[bool]*Point = map[bool]*Point{ | |
| MOVE_VERTICALLY: point_map_v, | |
| MOVE_HORIZONTALLY: point_map_h, | |
| } | |
| type BlockProperty struct { | |
| dir bool | |
| length uint | |
| pos Point | |
| } | |
| type MovableMemory struct { | |
| left bool | |
| right bool | |
| id uint | |
| } | |
| var blocks map[uint]*BlockProperty = make(map[uint]*BlockProperty) | |
| func main() { | |
| register_blocks() | |
| for step := 0; ; step++ { | |
| make_move() | |
| if is_solution() { | |
| pretty_print_blocks() | |
| log.Println("Solution found after step", step) | |
| break | |
| } | |
| } | |
| } | |
| func pretty_print_blocks() { | |
| out := "\n" | |
| for _, row := range matrix { | |
| for _, cell := range row { | |
| if cell == 0 { | |
| out += " " | |
| } else if blocks[cell].dir == MOVE_HORIZONTALLY { | |
| out += "-" | |
| } else { | |
| out += "|" | |
| } | |
| } | |
| out += "\n" | |
| } | |
| log.Println(out) | |
| } | |
| func register_blocks() { | |
| var i, j uint | |
| for i = 0; i < m_size_h; i++ { | |
| for j = 0; j < m_size_w; j++ { | |
| block_id := matrix[i][j] | |
| // Empty field. | |
| if block_id == 0 { | |
| continue | |
| } | |
| // Already registered block. | |
| if _, ok := blocks[block_id]; ok { | |
| continue | |
| } | |
| prop := &BlockProperty{} | |
| var block_dir_map Point | |
| if i < m_size_h-1 && matrix[i+1][j] == block_id { | |
| prop.dir = MOVE_VERTICALLY | |
| block_dir_map = Point{X: 0, Y: 1} | |
| } else { | |
| prop.dir = MOVE_HORIZONTALLY | |
| block_dir_map = Point{X: 1, Y: 0} | |
| } | |
| prop.pos = Point{X: j, Y: i} | |
| var length uint = 0 | |
| for matrix[i+length*block_dir_map.Y][j+length*block_dir_map.X] == block_id { | |
| length++ | |
| } | |
| prop.length = length | |
| blocks[block_id] = prop | |
| } | |
| } | |
| } | |
| func make_move() { | |
| selected, move_selected := select_for_move() | |
| // log.Println("Move", selected.id, "to", move_selected) | |
| mask_block(selected.id, 0) | |
| props := blocks[selected.id] | |
| move_map := point_map[props.dir] | |
| props.pos.Y = uint(int(props.pos.Y) + int(move_map.Y)*move_selected) | |
| props.pos.X = uint(int(props.pos.X) + int(move_map.X)*move_selected) | |
| mask_block(selected.id, selected.id) | |
| } | |
| func get_movables() []MovableMemory { | |
| var movable []MovableMemory | |
| for block_id, _ := range blocks { | |
| if left, right := is_movable(block_id); left || right { | |
| movable = append(movable, MovableMemory{left: left, right: right, id: block_id}) | |
| } | |
| } | |
| return movable | |
| } | |
| func select_for_move() (MovableMemory, int) { | |
| movable := get_movables() | |
| selected := movable[rand.Intn(len(movable))] | |
| var move_options []int | |
| if selected.left { | |
| move_options = append(move_options, MOVE_UPLEFT) | |
| } | |
| if selected.right { | |
| move_options = append(move_options, MOVE_DOWNRIGHT) | |
| } | |
| move_selected := move_options[rand.Intn(len(move_options))] | |
| return selected, move_selected | |
| } | |
| // Return: upleft, downright | |
| func is_movable(block_id uint) (bool, bool) { | |
| prop := blocks[block_id] | |
| move_map := point_map[prop.dir] | |
| move_left_y := prop.pos.Y - move_map.Y | |
| move_left_x := prop.pos.X - move_map.X | |
| move_right_y := prop.pos.Y + move_map.Y*(prop.length) | |
| move_right_x := prop.pos.X + move_map.X*(prop.length) | |
| var left, right bool | |
| left = in_range(move_left_x, m_size_w) && in_range(move_left_y, m_size_h) && matrix[move_left_y][move_left_x] == 0 | |
| right = in_range(move_right_x, m_size_w) && in_range(move_right_y, m_size_h) && matrix[move_right_y][move_right_x] == 0 | |
| return left, right | |
| } | |
| func in_range(n, limit uint) bool { | |
| return n >= 0 && n < limit | |
| } | |
| func mask_block(block_id uint, mask uint) { | |
| props := blocks[block_id] | |
| move_map := point_map[props.dir] | |
| var i uint | |
| for i = 0; i < props.length; i++ { | |
| matrix[props.pos.Y+(move_map.Y*i)][props.pos.X+(move_map.X*i)] = mask | |
| } | |
| } | |
| func is_solution() bool { | |
| return matrix[2][5] == 6 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment