分弦是国际象棋棋盘位置的紧凑表示,它允许你从棋盘位置获得必要的信息来开始下棋。这包括像棋盘上的碎片,城堡的状态等。更多信息在这里:https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_符号表示法。
我已经用go编写了一个简单的函数,将一个FEN字符串解码为单独的变量,并为FEN字符串所代表的每一个信息片段提供合适的类型,我想看看是否以一种合理的方式解析FEN字符串。
import (
"strings"
)
type pair struct {
x, y int8
}
func decodeFen(fen string) ([8][8]int8, int8, [4]bool, pair, int8, int) {
split := strings.Split(fen, " ")
var board [8][8]int8
board_split := strings.Split(split[0], "/")
for r, row := range board_split {
var col_ind int8
for _, char := range row {
if char >= 49 && char <= 57 {
for i := int8(0); i < int8(char) - 48; i++ {
board[r][col_ind] = '-'
col_ind++
}
} else {
board[r][col_ind] = int8(char)
col_ind++
}
}
}
var color int8
if split[1] == "w" {
color = 1
} else {color = 2}
var castle_status [4]bool
var status_map = map[rune]int8 {
'K' : 0, 'Q' : 1, 'k' : 2, 'q' : 3}
if split[2] != "-" {
for _, char := range split[2] {
castle_status[status_map[char]] = true
}
}
var ep_pos pair = pair{-1, -1}
if split[3] != "-" {
x_label := split[3][0]
y_label := split[3][1]
y_label -= 48
ep_pos = pair{int8(x_label - 97), int8(y_label - ((y_label - 1) - (8 - y_label)) - 1)}
}
var halfmove_clock int8 = int8(split[4][0]) - 48
var fullmove_number int = int(split[5][0]) - 48
return board, color, castle_status, ep_pos, halfmove_clock, fullmove_number
}这实际上只是一个解析问题,为了拆分字符串,我决定使用strings go库中的拆分()函数,而不是编写自己的函数。对这段代码的任何改进和反馈都将是很棒的,如果我没有正确地问这个问题,我很抱歉,因为这是我在这个社区中的第一篇文章。
发布于 2020-08-03 21:55:23
代码应该是正确的、可维护的、健壮的、合理有效的,而且最重要的是是可读的。
要确保代码是正确的,请仔细阅读规范和相关文档。
对于代码评审,请比较规范和并行实现它的代码.
在国际象棋中,棋子被放置在正方形上,这些棋子被组织成不同的排列和文件,形成一个棋盘。在decodeFen中,除了板外,似乎没有任何对这些基本概念的引用。因此,将代码与规范进行比较是很困难的。
PGN是“便携游戏表示法”,这是为使用ASCII文本文件表示国际象棋游戏数据而设计的标准。PGN数据使用8位ISO 8859/1 (拉丁文1)字符集的子集表示。因此,
var board [8][8]int8是不正确的。字符不是int8类型(8位有符号整数).字符类型为byte (8位)。
var board [8][8]byte密码
for _, char := range row { ... }期望一个UTF-8编码字符串。UTF-8编码与ISO 8859/1编码不同。
Go是一种安全的静态类型化语言。密码
board[r][col_ind] = int8(char)当ISO 8859/1编码被解码为UTF-8编码时,纠正错误的尝试失败。
decodeFen代码是一种“意识流”代码,很难阅读并证明是正确的。代码缺少基本概念,比如封装复杂性和实现细节的函数。例如,将decodeFen组织成一系列调用来解析每个FEN字段的函数。
作为一个例子,考虑分件放置字段。以下是初稿:
pieces.go:
package main
import (
"errors"
"fmt"
"strings"
)
type Board [8][8]byte
const (
whitePieceLetters = "PNBRQK"
blackPieceLetters = "pnbrqk"
pieceLetters = whitePieceLetters + blackPieceLetters
)
func isPiece(p byte) bool {
for i := 0; i < len(pieceLetters); i++ {
if p == pieceLetters[i] {
return true
}
}
return false
}
var (
ErrRankOutOfRange = errors.New("rank out of range")
ErrFileOutOfRange = errors.New("file out of range")
ErrPieceInvalid = errors.New("piece invalid")
)
func parseFENPieces(board *Board, pieces string) error {
ranks := strings.Split(pieces, "/")
if len(ranks) != len(board) {
return ErrRankOutOfRange
}
for r, rank := range ranks {
f := 0
for i := 0; i < len(rank); i++ {
piece := rank[i]
if piece >= '0' && piece <= '9' {
for j := byte(0); j < piece-'0'; j++ {
if f >= len(board[0]) {
return ErrFileOutOfRange
}
board[r][f] = '-'
f++
}
} else {
if f >= len(board[0]) {
return ErrFileOutOfRange
}
if !isPiece(piece) {
return ErrPieceInvalid
}
board[r][f] = piece
f++
}
}
if f != len(board[0]) {
return ErrFileOutOfRange
}
}
return nil
}
func main() {
fens := []string{
// https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
"rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2",
"rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2",
}
var board Board
for _, fen := range fens {
fields := strings.Split(fen, " ")
if len(fields) > 0 {
pieces := strings.Split(fen, " ")[0]
fmt.Println(pieces)
err := parseFENPieces(&board, pieces)
fmt.Println(err)
for i := range board {
fmt.Printf("%c\n", board[i])
}
}
}
}操场:https://play.golang.org/p/-pPnCs2GMao
输出:
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
<nil>
[r n b q k b n r]
[p p p p p p p p]
[- - - - - - - -]
[- - - - - - - -]
[- - - - - - - -]
[- - - - - - - -]
[P P P P P P P P]
[R N B Q K B N R]使用国际象棋术语,以符合规格。
棋盘数据结构无处不在。给它一种类型:
type Board [8][8]byte在Go中,参数通过值传递。对于数组,值是整个数组。因此,为了提高效率,我们使用指针(8字节或4字节)而不是数组(64字节)。
输入必须有效。不要对外部输入做出任何假设。报告错误。
不要使用魔法值: 49是'0',57是'9‘。
以此类推。
https://codereview.stackexchange.com/questions/247415
复制相似问题