Tablice dwuwymiarowe – wiersze i kolumny
Poznasz tablice 2D – struktury do przechowywania danych w formie tabeli. Nauczysz się je tworzyć, wypełniać, przeszukiwać i sortować!
Po co tablice 2D?
Zwykła tablica to jedna linia danych. Ale co jeśli dane mają strukturę tabeli – wiersze i kolumny?
- Arkusz kalkulacyjny – wiersze i kolumny z danymi
- Szachownica – 8 wierszy × 8 kolumn
- Miejsca w kinie – rzędy i fotele
- Piksele obrazu – szerokość × wysokość
- Plan lekcji – dni tygodnia × godziny
- Tabela ocen – uczniowie × przedmioty
// 😰 Bez tablicy 2D – trudne do ogarnięcia! int[] wiersz1 = { 1, 2, 3 }; int[] wiersz2 = { 4, 5, 6 }; int[] wiersz3 = { 7, 8, 9 }; // Jak teraz przejść przez wszystkie? Jak dodać wiersz 4? // ✅ Z tablicą 2D – elegancko! int[,] tablica = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
Czym jest tablica 2D?
Tablica dwuwymiarowa to struktura danych w formie prostokątnej siatki. Każdy element ma dwa indeksy: wiersz i kolumnę.
Tablica 2D działa jak Excel:
- Wiersze = numery 0, 1, 2… (jak w Excelu: 1, 2, 3…)
- Kolumny = numery 0, 1, 2… (jak w Excelu: A, B, C…)
- Komórka = przecięcie wiersza i kolumny
KOLUMNY
0 1 2
┌─────┬─────┬─────┐
0 │ 1 │ 2 │ 3 │ ← wiersz 0
├─────┼─────┼─────┤
W 1 │ 4 │ 5 │ 6 │ ← wiersz 1
I ├─────┼─────┼─────┤
E 2 │ 7 │ 8 │ 9 │ ← wiersz 2
R └─────┴─────┴─────┘
S
Z tablica[1, 2] = 6
E (wiersz 1, kolumna 2)
tablica[wiersz, kolumna] – najpierw wiersz (który rząd), potem kolumna (która pozycja w rzędzie).
Tworzenie tablicy 2D
Sposób 1: Deklaracja z rozmiarem
// Tablica 3 wiersze × 4 kolumny (pusta – same zera) int[,] tablica = new int[3, 4]; // 0 1 2 3 ← kolumny // 0 [ 0 , 0 , 0 , 0 ] // 1 [ 0 , 0 , 0 , 0 ] // 2 [ 0 , 0 , 0 , 0 ] // Tablica stringów 2×3 string[,] imiona = new string[2, 3]; // pusta – same null // Tablica double 5×5 double[,] macierz = new double[5, 5];
Sposób 2: Inicjalizacja z wartościami
// Od razu z wartościami int[,] tablica = { { 1, 2, 3 }, // wiersz 0 { 4, 5, 6 }, // wiersz 1 { 7, 8, 9 } // wiersz 2 }; // Plan lekcji (dni × godziny) string[,] plan = { { "Mat", "Pol", "Ang" }, // Poniedziałek { "Fiz", "Che", "Inf" }, // Wtorek { "WF", "His", "Geo" } // Środa }; // Szachownica 8×8 char[,] szachy = new char[8, 8];
Tablica 2D jest prostokątna – każdy wiersz ma taką samą liczbę kolumn.
Dostęp do elementów
Do elementu odwołujesz się przez dwa indeksy w jednym nawiasie: [wiersz, kolumna].
int[,] tab = { { 10, 20, 30 }, // wiersz 0 { 40, 50, 60 }, // wiersz 1 { 70, 80, 90 } // wiersz 2 }; // ODCZYT int a = tab[0, 0]; // 10 (wiersz 0, kolumna 0) int b = tab[1, 2]; // 60 (wiersz 1, kolumna 2) int c = tab[2, 1]; // 80 (wiersz 2, kolumna 1) // ZAPIS tab[0, 0] = 100; // Zmień element [0,0] na 100 tab[1, 1] = 999; // Zmień element [1,1] na 999 Console.WriteLine(tab[0, 0]); // 100 Console.WriteLine(tab[1, 1]); // 999
kolumna 0 kolumna 1 kolumna 2
↓ ↓ ↓
┌──────┬───────┬──────┐
wiersz 0│ 10 │ 20 │ 30 │ tab[0,1] = 20
├──────┼───────┼──────┤
wiersz 1│ 40 │ 50 │ 60 │ tab[1,2] = 60
├──────┼───────┼──────┤
wiersz 2│ 70 │ 80 │ 90 │ tab[2,0] = 70
└──────┴───────┴──────┘
Rozmiar tablicy
Metoda GetLength(wymiar) zwraca rozmiar w danym wymiarze.
int[,] tab = new int[3, 5]; // 3 wiersze × 5 kolumn // Liczba WIERSZY (wymiar 0) int wiersze = tab.GetLength(0); // 3 // Liczba KOLUMN (wymiar 1) int kolumny = tab.GetLength(1); // 5 // Łączna liczba elementów int wszystkie = tab.Length; // 15 (3 × 5) Console.WriteLine($"Tablica {wiersze}×{kolumny}, elementów: {wszystkie}"); // Tablica 3×5, elementów: 15
| Właściwość/Metoda | Co zwraca | Przykład (3×5) |
|---|---|---|
GetLength(0) | Liczba wierszy | 3 |
GetLength(1) | Liczba kolumn | 5 |
Length | Wszystkie elementy | 15 |
Rank | Liczba wymiarów | 2 |
GetLength(0)= wiersze (pierwszy wymiar)GetLength(1)= kolumny (drugi wymiar)
Iteracja – pętle zagnieżdżone
Aby przejść przez całą tablicę 2D, używamy dwóch pętli: zewnętrzna po wierszach, wewnętrzna po kolumnach.
int[,] tab = { { 1, 2, 3 }, { 4, 5, 6 } }; // Pętla zewnętrzna – wiersze for (int w = 0; w < tab.GetLength(0); w++) { // Pętla wewnętrzna – kolumny for (int k = 0; k < tab.GetLength(1); k++) { Console.Write(tab[w, k] + " "); } Console.WriteLine(); // Nowa linia po wierszu } // Wynik: // 1 2 3 // 4 5 6
Dla tablicy 2×3:
- w=0: k=0,1,2 → [0,0], [0,1], [0,2]
- w=1: k=0,1,2 → [1,0], [1,1], [1,2]
Czyli: cały wiersz 0, potem cały wiersz 1, itd.
Wypełnianie tablicy
Wypełnianie wartością
int[,] tab = new int[3, 4]; // Wypełnij wszystko jedynkami for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { tab[w, k] = 1; } }
Wypełnianie kolejnymi liczbami
int[,] tab = new int[3, 4]; int licznik = 1; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { tab[w, k] = licznik; licznik++; } } // Wynik: // 1 2 3 4 // 5 6 7 8 // 9 10 11 12
Wypełnianie losowymi liczbami
Random rnd = new Random(); int[,] tab = new int[3, 4]; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { tab[w, k] = rnd.Next(1, 100); // 1-99 } }
Wypełnianie od użytkownika
int[,] tab = new int[2, 3]; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { Console.Write($"Podaj wartość [{w},{k}]: "); tab[w, k] = int.Parse(Console.ReadLine()); } }
Wyświetlanie tablicy
Proste wyświetlanie
int[,] tab = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { Console.Write(tab[w, k] + " "); } Console.WriteLine(); } // Wynik: // 1 2 3 // 4 5 6 // 7 8 9
Sformatowane wyświetlanie (wyrównane kolumny)
int[,] tab = { { 1, 22, 333 }, { 4444, 5, 66 }, { 7, 888, 9 } }; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { // Wyrównanie do 5 znaków Console.Write($"{tab[w, k],5}"); } Console.WriteLine(); } // Wynik (ładnie wyrównane): // 1 22 333 // 4444 5 66 // 7 888 9
{x,5}– wyrównaj do prawej na 5 znaków{x,-5}– wyrównaj do lewej na 5 znaków
Wyszukiwanie
Znajdowanie wartości
int[,] tab = { { 5, 12, 3 }, { 8, 42, 7 }, { 1, 9, 15 } }; int szukana = 42; bool znaleziono = false; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { if (tab[w, k] == szukana) { Console.WriteLine($"Znaleziono {szukana} na pozycji [{w},{k}]"); znaleziono = true; } } } if (!znaleziono) Console.WriteLine("Nie znaleziono"); // Wynik: Znaleziono 42 na pozycji [1,1]
Znajdowanie minimum i maksimum
int[,] tab = { { 5, 12, 3 }, { 8, 42, 7 }, { 1, 9, 15 } }; int min = tab[0, 0]; int max = tab[0, 0]; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { if (tab[w, k] < min) min = tab[w, k]; if (tab[w, k] > max) max = tab[w, k]; } } Console.WriteLine($"Min: {min}, Max: {max}"); // Min: 1, Max: 42
Suma wszystkich elementów
int[,] tab = { { 1, 2, 3 }, { 4, 5, 6 } }; int suma = 0; for (int w = 0; w < tab.GetLength(0); w++) { for (int k = 0; k < tab.GetLength(1); k++) { suma += tab[w, k]; } } Console.WriteLine($"Suma: {suma}"); // Suma: 21
Sortowanie tablicy 2D
Możesz posortować tablicę 2D traktując ją jako jedną długą sekwencję. Poniżej przykład z Selection Sort.
Sortujemy wszystkie elementy tablicy 2D „jakby” były w jednej linii. Elementy pozostają na swoich miejscach w strukturze 2D, ale ich wartości są posortowane.
Selection Sort na tablicy 2D
int[,] tab = { { 9, 3, 7 }, { 1, 8, 2 }, { 5, 4, 6 } }; int wiersze = tab.GetLength(0); int kolumny = tab.GetLength(1); int n = wiersze * kolumny; // Łączna liczba elementów // Selection Sort for (int i = 0; i < n - 1; i++) { // Pozycja i-tego elementu w tablicy 2D int wi = i / kolumny; // wiersz int ki = i % kolumny; // kolumna // Szukaj minimum od pozycji i int minIdx = i; for (int j = i + 1; j < n; j++) { int wj = j / kolumny; int kj = j % kolumny; int wMin = minIdx / kolumny; int kMin = minIdx % kolumny; if (tab[wj, kj] < tab[wMin, kMin]) { minIdx = j; } } // Zamień elementy int wMin2 = minIdx / kolumny; int kMin2 = minIdx % kolumny; int temp = tab[wi, ki]; tab[wi, ki] = tab[wMin2, kMin2]; tab[wMin2, kMin2] = temp; } // PRZED: DOPO: // 9 3 7 1 2 3 // 1 8 2 → 4 5 6 // 5 4 6 7 8 9
Aby traktować tablicę 2D jak jednowymiarową:
wiersz = indeks / liczbaKolumnkolumna = indeks % liczbaKolumn
Dla tablicy 3×3, indeks 5 to: wiersz = 5/3 = 1, kolumna = 5%3 = 2 → [1,2]
Alternatywa: Sortowanie przez spłaszczenie
int[,] tab = { { 9, 3, 7 }, { 1, 8, 2 } }; int wiersze = tab.GetLength(0); int kolumny = tab.GetLength(1); // 1. Przepisz do tablicy 1D int[] temp = new int[wiersze * kolumny]; int idx = 0; for (int w = 0; w < wiersze; w++) { for (int k = 0; k < kolumny; k++) { temp[idx] = tab[w, k]; idx++; } } // 2. Posortuj tablicę 1D (wbudowana metoda) Array.Sort(temp); // 3. Przepisz z powrotem do 2D idx = 0; for (int w = 0; w < wiersze; w++) { for (int k = 0; k < kolumny; k++) { tab[w, k] = temp[idx]; idx++; } } // Wynik: posortowana tablica 2D
Praktyczne zastosowania
Przykład 1: Tabela mnożenia
int[,] mnozenie = new int[10, 10]; // Wypełnij tabliczkę mnożenia for (int w = 0; w < 10; w++) { for (int k = 0; k < 10; k++) { mnozenie[w, k] = (w + 1) * (k + 1); } } // Ile to 7 × 8? Console.WriteLine(mnozenie[6, 7]); // 56
Przykład 2: Plansza gry (kółko i krzyżyk)
char[,] plansza = { { ' ', ' ', ' ' }, { ' ', ' ', ' ' }, { ' ', ' ', ' ' } }; // Ruch gracza X na pozycji [1,1] (środek) plansza[1, 1] = 'X'; // Ruch gracza O na pozycji [0,0] plansza[0, 0] = 'O'; // Wyświetl planszę for (int w = 0; w < 3; w++) { Console.WriteLine($" {plansza[w, 0]} | {plansza[w, 1]} | {plansza[w, 2]} "); if (w < 2) Console.WriteLine("---+---+---"); } // Wynik: // O | | // ---+---+--- // | X | // ---+---+--- // | |
Przykład 3: Macierz ocen
// Wiersze = uczniowie, Kolumny = przedmioty // Przedmioty: Mat, Pol, Ang int[,] oceny = { { 5, 4, 3 }, // Uczeń 0: Jan { 3, 5, 4 }, // Uczeń 1: Anna { 4, 4, 5 } // Uczeń 2: Piotr }; string[] uczniowie = { "Jan", "Anna", "Piotr" }; // Oblicz średnią każdego ucznia for (int u = 0; u < oceny.GetLength(0); u++) { int suma = 0; for (int p = 0; p < oceny.GetLength(1); p++) { suma += oceny[u, p]; } double srednia = (double)suma / oceny.GetLength(1); Console.WriteLine($"{uczniowie[u]}: średnia {srednia:F2}"); } // Jan: średnia 4.00 // Anna: średnia 4.00 // Piotr: średnia 4.33
Częste błędy
❌ Błąd 1: Zła kolejność indeksów
❌ Źle
// Pomieszanie wierszy z kolumnami tab[kolumna, wiersz]
✅ Dobrze
// Zawsze: wiersz, kolumna tab[wiersz, kolumna]
❌ Błąd 2: Użycie Length zamiast GetLength
❌ Źle
// Length daje WSZYSTKIE elementy! for (int w = 0; w < tab.Length; w++) // Dla 3×4 da 12 – za dużo!
✅ Dobrze
// GetLength(0) = wiersze for (int w = 0; w < tab.GetLength(0); w++) // Dla 3×4 da 3 – poprawnie!
❌ Błąd 3: Wyjście poza zakres
❌ Źle
int[,] tab = new int[3, 4]; tab[3, 0] = 5; // Błąd! Max wiersz to 2
✅ Dobrze
int[,] tab = new int[3, 4]; tab[2, 0] = 5; // OK, wiersz 0-2
❌ Błąd 4: Dwa nawiasy zamiast jednego
❌ Źle (to tablica tablic!)
int[][] tab; // Tablica postrzępiona tab[0][1] = 5; // Dwa nawiasy
✅ Dobrze (tablica 2D)
int[,] tab; // Tablica 2D tab[0, 1] = 5; // Jeden nawias, przecinek
Podsumowanie
- Tablica 2D – prostokątna siatka elementów
- int[,] – deklaracja tablicy 2D
- [wiersz, kolumna] – dostęp do elementu
- GetLength(0) – liczba wierszy
- GetLength(1) – liczba kolumn
- Pętle zagnieżdżone – iteracja przez tablicę
Schemat pracy z tablicą 2D
// 1. Tworzenie int[,] tab = new int[3, 4]; // lub z wartościami { {...}, {...} } // 2. Rozmiar int wiersze = tab.GetLength(0); int kolumny = tab.GetLength(1); // 3. Dostęp tab[0, 0] = 10; // zapis int x = tab[1, 2]; // odczyt // 4. Iteracja for (int w = 0; w < wiersze; w++) { for (int k = 0; k < kolumny; k++) { // użyj tab[w, k] } }
Zadania praktyczne
📝 Zadanie 1: Suma i średnia
Utwórz tablicę 3×4 wypełnioną losowymi liczbami 1-100. Oblicz i wyświetl:
- Sumę wszystkich elementów
- Średnią arytmetyczną
- Wartość minimalną i maksymalną
📝 Zadanie 2: Ramka z gwiazdek
Utwórz tablicę char 5×10. Wypełnij ją tak, aby brzegi były gwiazdkami (*), a środek spacjami. Wyświetl wynik:
********** * * * * * * **********
📝 Zadanie 3: Suma wierszy i kolumn
Dla tablicy 4×4 z losowymi liczbami 1-20 oblicz i wyświetl:
- Sumę każdego wiersza
- Sumę każdej kolumny
⭐ Zadanie 4: Przekątna
Utwórz tablicę 5×5. Wypełnij ją zerami, ale na głównej przekątnej (gdzie wiersz == kolumna) wpisz jedynki. Wyświetl wynik – powinna powstać "macierz jednostkowa".
1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1
⭐ Zadanie 5: Sortowanie tablicy 2D
Utwórz tablicę 3×4 wypełnioną losowymi liczbami 1-50. Posortuj ją rosnąco (używając Selection Sort lub przepisując do tablicy 1D). Wyświetl tablicę przed i po sortowaniu.
⭐⭐ Zadanie 6: Szachownica
Utwórz tablicę char 8×8 reprezentującą szachownicę. Wypełnij ją naprzemiennie znakami 'B' (białe) i 'C' (czarne). Wyświetl planszę.
B C B C B C B C C B C B C B C B B C B C B C B C ...
⭐⭐ Zadanie 7: Wyszukiwanie sąsiadów
Dla tablicy 5×5 z losowymi liczbami znajdź element o największej sumie sąsiadów (góra, dół, lewo, prawo). Uwaga na brzegi tablicy!