Tablice dwuwymiarowe – wiersze i kolumny

Poznasz tablice 2D – struktury do przechowywania danych w formie tabeli. Nauczysz się je tworzyć, wypełniać, przeszukiwać i sortować!

tablica 2D int[,] GetLength wiersze kolumny
01

Po co tablice 2D?

Zwykła tablica to jedna linia danych. Ale co jeśli dane mają strukturę tabeli – wiersze i kolumny?

Przykłady danych 2D w życiu
  • 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
cs/Problem.cs C#
// 😰 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 }
};
02

Czym jest tablica 2D?

Tablica dwuwymiarowa to struktura danych w formie prostokątnej siatki. Każdy element ma dwa indeksy: wiersz i kolumnę.

Analogia: Arkusz kalkulacyjny 📊

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
txt/Wizualizacja.txt Schemat
              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)
Zapamiętaj kolejność!

tablica[wiersz, kolumna] – najpierw wiersz (który rząd), potem kolumna (która pozycja w rzędzie).

03

Tworzenie tablicy 2D

Sposób 1: Deklaracja z rozmiarem

cs/Tworzenie1.cs C#
// 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

cs/Tworzenie2.cs C#
// 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];
Wszystkie wiersze muszą mieć tę samą długość!

Tablica 2D jest prostokątna – każdy wiersz ma taką samą liczbę kolumn.

04

Dostęp do elementów

Do elementu odwołujesz się przez dwa indeksy w jednym nawiasie: [wiersz, kolumna].

cs/Dostep.cs C#
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
txt/Indeksy.txt Schemat
        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
        └──────┴───────┴──────┘
05

Rozmiar tablicy

Metoda GetLength(wymiar) zwraca rozmiar w danym wymiarze.

cs/Rozmiar.cs C#
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ść/MetodaCo zwracaPrzykład (3×5)
GetLength(0)Liczba wierszy3
GetLength(1)Liczba kolumn5
LengthWszystkie elementy15
RankLiczba wymiarów2
Zapamiętaj!
  • GetLength(0) = wiersze (pierwszy wymiar)
  • GetLength(1) = kolumny (drugi wymiar)
06

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.

cs/Iteracja.cs C#
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
Pętla zewnętrzna
w = 0, 1, 2…
Pętla wewnętrzna
k = 0, 1, 2…
Element
tab[w, k]
Jak to działa?

Dla tablicy 2×3:

  1. w=0: k=0,1,2 → [0,0], [0,1], [0,2]
  2. w=1: k=0,1,2 → [1,0], [1,1], [1,2]

Czyli: cały wiersz 0, potem cały wiersz 1, itd.

07

Wypełnianie tablicy

Wypełnianie wartością

cs/Wypelnianie1.cs C#
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

cs/Wypelnianie2.cs C#
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

cs/Wypelnianie3.cs C#
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

cs/Wypelnianie4.cs C#
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());
    }
}
08

Wyświetlanie tablicy

Proste wyświetlanie

cs/Wyswietlanie1.cs C#
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)

cs/Wyswietlanie2.cs C#
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
Formatowanie {wartość,szerokość}
  • {x,5} – wyrównaj do prawej na 5 znaków
  • {x,-5} – wyrównaj do lewej na 5 znaków
09

Wyszukiwanie

Znajdowanie wartości

cs/Szukaj.cs C#
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

cs/MinMax.cs C#
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

cs/Suma.cs C#
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
10

Sortowanie tablicy 2D

Możesz posortować tablicę 2D traktując ją jako jedną długą sekwencję. Poniżej przykład z Selection Sort.

Jak to działa?

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

cs/SelectionSort2D.cs C#
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
Przeliczanie indeksów

Aby traktować tablicę 2D jak jednowymiarową:

  • wiersz = indeks / liczbaKolumn
  • kolumna = indeks % liczbaKolumn

Dla tablicy 3×3, indeks 5 to: wiersz = 5/3 = 1, kolumna = 5%3 = 2 → [1,2]

Alternatywa: Sortowanie przez spłaszczenie

cs/SortowanieSplaszcz.cs C#
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
11

Praktyczne zastosowania

Przykład 1: Tabela mnożenia

cs/TabliczkaMnozenia.cs C#
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)

cs/KolkoKrzyzyk.cs C#
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

cs/Oceny.cs C#
// 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
12

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
13

Podsumowanie

Kluczowe pojęcia
  • 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

cs/Schemat.cs C#
// 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

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!