Skip to content

Commit

Permalink
long loop...
Browse files Browse the repository at this point in the history
  • Loading branch information
EParisot committed Jul 10, 2019
1 parent 2de47a6 commit 2c71b99
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 73 deletions.
149 changes: 129 additions & 20 deletions algo.go
Expand Up @@ -25,49 +25,158 @@ func (env *Env) botPlayer() {
func (env *Env) algo() {
env.buildFinished()
//print(env.globalManDist())
env.aStar()
}

func (env *Env) aStar() {
var closedList []*cell
var openList []*cell
var closedList []*grid
var openList []*grid
// Append start node to open list
env.grid[0].cost = 0
env.grid[0].heuristic = env.globalManDist()
openList = append(openList, env.grid[0])
env.grid.cost = 0
env.grid.heuristic = env.globalManDist(env.grid)
openList = append(openList, env.grid)
lastPos := make([]int, 2)

for len(openList) != 0 {
// Sort open list by heuristic
// sort openList
sort.Slice(openList, func(i, j int) bool {
return openList[i].heuristic < openList[j].heuristic
})
// Unstack first cell of open list
currPos := openList[0]
openList[0] = nil
openList = openList[1:]
currGrid := openList[0]
openList = openList[:0]

env.grid = currGrid
//DEBUG
/*fmt.Println(currGrid.mapping[0].X, ", ", currGrid.mapping[0].Y, currGrid.cost, "; ", currGrid.heuristic)
for {
time.Sleep(time.Second)
if ebiten.IsKeyPressed(ebiten.KeyControl) {
break
}
}*/
// Check end
if env.isFinished() {
closedList = append(closedList, currPos)
closedList = append(closedList, currGrid)
fmt.Println("aStar done")
return
}
//for each possible move
// if already present in closedList
// then continue
// elif already present in openList with lower cost
// then continue
//
// append move to openList
//append move to closedList
movesList := env.getMoves(currGrid, lastPos)
for _, newGrid := range movesList {
// if already present in closedList
i := isPresentID(newGrid, closedList)
if i >= 0 {
//fmt.Println("present in closed")
continue
}
// elif already present in openList
i = isPresentID(newGrid, openList)
if i >= 0 {
if openList[i].cost < newGrid.cost {
continue
} else {
openList[i] = newGrid
continue
}
}
// append move to openList
openList = append(openList, newGrid)
}
//append currGrid to closedList
closedList = append(closedList, currGrid)
lastPos[0] = currGrid.mapping[0].X
lastPos[1] = currGrid.mapping[0].Y
}
fmt.Println("aStar returned no solution")
}

func isPresentID(currGrid *grid, gridList []*grid) int {
for i, grid := range gridList {
for cell := 0; cell < len(currGrid.mapping); cell++ {
if grid.mapping[cell] == currGrid.mapping[cell] {
return i
}
}
}
return -1
}

func (env *Env) getMoves(currGrid *grid, lastPos []int) []*grid {
var gridList []*grid
for direction := 1; direction < 5; direction++ {
if env.checkMove(currGrid, direction) >= 0 {
//DEBUG
/*fmt.Println(direction)
for i := 0; i < len(currGrid.mapping); i++ {
print(currGrid.mapping[i].X, ", ", currGrid.mapping[i].Y, "; ", currGrid.cost, ", ", currGrid.heuristic)
}
print("\n")*/

newGrid := env.virtualMove(currGrid, direction)

/*for i := 0; i < len(newGrid.mapping); i++ {
print(newGrid.mapping[i].X, ", ", newGrid.mapping[i].Y, "; ", newGrid.cost, ", ", newGrid.heuristic)
}
print("\n")*/

// append newGrid to list
if lastPos[0] != newGrid.mapping[0].X || lastPos[1] != newGrid.mapping[0].Y {
gridList = append(gridList, newGrid)
}
}
}
return gridList
}

func (env *Env) virtualMove(currGrid *grid, direction int) *grid {
newGrid := copyGrid(currGrid)
i := env.checkMove(newGrid, direction)
if i >= 0 {
switch {
case direction == UP:
newGrid.mapping[0].Y++
newGrid.mapping[i].Y--
case direction == DOWN:
newGrid.mapping[0].Y--
newGrid.mapping[i].Y++
case direction == LEFT:
newGrid.mapping[0].X++
newGrid.mapping[i].X--
case direction == RIGHT:
newGrid.mapping[0].X--
newGrid.mapping[i].X++
}
newGrid.cost = newGrid.cost + 1
newGrid.heuristic = newGrid.cost + env.globalManDist(newGrid)
}
return newGrid
}

func copyGrid(srcGrid *grid) *grid {
newGrid := &grid{}
newGrid.mapping = make([]*cell, len(srcGrid.mapping))
for i := 0; i < len(srcGrid.mapping); i++ {
newCell := cell{}
newCell.X = srcGrid.mapping[i].X
newCell.Y = srcGrid.mapping[i].Y
newCell.cellImg = srcGrid.mapping[i].cellImg
newGrid.mapping[i] = &newCell
}
newGrid.cost = srcGrid.cost
newGrid.heuristic = srcGrid.heuristic
return newGrid
}

func manhattanDistance(a, b *cell) int {
return int(math.Abs(float64(a.X)-float64(b.X)) +
math.Abs(float64(a.Y)-float64(b.Y)))
}

func (env *Env) globalManDist() int {
func (env *Env) globalManDist(currGrid *grid) int {
gManDist := 0
for id := 0; id < len(env.grid); id++ {
gManDist += manhattanDistance(env.grid[id], env.finishedMap[id])
for id := 0; id < len(currGrid.mapping); id++ {
gManDist += manhattanDistance(currGrid.mapping[id], env.finishedMap.mapping[id])
}
return gManDist
}
5 changes: 5 additions & 0 deletions go.mod
Expand Up @@ -3,7 +3,12 @@ module github.com/EParisot/N-Puzzle
go 1.12

require (
github.com/guregu/null v3.4.0+incompatible // indirect
github.com/hajimehoshi/ebiten v1.9.3
github.com/lib/pq v1.1.1 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/oliamb/cutter v0.2.2
github.com/satori/go.uuid v1.2.0 // indirect
github.com/stretchr/testify v1.3.0 // indirect
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f
)
15 changes: 15 additions & 0 deletions go.sum
@@ -1,3 +1,5 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-gl/glfw v0.0.0-20181213070059-819e8ce5125f h1:7MsFMbSn8Lcw0blK4+NEOf8DuHoOBDhJsHz04yh13pM=
github.com/go-gl/glfw v0.0.0-20181213070059-819e8ce5125f/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/gofrs/flock v0.7.0 h1:pGFUjl501gafK9HBt1VGL1KCOd/YhIooID+xgyJCf3g=
Expand All @@ -8,6 +10,8 @@ github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORR
github.com/gopherjs/gopherwasm v0.1.1/go.mod h1:kx4n9a+MzHH0BJJhvlsQ65hqLFXDO/m256AsaDPQ+/4=
github.com/gopherjs/gopherwasm v1.0.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI=
github.com/gopherjs/gopherwasm v1.1.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI=
github.com/guregu/null v3.4.0+incompatible h1:a4mw37gBO7ypcBlTJeZGuMpSxxFTV9qFfFKgWxQSGaM=
github.com/guregu/null v3.4.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM=
github.com/hajimehoshi/bitmapfont v1.1.1/go.mod h1:Hamfxgney7tDSmVOSDh2AWzoDH70OaC+P24zc02Gum4=
github.com/hajimehoshi/ebiten v1.9.3 h1:YijWGMBwH2XA1ZytUQFy33UDHeCSS6d4JZKH1wq38O0=
github.com/hajimehoshi/ebiten v1.9.3/go.mod h1:XxiJ4Eltvb1KmcD0i6F81eIB1asJhK47y5DC+FPkyso=
Expand All @@ -20,10 +24,21 @@ github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2Q
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/oliamb/cutter v0.2.2 h1:Lfwkya0HHNU1YLnGv2hTkzHfasrSMkgv4Dn+5rmlk3k=
github.com/oliamb/cutter v0.2.2/go.mod h1:4BenG2/4GuRBDbVm/OPahDVqbrOemzpPiG5mi1iryBU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f h1:QatZ4lsJBY3x1+Imst9g95+vUl7m52dqM9Pi4aSMW8w=
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f/go.mod h1:BNLmYJ8oMJPIPpNx5968jCyUhwEU1XT3YsuOqtbo5qo=
golang.org/x/exp v0.0.0-20180710024300-14dda7b62fcd/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20180926015637-991ec62608f3/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
Expand Down
84 changes: 48 additions & 36 deletions graphic.go
Expand Up @@ -33,10 +33,10 @@ func (env *Env) update(screen *ebiten.Image) error {
//Handle controls
env.getKey()

for i := range env.grid {
for i := range env.grid.mapping {
//Add cells
env.addSquare(float64(env.grid[i].X*(env.sizeWindows/env.size)),
float64(env.grid[i].Y*(env.sizeWindows/env.size)),
env.addSquare(float64(env.grid.mapping[i].X*(env.sizeWindows/env.size)),
float64(env.grid.mapping[i].Y*(env.sizeWindows/env.size)),
square,
screen,
i,
Expand All @@ -48,61 +48,73 @@ func (env *Env) update(screen *ebiten.Image) error {

func (env *Env) getKey() {
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
env.moveCell(UP)
env.moveCell(env.grid, UP)
} else if inpututil.IsKeyJustPressed(ebiten.KeyDown) {
env.moveCell(DOWN)
env.moveCell(env.grid, DOWN)
} else if inpututil.IsKeyJustPressed(ebiten.KeyLeft) {
env.moveCell(LEFT)
env.moveCell(env.grid, LEFT)
} else if inpututil.IsKeyJustPressed(ebiten.KeyRight) {
env.moveCell(RIGHT)
env.moveCell(env.grid, RIGHT)
} else if env.isFinished() {
return
}
}

func (env *Env) moveCell(direction int) {

if direction == UP && env.grid[0].Y != env.size-1 {
for i := range env.grid {
if env.grid[i].X == env.grid[0].X && env.grid[i].Y == env.grid[0].Y+1 {
env.grid[0].Y++
env.grid[i].Y--
break
func (env *Env) checkMove(currGrid *grid, move int) int {
if move == UP && currGrid.mapping[0].Y != env.size-1 {
for i := range currGrid.mapping {
if currGrid.mapping[i].X == currGrid.mapping[0].X && currGrid.mapping[i].Y == currGrid.mapping[0].Y+1 {
return i
}
}
} else if direction == DOWN && env.grid[0].Y != 0 {
for i := range env.grid {
if env.grid[i].X == env.grid[0].X && env.grid[i].Y == env.grid[0].Y-1 {
env.grid[0].Y--
env.grid[i].Y++
break
} else if move == DOWN && currGrid.mapping[0].Y != 0 {
for i := range currGrid.mapping {
if currGrid.mapping[i].X == currGrid.mapping[0].X && currGrid.mapping[i].Y == currGrid.mapping[0].Y-1 {
return i
}
}
} else if direction == LEFT && env.grid[0].X != env.size-1 {
for i := range env.grid {
if env.grid[i].X == env.grid[0].X+1 && env.grid[i].Y == env.grid[0].Y {
env.grid[0].X++
env.grid[i].X--
break
} else if move == LEFT && currGrid.mapping[0].X != env.size-1 {
for i := range currGrid.mapping {
if currGrid.mapping[i].X == currGrid.mapping[0].X+1 && currGrid.mapping[i].Y == currGrid.mapping[0].Y {
return i
}
}
} else if direction == RIGHT && env.grid[0].X != 0 {
for i := range env.grid {
if env.grid[i].X == env.grid[0].X-1 && env.grid[i].Y == env.grid[0].Y {
env.grid[0].X--
env.grid[i].X++
break
} else if move == RIGHT && currGrid.mapping[0].X != 0 {
for i := range currGrid.mapping {
if currGrid.mapping[i].X == currGrid.mapping[0].X-1 && currGrid.mapping[i].Y == currGrid.mapping[0].Y {
return i
}
}
}
return -1
}

func (env *Env) moveCell(currGrid *grid, direction int) {
i := env.checkMove(currGrid, direction)
if i >= 0 {
switch {
case direction == UP:
currGrid.mapping[0].Y++
currGrid.mapping[i].Y--
case direction == DOWN:
currGrid.mapping[0].Y--
currGrid.mapping[i].Y++
case direction == LEFT:
currGrid.mapping[0].X++
currGrid.mapping[i].X--
case direction == RIGHT:
currGrid.mapping[0].X--
currGrid.mapping[i].X++
}
}
}

func (env *Env) addSquare(x float64, y float64, square *ebiten.Image, screen *ebiten.Image, i int) {

var err error

if i != 0 {
square, err = ebiten.NewImageFromImage(env.grid[i].cellImg, ebiten.FilterDefault)
square, err = ebiten.NewImageFromImage(env.grid.mapping[i].cellImg, ebiten.FilterDefault)
if err != nil {
log.Fatal("Error new images", err)
}
Expand Down Expand Up @@ -139,7 +151,7 @@ func (env *Env) cropImage(images string) {
countCell := 0
offset := 0
way := 0
for i := range env.grid {
for i := range env.grid.mapping {
if i == 0 {
continue
}
Expand All @@ -156,7 +168,7 @@ func (env *Env) cropImage(images string) {
os.Exit(1)
}
// Each cell fill with a square of the image
env.grid[i].cellImg = cImg
env.grid.mapping[i].cellImg = cImg

if countCell+offset == env.size-1 {
countCell = 0
Expand Down

0 comments on commit 2c71b99

Please sign in to comment.