Skip to content

Instantly share code, notes, and snippets.

@tyamagu2
Created February 24, 2016 10:04
Show Gist options
  • Save tyamagu2/b7cf24e37edd22cc9522 to your computer and use it in GitHub Desktop.
Save tyamagu2/b7cf24e37edd22cc9522 to your computer and use it in GitHub Desktop.
Go Moku Narabe
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
var N, M = 19, 5
var BLACK, WHITE, NONE = "x", "o", " "
var sc = bufio.NewScanner(os.Stdin)
var directions = [][]int {
[]int{ 1, 0 },
[]int{ 0, 1 },
[]int{ 1, 1 },
[]int{ 1, -1 },
}
func show_board(board [][]string) {
for i:= range board {
fmt.Print("|")
for j := range board[i] {
fmt.Print(board[i][j], "|")
}
fmt.Println("")
}
}
func main() {
sc.Split(bufio.ScanWords)
board := make([][]string, N)
for i:= range board {
board[i] = make([]string, N)
for j := range board[i] {
board[i][j] = NONE
}
}
total := 0
turn := BLACK
show_board(board)
for {
if turn == BLACK {
fmt.Println("BLACK")
} else {
fmt.Println("WHITE")
}
sc.Scan()
row, e := strconv.Atoi(sc.Text())
if e != nil { panic(e) }
sc.Scan()
col, e := strconv.Atoi(sc.Text())
if e != nil { panic(e) }
if row < 0 || row >= N || col < 0 || col >= N {
fmt.Println("OUT OF BOUNDS")
continue
} else if board[row][col] != NONE {
fmt.Println("OCCUPIED")
continue
}
board[row][col] = turn
total += 1
count := 0
for di := range directions {
count = 1
dr, dc := directions[di][0], directions[di][1]
nr, nc := row, col
for {
nr += dr
nc += dc
if nr < 0 || nr >= N || nc < 0 || nc >= N { break }
if board[nr][nc] != turn { break }
count += 1
}
nr, nc = row, col
for {
nr -= dr
nc -= dc
if nr < 0 || nr >= N || nc < 0 || nc >= N { break }
if board[nr][nc] != turn { break }
count += 1
}
if count == M { break }
}
show_board(board)
if count == M {
winner := "BLACK"
if turn == WHITE {
winner = "WHITE"
}
fmt.Println(winner, " WIN!")
break
}
if total == N * N {
fmt.Println("DRAW!")
break
}
if turn == BLACK {
turn = WHITE
} else {
turn = BLACK
}
}
}
class Board
def initialize(size = 8, required = 5)
@size = size
@required = required
@placed = 0
@board = size.times.map { size.times.map { :none } }
end
def place(color, row, col)
return :out_of_bounds if outside?(row, col)
return :occupied if @board[row][col] != :none
return :invalid_color unless [:black, :white].include?(color)
@board[row][col] = color
@placed += 1
if win?(color, row, col)
:win
elsif draw?
:draw
else
:continue
end
end
def show
puts " |#{@size.times.map(&:to_s).join('|')}|"
@board.each_with_index do |row, i|
str = row.map { |column|
case column
when :black then 'x'
when :white then 'o'
else
' '
end
}.join('|')
puts "#{i}|#{str}|"
end
end
private
def draw?
@placed == @size * @size
end
def outside?(row, col)
row < 0 || row >= @size || col < 0 || col >= @size
end
def win?(color, row, col)
[[1, 0], [1, 1], [0, 1], [1, -1]].any? do |dx, dy|
count = 1
rr = row + dx
cc = col + dy
while !outside?(rr, cc) && @board[rr][cc] == color
count += 1
rr += dx
cc += dy
end
rr = row - dx
cc = col - dy
while !outside?(rr, cc) && @board[rr][cc] == color
count += 1
rr -= dx
cc -= dy
end
count >= @required
end
end
end
class Game
attr_reader :turn
def initialize(size = 8, required = 5)
@board = Board.new(size, required)
@turn = :white
end
def change_turn
@turn = @turn == :white ? :black : :white
end
def run
loop do
@board.show
puts "#{@turn}'s turn"
row, col = gets.split.map(&:to_i)
case (result = @board.place(@turn, row, col))
when :win
puts "#{@turn} won!"
break
when :draw
puts 'draw!'
break
when :continue
change_turn
else
puts result
end
end
end
end
Game.new.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment