Tracks
/
Go
Go
/
Übungen
/
Schachbrett
Schachbrett

Schachbrett

Lernübung

Einführung

In Go kannst du mit for und einem Index über einen slice iterieren, oder du verwendest range. Mit range kannst du auch über eine map iterieren.

Jede Iteration gibt zwei Werte zurück: den Index/Schlüssel und eine Kopie des Elements an diesem Index bzw. Schlüssel.

Über einen Slice iterieren

Ein Kinderspiel: Schleifen über einen Slice, in der erwarteten Reihenfolge.

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

Über eine Map iterieren

Beim Iterieren über eine Map taucht ein neues Problem auf. Die Reihenfolge ist jetzt zufällig.

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

Es mag so aussehen, als wäre die obige Ausgabe falsch, denn man würde erwarten, dass das erste Schlüssel/Wert-Paar bei der Deklaration der Map 9 10 als erstes ausgegeben wird und nicht als letztes. Allerdings sind Maps von Natur aus ungeordnet, es gibt kein erstes oder letztes Schlüssel/Wert-Paar. Deshalb ist die Reihenfolge beim Iterieren über die Einträge einer Map zufällig und folgt keinem bestimmten Muster. Das bedeutet, dass die obige Ausgabe möglich ist, aber von dem abweichen kann, was du bekommst, wenn du das selbst ausprobierst. Mehr dazu erfährst du unter Go Language Spec: range clause.

Iteration ohne Schlüssel oder Wert

In Go führt eine unbenutzte Variable zur Build-Zeit zu einem Fehler. Manchmal brauchst du nur den Wert, wie im ersten Beispiel:

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

Du kannst das i durch _ ersetzen, was dem Compiler mitteilt, dass wir diesen Wert nicht verwenden:

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

Wenn du nur den Index ausgeben möchtest, kannst du das x durch _ ersetzen oder die Deklaration einfach weglassen:

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

Typen definieren

Eine Typdefinition erzeugt einen neuen benannten Typ, der sich von jedem anderen Typ unterscheidet, selbst von einem mit demselben zugrunde liegenden Typ.

type File []bool

File bezeichnet hier eine einzelne vertikale Spalte auf einem Schachbrett, die üblicherweise mit A bis H beschriftet ist. Jedes Feld in dieser Spalte wird durch einen booleschen Wert dargestellt, der angibt, ob es besetzt ist oder nicht. Nachdem File nun definiert ist, können wir es in anderen Definitionen verwenden:

type Chessboard map[string]File

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

Chessboard ordnet Spaltenbezeichner den File-Werten zu. Ein File ist jeweils ein Slice von booleschen Werten, das die Felder einer Schachspalte repräsentiert. Ohne diese Typdefinitionen wäre board ein map[string][]bool, was es schwerer verständlich machen würde, was wir darstellen.

Anleitung

Als Schachfan möchtest du deine eigene Version des Spiels schreiben. Klar, es gibt online schon reichlich Schach-Implementierungen, aber deine wird einzigartig!

Jedes Feld des Schachbretts wird durch ein Paar aus Buchstabe und Zahl angegeben:

  • Die horizontalen Felderreihen heißen Reihen und sind von 1 bis 8 nummeriert.
  • Die vertikalen Felderreihen heißen Linien und sind mit A bis H beschriftet.
   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. Zähle bei gegebenem Schachbrett und gegebener Linie, wie viele Felder besetzt sind

Implementiere die Funktion CountInFile(board Chessboard, file string) int. Sie soll die Gesamtzahl der besetzten Felder zählen, indem sie über eine Map iteriert. Gib eine Ganzzahl zurück. Gib eine Anzahl von null (0) zurück, wenn die angegebene Linie nicht in der Map gefunden werden kann.

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

2. Zähle bei gegebenem Schachbrett und gegebener Reihe, wie viele Felder besetzt sind

Implementiere die Funktion CountInRank(board Chessboard, rank int) int. Sie soll die Gesamtzahl der besetzten Felder zählen, indem sie über die angegebene Reihe iteriert. Gib eine Ganzzahl zurück. Gib eine Anzahl von null (0) zurück, wenn die angegebene Reihe ungültig ist (nicht zwischen 1 und 8, einschließlich).

CountInRank(board, 2)
// => 1

3. Zähle, wie viele Felder auf dem gegebenen Schachbrett vorhanden sind

Implementiere die Funktion CountAll(board Chessboard) int. Sie soll zählen, wie viele Felder auf dem Schachbrett vorhanden sind, und gibt eine Ganzzahl zurück. Da du den Inhalt der Felder nicht überprüfen musst, kannst du range verwenden und dabei sowohl index als auch value weglassen.

CountAll(board)
// => 64

4. Zähle, wie viele Felder auf dem gegebenen Schachbrett besetzt sind

Implementiere die Funktion CountOccupied(board Chessboard) int. Sie soll zählen, wie viele Felder auf dem Schachbrett besetzt sind. Gib eine Ganzzahl zurück.

CountOccupied(board)
// => 15
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Go Exercism

Bereit, mit Schachbrett zu starten?

Melde dich bei Exercism an, um Go mit 34 Konzepte166 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.