1 // jumpsaround.go - jumper game
    2 // (c) 2020 Alexander Kulbartsch
    3 // 
    4 // Slightly performace optimized version: valid jumpes checked bevore iteration.
    5 // added multithreading
    6 
    7 package main
    8 
    9 import (
   10     "fmt"
   11     "sync"
   12     "sync/atomic"
   13 )
   14 
   15 const SIZEX = 6
   16 const SIZEY = 5
   17 
   18 type boardt [SIZEX][SIZEY]int32
   19 var jump = [8][2]int32{{-1,-2}, {1,-2}, {-2,-1}, {2,-1}, {-2,1}, {2,1}, {-1,2}, {1,2}}
   20 var solutions int32  = 0
   21 var roundtrips int32 =  0
   22 
   23 var wg sync.WaitGroup                                                     // <<--
   24 
   25 
   26 func main() {
   27     fmt.Println("Hello, Jumper!")
   28     var board boardt // [SIZEX][SIZEY]int
   29     wg.Add(1)                                                             // <<--
   30     jumpto(board, 0, 0, 1)
   31     wg.Wait() // waiting for waitgroup processes                          // <<--
   32     fmt.Println("===== Solution #", solutions," (Roundtripps:", roundtrips, ") ====== ")    
   33     fmt.Println("I am done.")
   34 }
   35 
   36 
   37 func jumpto(board boardt, x, y, iter int32) {
   38 
   39     defer wg.Done()                                                       // <<--
   40 
   41     // ok - store position
   42     board[x][y] = iter
   43     
   44     // finished ?
   45     if iter >= SIZEX*SIZEY {
   46 
   47         // check for jumper roundtrips
   48         round := false
   49         for _, d := range jump {
   50             nx := x + d[0]
   51             ny := y + d[1]
   52             // check if position is on the board
   53             if nx<0 || nx>(SIZEX-1) || ny<0 || ny>(SIZEY-1) { continue }
   54             // detect roundtrip
   55             if board[nx][ny] == 1 { round = true; atomic.AddInt32(&roundtrips,1); break } // True
   56         }
   57 
   58         atomic.AddInt32(&solutions, 1)                                    // <<--
   59 
   60         printboard(board, round)
   61 
   62         return
   63     }
   64     
   65     // try next jump
   66     for _, d := range jump {
   67         nx := x + d[0]
   68         ny := y + d[1]
   69 
   70         // check if position is on the board
   71         if nx<0 || nx>(SIZEX-1) || ny<0 || ny>(SIZEY-1) { continue }
   72 
   73         //  check if new field position is still empty
   74         if board[nx][ny] != 0 { continue } // True
   75 
   76         wg.Add(1)                                                         // <<--
   77         go jumpto(board, nx, ny, iter + 1);                               // <<--
   78     }
   79     
   80     // this iteration is done
   81     board[x][y] = 0;
   82     
   83 }
   84 
   85 
   86 func printboard(board boardt, round bool) {
   87     if round == true { fmt.Println(" *** Roundtrip #", roundtrips, "*** ")
   88         fmt.Println("")
   89         for i := 0; i < SIZEY; i++ {
   90             for j := 0; j < SIZEX; j++ {
   91                 fmt.Printf("%2d:", board[j][i])
   92             }
   93             fmt.Println("")
   94         }
   95         fmt.Println("")
   96     }
   97 }
   98 
   99 // EOF