Треки
/
Go
Go
/
Вправи
/
Шахівниця
Шахівниця

Шахівниця

Навчальна вправа

Вступ

У Go ми можемо перебирати slice за допомогою for та індексу, або ж скористатися range. range також дає змогу перебирати map.

Кожна ітерація повертає два значення: індекс/ключ і копію елемента за цим індексом/ключем.

Перебирання слайса

Простіше простого: цикл по слайсу перебирає елементи в очікуваному порядку.

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

Перебирання мапи

Перебирання мапи ставить нову проблему. Порядок тепер випадковий.

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

Може здатися, що наведений вище вивід неправильний, адже можна було б очікувати, що перша пара ключ-значення з оголошення мапи, 9 10, буде надрукована першою, а не останньою. Однак мапи за своєю природою невпорядковані: у них немає першої чи останньої пари ключ-значення. Через це, коли ми перебираємо елементи мапи, порядок, у якому їх буде відвідано, буде випадковим і не підпорядковується жодній закономірності. Це означає, що наведений вивід можливий, але може відрізнятися від того, що ми побачимо, якщо спробуємо запустити це самостійно. Щоб дізнатися більше, дивіться Специфікація мови 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. Кожну клітинку в цій вертикалі представлено булевим значенням (англ. Boolean), яке вказує, зайнята вона чи ні. Тепер, коли 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. Вона має порахувати загальну кількість зайнятих клітинок, перебираючи елементи заданої горизонталі. Поверніть ціле число. Поверніть нуль (0), якщо задана горизонталь недійсна (не в межах від 1 до 8 включно).

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, щоб вивчати й опановувати Go, а також 34 концепції166 вправ та справжнє наставництво від людей, і все це безкоштовно.