diff --git a/.goreleaser.yml b/.goreleaser.yml index d70894d..7eb83d5 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,20 +1,20 @@ -builds: - - binary: 4inarowgo - goos: - - windows - - darwin - - linux - goarch: - - amd64 - - 386 -archive: - format: zip - name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" - replacements: - amd64: 64-bit - 386: 32-bit - darwin: macOS -release: - github: - owner: y-hatano-github +builds: + - binary: 4inarowgo + goos: + - windows + - darwin + - linux + goarch: + - amd64 + - 386 +archive: + format: zip + name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" + replacements: + amd64: 64-bit + 386: 32-bit + darwin: macOS +release: + github: + owner: y-hatano-github name: 4-in-a-row-go \ No newline at end of file diff --git a/README.md b/README.md index 3d0f51a..64179b4 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,25 @@ -# 4-in-a-row-go -CLI game '4-in-a-row' written in go. - -## What is 4-in-a-row? -https://en.wikipedia.org/wiki/Four-in-a-row - -## How to get and run the code. -### 1st step -Get the code. -``` -go get -d github.com/y-hatano-github/4-in-a-row-go -``` -### 2nd step -Change directory to the source code directory. -``` -cd $GOPATH/src/github.com/y-hatano-github/4-in-a-row-go -``` -### 3rd step -Run the code. -``` -go run main.go -``` - -## Win/Mac/Linux binary -https://github.com/y-hatano-github/4-in-a-row-go/releases +# 4-in-a-row-go +CLI game '4-in-a-row' written in go. + +## What is 4-in-a-row? +https://en.wikipedia.org/wiki/Four-in-a-row + +## How to get and run the code. +### 1st step +Get the code. +``` +go get -d github.com/y-hatano-github/4-in-a-row-go +``` +### 2nd step +Change directory to the source code directory. +``` +cd $GOPATH/src/github.com/y-hatano-github/4-in-a-row-go +``` +### 3rd step +Run the code. +``` +go run main.go +``` + +## Win/Mac/Linux binary +https://github.com/y-hatano-github/4-in-a-row-go/releases diff --git a/cpu/cpu.go b/cpu/cpu.go index b2a9dfe..ed613ba 100644 --- a/cpu/cpu.go +++ b/cpu/cpu.go @@ -1,161 +1,160 @@ -package cpu - -import ( - "math/rand" - - "github.com/y-hatano-github/4inarow/game" -) - -// ExecCPUTurn CPUのターン実行 -func ExecCPUTurn(b *game.Board) { - x, y, sx := 0, 0, 0 - // 左右どちらから走査するか - if rand.Intn(2) == 1 { - sx = 6 - } - - // 勝てる場所を探す - for x = 0; x < 7; x++ { - if b.Height[x] > 9 { - continue - } - y = 9 - b.Height[x] - if checkCPUCell(x, y, 4, game.CPU, b) { - b.Put(x, game.CPU) - return - } - } - - // 負ける場所を探す - for x = 0; x < 7; x++ { - if b.Height[x] > 9 { - continue - } - y = 9 - b.Height[x] - if checkCPUCell(x, y, 4, game.Player, b) { - b.Put(x, game.CPU) - return - } - } - - // Playerが三つそろう箇所を抑える - for x = 0; x < 7; x++ { - x2 := Abs(sx - x) - if b.Height[x2] > 9 { - continue - } - y = 9 - b.Height[x2] - if checkCPUCell(x2, y, 3, game.Player, b) { - // 次の手で負ける場合は抑えない - if IsCPULostNextTurn(x2, y, b) { - continue - } - b.Put(x2, game.CPU) - return - } - } - - // CPUが三つそろう箇所を抑える - for x = 0; x < 7; x++ { - x2 := Abs(sx - x) - if b.Height[x2] > 9 { - continue - } - y = 9 - b.Height[x2] - if checkCPUCell(x2, y, 3, game.CPU, b) { - // 次の手で負ける場合は抑えない - if IsCPULostNextTurn(x2, y, b) { - continue - } - b.Put(x2, game.CPU) - return - } - } - - // Playerが二つそろう箇所を抑える - for x = 0; x < 7; x++ { - x2 := Abs(sx - x) - if b.Height[x2] > 9 { - continue - } - y = 9 - b.Height[x2] - if checkCPUCell(x2, y, 2, game.Player, b) { - // 次の手で負ける場合は抑えない - if IsCPULostNextTurn(x2, y, b) { - continue - } - b.Put(x2, game.CPU) - return - } - } - - // CPUが二つそろう箇所を抑える - /* - for x = 0; x < 7; x++ { - x2 := Abs(sx - x) - if b.Height[x2] > 9 { - continue - } - y = 9 - b.Height[x2] - if checkCPUCell(x2, y, 2, game.CPU, b) { - // 次の手で負ける場合は抑えない - if IsCPULostNextTurn(x2, y, b) { - continue - } - b.Put(x2, game.CPU) - return - } - }*/ - - // ランダムに手を置く - for x = 0; x < 7; x++ { - rx := rand.Intn(7) - if b.Height[rx] > 9 { - continue - } - y = 9 - b.Height[rx] - // 負ける場所にはおかない - if IsCPULostNextTurn(rx, y, b) { - continue - } - b.Put(rx, game.CPU) - return - } - - // 期待した場所がなければ空いている場所に置く - for x = 0; x < 7; x++ { - x2 := Abs(sx - x) - if b.Height[x2] > 9 { - continue - } - b.Put(x2, game.CPU) - break - } -} - -// checkCPUCell CPUの手(期待値)のチェック -func checkCPUCell(x, y, c int, z game.Char, b *game.Board) bool { - cbord := b.Board - cbord[y][x] = z - return b.CheckCellCount(x, y, c, z, cbord) -} - -// IsCPULostNextTurn 次の手でCPUが負けるか -func IsCPULostNextTurn(x, y int, b *game.Board) bool { - if b.Height[x] > 8 { - return false - } - cbord := b.Board - cbord[y][x] = game.CPU - cbord[y-1][x] = game.Player - - return b.CheckCellCount(x, y-1, 4, game.Player, cbord) -} - -// Abs 絶対値 mathだとfloatなので -func Abs(x int) int { - if x < 0 { - return -x - } - return x -} +package cpu + +import ( + "4-in-a-row-go/game" + "math/rand" +) + +// ExecCPUTurn CPUのターン実行 +func ExecCPUTurn(b *game.Board) { + x, y, sx := 0, 0, 0 + // 左右どちらから走査するか + if rand.Intn(2) == 1 { + sx = 6 + } + + // 勝てる場所を探す + for x = 0; x < 7; x++ { + if b.Height[x] > 9 { + continue + } + y = 9 - b.Height[x] + if checkCPUCell(x, y, 4, game.CPU, b) { + b.Put(x, game.CPU) + return + } + } + + // 負ける場所を探す + for x = 0; x < 7; x++ { + if b.Height[x] > 9 { + continue + } + y = 9 - b.Height[x] + if checkCPUCell(x, y, 4, game.Player, b) { + b.Put(x, game.CPU) + return + } + } + + // Playerが三つそろう箇所を抑える + for x = 0; x < 7; x++ { + x2 := Abs(sx - x) + if b.Height[x2] > 9 { + continue + } + y = 9 - b.Height[x2] + if checkCPUCell(x2, y, 3, game.Player, b) { + // 次の手で負ける場合は抑えない + if IsCPULostNextTurn(x2, y, b) { + continue + } + b.Put(x2, game.CPU) + return + } + } + + // CPUが三つそろう箇所を抑える + for x = 0; x < 7; x++ { + x2 := Abs(sx - x) + if b.Height[x2] > 9 { + continue + } + y = 9 - b.Height[x2] + if checkCPUCell(x2, y, 3, game.CPU, b) { + // 次の手で負ける場合は抑えない + if IsCPULostNextTurn(x2, y, b) { + continue + } + b.Put(x2, game.CPU) + return + } + } + + // Playerが二つそろう箇所を抑える + for x = 0; x < 7; x++ { + x2 := Abs(sx - x) + if b.Height[x2] > 9 { + continue + } + y = 9 - b.Height[x2] + if checkCPUCell(x2, y, 2, game.Player, b) { + // 次の手で負ける場合は抑えない + if IsCPULostNextTurn(x2, y, b) { + continue + } + b.Put(x2, game.CPU) + return + } + } + + // CPUが二つそろう箇所を抑える + /* + for x = 0; x < 7; x++ { + x2 := Abs(sx - x) + if b.Height[x2] > 9 { + continue + } + y = 9 - b.Height[x2] + if checkCPUCell(x2, y, 2, game.CPU, b) { + // 次の手で負ける場合は抑えない + if IsCPULostNextTurn(x2, y, b) { + continue + } + b.Put(x2, game.CPU) + return + } + }*/ + + // ランダムに手を置く + for x = 0; x < 7; x++ { + rx := rand.Intn(7) + if b.Height[rx] > 9 { + continue + } + y = 9 - b.Height[rx] + // 負ける場所にはおかない + if IsCPULostNextTurn(rx, y, b) { + continue + } + b.Put(rx, game.CPU) + return + } + + // 期待した場所がなければ空いている場所に置く + for x = 0; x < 7; x++ { + x2 := Abs(sx - x) + if b.Height[x2] > 9 { + continue + } + b.Put(x2, game.CPU) + break + } +} + +// checkCPUCell CPUの手(期待値)のチェック +func checkCPUCell(x, y, c int, z game.Char, b *game.Board) bool { + cbord := b.Board + cbord[y][x] = z + return b.CheckCellCount(x, y, c, z, cbord) +} + +// IsCPULostNextTurn 次の手でCPUが負けるか +func IsCPULostNextTurn(x, y int, b *game.Board) bool { + if b.Height[x] > 8 { + return false + } + cbord := b.Board + cbord[y][x] = game.CPU + cbord[y-1][x] = game.Player + + return b.CheckCellCount(x, y-1, 4, game.Player, cbord) +} + +// Abs 絶対値 mathだとfloatなので +func Abs(x int) int { + if x < 0 { + return -x + } + return x +} diff --git a/game/game.go b/game/game.go index 3bc5c00..21e2928 100644 --- a/game/game.go +++ b/game/game.go @@ -1,239 +1,239 @@ -package game - -import ( - "bufio" - "fmt" - "os" - "strings" - - "github.com/shiena/ansicolor" -) - -// Char 表示キャラクタ制御 -type Char int - -// 表示キャラクタ -const ( - Brank Char = iota - Player - CPU -) - -// Status 状態制御 -type Status int - -// 状態 -const ( - Playing Status = iota - PlayerWin - CPUWin - Draw -) - -// Board ゲーム盤 -type Board struct { - // 盤(縦×横 : 10 × 7) - Board [10][7]Char - // 盤の埋まっている高さ - Height [7]int - // ゲーム状態 - GameStatus Status -} - -// Init 初期化 -func (b *Board) Init() { - for i, rows := range b.Board { - for j := range rows { - b.Board[i][j] = 0 - b.Height[j] = 0 - } - } - b.GameStatus = Playing -} - -// DrawTitle タイトル描画 -func (b *Board) DrawTitle() { - w := ansicolor.NewAnsiColorWriter(os.Stdout) - fmt.Println("4 in a row.") - fmt.Fprint(w, fmt.Sprintf("\x1b[32m%s\x1b[0m", "〇")) - fmt.Println(" is your cell.") - fmt.Fprint(w, fmt.Sprintf("\x1b[31m%s\x1b[0m", "〇")) - fmt.Println(" is cpu's cell.") - for { - fmt.Print("type 's' to start(type 'q' to quit):") - stdin := bufio.NewScanner(os.Stdin) - stdin.Scan() - t := stdin.Text() - - if t == "q" { - fmt.Println("bye..") - os.Exit(0) - } - if t == "s" { - break - } - } - fmt.Println("") - fmt.Println("") - fmt.Println("Game start!!") - fmt.Println("") -} - -// EndGame ゲーム終了結果出力 -func (b *Board) EndGame() { - switch b.GameStatus { - case PlayerWin: - fmt.Println("Player won!!") - case CPUWin: - fmt.Println("Player lost..") - case Draw: - fmt.Println("Draw game.") - } - - for { - fmt.Print("type 'r' to restart(type 'q' to quit):") - stdin := bufio.NewScanner(os.Stdin) - stdin.Scan() - t := stdin.Text() - - if t == "q" { - fmt.Println("bye..") - os.Exit(0) - } - if t == "r" { - fmt.Println() - fmt.Println() - fmt.Println() - break - } - } -} - -// DrawBoard 盤描画 -func (b *Board) DrawBoard() { - for _, rows := range b.Board { - var a string - for _, value := range rows { - switch value { - case Brank: - a += "・" - case Player: - a += fmt.Sprintf("\x1b[32m%s\x1b[0m", "〇") - case CPU: - a += fmt.Sprintf("\x1b[31m%s\x1b[0m", "〇") - } - } - w := ansicolor.NewAnsiColorWriter(os.Stdout) - fmt.Fprintln(w, a) - } - fmt.Println("1234567") - fmt.Println() -} - -// Put コマを置く -func (b *Board) Put(x int, z Char) bool { - if b.Height[x] == 10 { - fmt.Printf("[%v] not vacant.", x+1) - fmt.Println() - return false - } - b.Board[9-b.Height[x]][x] = z - b.Height[x]++ - return true -} - -//Judge 判定 -func (b *Board) Judge() { - for y, rows := range b.Board { - for x, value := range rows { - if value == 0 { - continue - } - if b.CheckCellCount(x, y, 4, value, b.Board) { - switch value { - case Player: - b.GameStatus = PlayerWin - return - case CPU: - b.GameStatus = CPUWin - return - } - } - } - } - - if b.IsDraw() { - b.GameStatus = Draw - return - } - b.GameStatus = Playing -} - -// IsDraw 引き分けチェック -func (b *Board) IsDraw() bool { - for _, value := range b.Height { - if value < 10 { - return false - } - } - - return true -} - -// CheckCellCount 指定されたキャラのカウントと同数か -func (b *Board) CheckCellCount(x, y, c int, z Char, board [10][7]Char) bool { - cs := "" - for i := 0; i < c; i++ { - cs += [...]string{"0", "1", "2"}[z] - } - - // 縦の判定 - cells := "" - for yy := y - (c - 1); yy < y+c; yy++ { - if yy > -1 && yy < 10 { - cells += [...]string{"0", "1", "2"}[board[yy][x]] - } - } - if strings.Index(cells, cs) != -1 { - return true - } - - // 横の判定 - cells = "" - for xx := x - (c - 1); xx < x+c; xx++ { - if xx > -1 && xx < 7 { - cells += [...]string{"0", "1", "2"}[board[y][xx]] - } - } - if strings.Index(cells, cs) != -1 { - return true - } - - // 右肩下がり斜め - cells = "" - xx := x - (c - 1) - for yy := y - (c - 1); yy < y+c; yy++ { - if (yy > -1 && yy < 10) && (xx > -1 && xx < 7) { - cells += [...]string{"0", "1", "2"}[board[yy][xx]] - } - xx++ - } - if strings.Index(cells, cs) != -1 { - return true - } - - // 右肩上がり斜め - cells = "" - xx = x + (c - 1) - for yy := y - (c - 1); yy < y+c; yy++ { - if (yy > -1 && yy < 10) && (xx > -1 && xx < 7) { - cells += [...]string{"0", "1", "2"}[board[yy][xx]] - } - xx-- - } - if strings.Index(cells, cs) != -1 { - return true - } - - return false -} +package game + +import ( + "bufio" + "fmt" + "os" + "strings" + + "github.com/shiena/ansicolor" +) + +// Char 表示キャラクタ制御 +type Char int + +// 表示キャラクタ +const ( + Brank Char = iota + Player + CPU +) + +// Status 状態制御 +type Status int + +// 状態 +const ( + Playing Status = iota + PlayerWin + CPUWin + Draw +) + +// Board ゲーム盤 +type Board struct { + // 盤(縦×横 : 10 × 7) + Board [10][7]Char + // 盤の埋まっている高さ + Height [7]int + // ゲーム状態 + GameStatus Status +} + +// Init 初期化 +func (b *Board) Init() { + for i, rows := range b.Board { + for j := range rows { + b.Board[i][j] = 0 + b.Height[j] = 0 + } + } + b.GameStatus = Playing +} + +// DrawTitle タイトル描画 +func (b *Board) DrawTitle() { + w := ansicolor.NewAnsiColorWriter(os.Stdout) + fmt.Println("4 in a row.") + fmt.Fprint(w, fmt.Sprintf("\x1b[32m%s\x1b[0m", "〇")) + fmt.Println(" is your cell.") + fmt.Fprint(w, fmt.Sprintf("\x1b[31m%s\x1b[0m", "〇")) + fmt.Println(" is cpu's cell.") + for { + fmt.Print("type 's' to start(type 'q' to quit):") + stdin := bufio.NewScanner(os.Stdin) + stdin.Scan() + t := stdin.Text() + + if t == "q" { + fmt.Println("bye..") + os.Exit(0) + } + if t == "s" { + break + } + } + fmt.Println("") + fmt.Println("") + fmt.Println("Game start!!") + fmt.Println("") +} + +// EndGame ゲーム終了結果出力 +func (b *Board) EndGame() { + switch b.GameStatus { + case PlayerWin: + fmt.Println("Player won!!") + case CPUWin: + fmt.Println("Player lost..") + case Draw: + fmt.Println("Draw game.") + } + + for { + fmt.Print("type 'r' to restart(type 'q' to quit):") + stdin := bufio.NewScanner(os.Stdin) + stdin.Scan() + t := stdin.Text() + + if t == "q" { + fmt.Println("bye..") + os.Exit(0) + } + if t == "r" { + fmt.Println() + fmt.Println() + fmt.Println() + break + } + } +} + +// DrawBoard 盤描画 +func (b *Board) DrawBoard() { + for _, rows := range b.Board { + var a string + for _, value := range rows { + switch value { + case Brank: + a += "・" + case Player: + a += fmt.Sprintf("\x1b[32m%s\x1b[0m", "〇") + case CPU: + a += fmt.Sprintf("\x1b[31m%s\x1b[0m", "〇") + } + } + w := ansicolor.NewAnsiColorWriter(os.Stdout) + fmt.Fprintln(w, a) + } + fmt.Println("1234567") + fmt.Println() +} + +// Put コマを置く +func (b *Board) Put(x int, z Char) bool { + if b.Height[x] == 10 { + fmt.Printf("[%v] not vacant.", x+1) + fmt.Println() + return false + } + b.Board[9-b.Height[x]][x] = z + b.Height[x]++ + return true +} + +//Judge 判定 +func (b *Board) Judge() { + for y, rows := range b.Board { + for x, value := range rows { + if value == 0 { + continue + } + if b.CheckCellCount(x, y, 4, value, b.Board) { + switch value { + case Player: + b.GameStatus = PlayerWin + return + case CPU: + b.GameStatus = CPUWin + return + } + } + } + } + + if b.IsDraw() { + b.GameStatus = Draw + return + } + b.GameStatus = Playing +} + +// IsDraw 引き分けチェック +func (b *Board) IsDraw() bool { + for _, value := range b.Height { + if value < 10 { + return false + } + } + + return true +} + +// CheckCellCount 指定されたキャラのカウントと同数か +func (b *Board) CheckCellCount(x, y, c int, z Char, board [10][7]Char) bool { + cs := "" + for i := 0; i < c; i++ { + cs += [...]string{"0", "1", "2"}[z] + } + + // 縦の判定 + cells := "" + for yy := y - (c - 1); yy < y+c; yy++ { + if yy > -1 && yy < 10 { + cells += [...]string{"0", "1", "2"}[board[yy][x]] + } + } + if strings.Index(cells, cs) != -1 { + return true + } + + // 横の判定 + cells = "" + for xx := x - (c - 1); xx < x+c; xx++ { + if xx > -1 && xx < 7 { + cells += [...]string{"0", "1", "2"}[board[y][xx]] + } + } + if strings.Index(cells, cs) != -1 { + return true + } + + // 右肩下がり斜め + cells = "" + xx := x - (c - 1) + for yy := y - (c - 1); yy < y+c; yy++ { + if (yy > -1 && yy < 10) && (xx > -1 && xx < 7) { + cells += [...]string{"0", "1", "2"}[board[yy][xx]] + } + xx++ + } + if strings.Index(cells, cs) != -1 { + return true + } + + // 右肩上がり斜め + cells = "" + xx = x + (c - 1) + for yy := y - (c - 1); yy < y+c; yy++ { + if (yy > -1 && yy < 10) && (xx > -1 && xx < 7) { + cells += [...]string{"0", "1", "2"}[board[yy][xx]] + } + xx-- + } + if strings.Index(cells, cs) != -1 { + return true + } + + return false +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c897a3f --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module 4-in-a-row-go + +go 1.12 + +require github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bfeda82 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo= +github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= diff --git a/main.go b/main.go index 3dd9165..5e9de5c 100644 --- a/main.go +++ b/main.go @@ -1,46 +1,46 @@ -package main - -import ( - "math/rand" - "time" - - "github.com/y-hatano-github/4inarow/cpu" - "github.com/y-hatano-github/4inarow/game" - "github.com/y-hatano-github/4inarow/player" -) - -func main() { - // 乱数 - rand.Seed(time.Now().UnixNano()) - - b := &game.Board{} - b.DrawTitle() - for { - // 初期化 - b.Init() - b.DrawBoard() - for { - - // プレイヤーのターン - player.ExecPlayerTunr(b) - // 盤描画 - b.DrawBoard() - // チェック - b.Judge() - if b.GameStatus != game.Playing { - break - } - // COMのターン - cpu.ExecCPUTurn(b) - // 盤描画 - b.DrawBoard() - // チェック - b.Judge() - if b.GameStatus != game.Playing { - break - } - } - // 終了処理 - b.EndGame() - } -} +package main + +import ( + "math/rand" + "time" + + "4-in-a-row-go/cpu" + "4-in-a-row-go/game" + "4-in-a-row-go/player" +) + +func main() { + // 乱数 + rand.Seed(time.Now().UnixNano()) + + b := &game.Board{} + b.DrawTitle() + for { + // 初期化 + b.Init() + b.DrawBoard() + for { + + // プレイヤーのターン + player.ExecPlayerTurn(b) + // 盤描画 + b.DrawBoard() + // チェック + b.Judge() + if b.GameStatus != game.Playing { + break + } + // COMのターン + cpu.ExecCPUTurn(b) + // 盤描画 + b.DrawBoard() + // チェック + b.Judge() + if b.GameStatus != game.Playing { + break + } + } + // 終了処理 + b.EndGame() + } +} diff --git a/player/player.go b/player/player.go index 551bb1f..2cd1539 100644 --- a/player/player.go +++ b/player/player.go @@ -1,31 +1,31 @@ -package player - -import ( - "bufio" - "fmt" - "os" - "strconv" - - "github.com/y-hatano-github/4inarow/game" -) - -// ExecPlayerTunr プレイヤーの手の入力 -func ExecPlayerTunr(b *game.Board) { - for { - fmt.Print("type number 1-9. (type 'q' to quit):") - stdin := bufio.NewScanner(os.Stdin) - stdin.Scan() - t := stdin.Text() - if t == "q" { - fmt.Println("bye..") - os.Exit(0) - } - if i, err := strconv.Atoi(t); err == nil { - if i > 0 && i < 8 { - if b.Put(i-1, 1) { - break - } - } - } - } -} +package player + +import ( + "bufio" + "fmt" + "os" + "strconv" + + "4-in-a-row-go/game" +) + +// ExecPlayerTurn プレイヤーの手の入力 +func ExecPlayerTurn(b *game.Board) { + for { + fmt.Print("type number 1-9. (type 'q' to quit):") + stdin := bufio.NewScanner(os.Stdin) + stdin.Scan() + t := stdin.Text() + if t == "q" { + fmt.Println("bye..") + os.Exit(0) + } + if i, err := strconv.Atoi(t); err == nil { + if i > 0 && i < 8 { + if b.Put(i-1, 1) { + break + } + } + } + } +}