Oki to zacznę po kawałku od początku...
1) Tworzę sobie tablicę ruchy, która ma być odpowiednikiem planszy do gry...
public static int[][] ruchy = new int[15][];
2) Do tej tablicy tworzę drugą która jedynie przechowuje indeksy do listy - tablica indeksów wypełniona jest kolejnymi liczbami od 0 do 224...
public static int[][] indeksy_Board = new int[15][];
3) Tworzę pewną klasę której obiekty będę przechowywał na liście 225 elementów
public class TypListy
{
public unsafe int*[] poziomo { get; set; }
public unsafe int*[] pionowo { get; set; }
public unsafe int*[] skosL { get; set; }
public unsafe int*[] skosP { get; set; }
public int[] zasieg { get; set; }
}
4) Tworzę listę elementów
public static List<TypListy> BoardList = new List<TypListy>();
5) Wypełniam listę odpowiednimi elementami tablicy ruchy w formie wskaźników
public unsafe static void attak()
{
for (int i = 0; i < 15; i++) //x
for (int j = 0; j < 15; j++) //y
{
int*[] _pionowo = new int*[9];
int*[] _poziomo = new int*[9];
int*[] _skosL = new int*[9];
int*[] _skosP = new int*[9];
int[] _zasieg = { 0, 0, 0, 0 };
int licznik = 0;
// wskaźniki na 1 element ustawiam żeby wszystkie na coś wskazywały ;P
fixed (int* pirat = &ruchy[0][0])
{
for (int www = 0; www < 9; www++)
{
_pionowo[www] = pirat;
_poziomo[www] = pirat;
_skosL[www] = pirat;
_skosP[www] = pirat;
}
}
//==========================================
//pionowo
//==========================================
//od góry do ij
for (int x = 4; x >= 0; x--)
{
try
{
fixed (int* adres = &ruchy[i - x][j])
{
_pionowo[licznik] = adres;
licznik++;
}
}
catch { };
}
//od ij+1 do dołu=============================
for (int x = 1; x < 5; x++)
{
try
{
fixed (int* adres = &ruchy[i + x][j])
{
_pionowo[licznik] = adres;
licznik++;
}
}
catch { };
}
_zasieg[0] = licznik;
licznik = 0;
//==========================================
//poziomo
//==========================================
//od lewej do ij
for (int x = 4; x >= 0; x--)
{
try
{
fixed (int* adres = &ruchy[i][j - x])
{
_poziomo[licznik] = adres;
licznik++;
}
}
catch { };
}
// od ij+1 do prawej 4 elementy
for (int x = 1; x < 5; x++)
{
try
{
fixed (int* adres = &ruchy[i][j + x])
{
_poziomo[licznik] = adres;
licznik++;
}
}
catch { };
}
_zasieg[1] = licznik;
licznik = 0;
//==========================================
//skosL \
//==========================================
//od lewej góry do ij
for (int x = 4; x >= 0; x--)
{
try
{
fixed (int* adres = &ruchy[i - x][j - x])
{
_skosL[licznik] = adres;
licznik++;
}
}
catch { };
}
// od ij do prawego dołu 4 elementy
for (int x = 1; x < 5; x++)
{
try
{
fixed (int* adres = &ruchy[i + x][j + x])
{
_skosL[licznik] = adres;
licznik++;
}
}
catch { };
}
_zasieg[2] = licznik;
licznik = 0;
//==========================================
//skosP /
//==========================================
//od prawej góry do ij
for (int x = 4; x >= 0; x--)
{
try
{
fixed (int* adres = &ruchy[i - x][j + x])
{
_skosP[licznik] = adres;
licznik++;
}
}
catch { };
}
// od ij do lewego dołu 4 elementy
for (int x = 1; x < 5; x++)
{
try
{
fixed (int* adres = &ruchy[i + x][j - x])
{
_skosP[licznik] = adres;
licznik++;
}
}
catch { };
}
_zasieg[3] = licznik;
licznik = 0;
//=============================================
BoardList.Add(new TypListy { pionowo = _pionowo, poziomo = _poziomo, skosL = _skosL, skosP = _skosP, zasieg = _zasieg });
}
}
6) Teraz zrobiłem sobie metodę do sprawdzania czy konkretny element tablicy ruchy jest częścią kolejnych pięciu takich samych elementów pod względem wartość np = 1
public int fastwinsearch(int numerek, int gracz)
{
int licznik = 0;
int suma = 0;
int zasiegaj = 0;
//pionowo ====================================
zasiegaj = BoardList[numerek].zasieg[0];
if (zasiegaj >= 5)
{
unsafe
{
while (suma < 5 && licznik < zasiegaj)
{
if (*BoardList[numerek].pionowo[licznik] == gracz) suma++;
else suma = 0;
licznik++;
}
}
if (suma == 5) return 5;
suma = 0;
licznik = 0;
}
//poziomo ====================================
zasiegaj = BoardList[numerek].zasieg[1];
if (zasiegaj >= 5)
{
unsafe
{
while (suma < 5 && licznik < zasiegaj)
{
if (*BoardList[numerek].poziomo[licznik] == gracz) suma++;
else suma = 0;
licznik++;
}
}
if (suma == 5) return 5;
suma = 0;
licznik = 0;
}
//skosL ====================================
zasiegaj = BoardList[numerek].zasieg[2];
if (zasiegaj >= 5)
{
unsafe
{
while (suma < 5 && licznik < zasiegaj)
{
if (*BoardList[numerek].skosL[licznik] == gracz) suma++;
else suma = 0;
licznik++;
}
}
if (suma == 5) return 5;
suma = 0;
licznik = 0;
}
//skosP ====================================
zasiegaj = BoardList[numerek].zasieg[3];
if (zasiegaj >= 5)
{
unsafe
{
while (suma < 5 && licznik < zasiegaj)
{
if (*BoardList[numerek].skosP[licznik] == gracz) suma++;
else suma = 0;
licznik++;
}
}
if (suma == 5) return 5;
suma = 0;
licznik = 0;
}
return 0;
}
7) No i mam też jakąś prostą metodę czyszczącą planszę
public void czysc()
{
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++)
{
buttony[i][j].BackColor = Color.FromArgb(171, 156, 156);
buttony[i][j].Text = "";
ruchy[i][j] = 0;
}
}
8) Póki co wstawiam sobie na planszy liczby 1 i po każdym wstawieniu sprawdzam czy udało się utworzyć 5 w linii - jeśli tak to wyświetlam napis że wygrana i czyszczę planszę i dalej chcę sobie powstawiać tak samo te 1 ale już nie działa....
public void buttony_Click(object sender, EventArgs e)
{
if (flaga)
{
flaga = false; //blokada
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++)
{
if (sender == buttony[i][j])
{
//czysc();
buttony[i][j].Text = "O";
buttony[i][j].BackColor = Color.FromArgb(100, 126, 56);
ruchy[i][j] = 1;
if (fastwinsearch(indeksy_Board[i][j], 1) == 5)
{
MessageBox.Show("Znaleziono wygraną!!");
czysc();
}
}
}
flaga = true; //zwolnienie blokady
}
}
Znalazłem takie info w necie:
Quote: fixed : pozwala blokować obiekty (zmienne) w pamięci. Informuje system, by nie zmieniał położenia w pamięci danego obiektu (standardowo system dowolnie umieszcza i przesuwa obiekty w obrębie sterty - jednak gdybyśmy wskazywali na jakiś obiekt wskaźnikiem, a w międzyczasie zmienił by on swoje położenie, doprowadziło by to do błędów).
Tak jak ja to rozumiem to faktycznie GC blokuje możliwość przesunięcia w pamięci tablicy, ale tylko na czas gdy jesteśmy wewnątrz bloku fixed natomiast po wyjściu z niego tablica dalej może być przenoszona.. W moim przypadku na samym początku uruchamiania programu następuje uzupełnienie wskaźników na liście i wtedy faktycznie jest na chwilę blokowana tablica. Natomiast później wskaźniki nie są w żaden sposób uaktualniane więc jeśli GC przesunie sobie w inne miejsce taką tablicę to adresy na jakie wskazują stają się nieaktualne i moja metoda fastwinsearch nie jest w stanie nic znaleźć... Takie jest moje zdanie, ale mogę się mylić... Co o tym myślicie?