轨道
/
Go
Go
/
练习
/
棋盘
棋盘

棋盘

学习练习

简介

在 Go 中,你可以用for和下标来遍历slice,也可以使用range。range还允许你遍历map。

每次迭代都会返回两个值:下标/键,以及该下标/键对应元素的副本。

遍历 slice

小菜一碟,遍历slice时,顺序和预期一致。

xi := []int{10, 20, 30}
for i, x := range xi {
  fmt.Println(i, x)
}
// outputs:
// 0, 10
// 1, 20
// 2, 30

遍历 map

遍历map会带来一个新问题。 现在的顺序是随机的。

hash := map[int]int{9: 10, 99: 20, 999: 30}
for k, v := range hash {
  fmt.Println(k, v)
}
// outputs, for example:
// 99 20
// 999 30
// 9 10
Note

上面的输出看起来可能不对,因为人们会以为在声明 map 时最先出现的键值对9 10应该最先打印,而不是最后一个。 然而,map 天生就是无序的,并不存在第一个或最后一个键值对。 因此,在遍历 map 的条目时,访问条目的顺序是随机的,不会遵循任何特定规律。 这意味着上面的输出是有可能的,但你自己运行这段代码时得到的结果可能不一样。 想了解更多,请参阅 Go 语言规范:range 子句。

省略键或值的迭代

在 Go 中,未使用的变量会在构建时引发错误。 有时你只需要值,就像第一个例子那样:

xi := []int{10, 20, 30}
for i, x := range xi {
  fmt.Println(x)
}
// Go build failed: i declared but not used

你可以用_替换i,这告诉编译器我们不使用那个值:

xi := []int{10, 20, 30}
for _, x := range xi {
  fmt.Println(x)
}
// outputs:
// 10
// 20
// 30

如果你只想打印下标,可以用_替换x,或者干脆省略声明:

xi := []int{10, 20, 30}
// for i, _ := range xi {
for i := range xi {
  fmt.Println(i)
}
// outputs:
// 0
// 1
// 2

定义类型

类型定义会创建一个新的具名类型,它与其他任何类型都不相同,哪怕另一个类型的底层类型和它一样。

type File []bool

这里的File指的是棋盘上的一条竖列,通常用 A 到 H 标注。 这一列中的每个格子都用一个布尔值表示,标记它是否被占据。 既然File已经定义好了,我们就可以在其他定义里使用它:

type Chessboard map[string]File

board := Chessboard{
    "A": File{true, false, true},
    "B": File{false, true, false},
}

Chessboard把列的标识符映射到File值。 每个File都是一个布尔值切片,表示一条竖列中的各个格子。 没有这些类型定义,board就会是map[string][]bool,这会让人更难理解我们到底在表示什么。

说明

作为一名国际象棋爱好者,你想写出自己的版本。 没错,网上可能已经有很多国际象棋的实现,但你的将是独一无二的!

棋盘上的每个方格都由字母和数字的组合来标识:

  • 水平方向的一排方格称为行,编号从 1 到 8。
  • 垂直方向的一列方格称为列,标记为 A 到 H。
   A B C D E F G H
 8 # _ _ _ # _ _ # 8
 7 _ _ _ _ _ _ _ _ 7
 6 _ _ _ _ # _ _ # 6
 5 _ # _ _ _ _ _ # 5
 4 _ _ _ _ _ _ # # 4
 3 # _ # _ _ _ _ # 3
 2 _ _ _ _ _ _ _ # 2
 1 # _ _ _ _ _ _ # 1
   A B C D E F G H

1. 给定一个棋盘和一个列,数一数有多少个方格被占据

实现 CountInFile(board Chessboard, file string) int 函数。 它应该通过遍历一个映射来统计被占据的方格总数。 返回一个整数。 如果给定的列在映射中找不到,则返回计数零(0)。

CountInFile(board, "A")
// => 3

2. 给定一个棋盘和一个行,数一数有多少个方格被占据

实现 CountInRank(board Chessboard, rank int) int 函数。 它应该通过遍历给定的行来统计被占据的方格总数。 返回一个整数。 如果给定的行不是有效的(不在 1 到 8 之间,包含两端),则返回计数零(0)。

CountInRank(board, 2)
// => 1

3. 数一数给定的棋盘中有多少个存在的方格

实现 CountAll(board Chessboard) int 函数。 它应该统计棋盘中有多少个存在的方格,并返回一个整数。 由于你不需要检查方格的内容,可以考虑使用 range,同时省略 index 和 value。

CountAll(board)
// => 64

4. 数一数给定的棋盘中有多少个方格被占据

实现 CountOccupied(board Chessboard) int 函数。 它应该统计棋盘中有多少个方格被占据。 返回一个整数。

CountOccupied(board)
// => 15
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Go Exercism

准备好开始 棋盘 了吗?

注册 Exercism,借助 34 个概念166 个练习 和真人导师指导,学习并掌握 Go,全部免费。