// pomoci deskaCopy zkousim pozdeji legalnost mych tahu: public Deska ZkusZahratTah(Tah tah) { List <Pozice> seznamPozic = tah.GetSeznamPozic; Pozice odkud = null; Deska deskaCopy = cloneDJ(); if (seznamPozic.Count() == 2) { Pozice kam; odkud = seznamPozic[0]; if (deskaCopy.ProvedPosunKamene(odkud, kam = seznamPozic[1], tah)) { return(deskaCopy); } return(null); } foreach (Pozice kam in seznamPozic) { if (odkud != null && !deskaCopy.JePosunPreskokemKameneProtihrace(odkud, kam)) { return(null); } if (odkud != null) { deskaCopy.ProvedPosunKamene(odkud, kam, tah); } odkud = kam; } return(deskaCopy); }
// Test na Legalni posun figurkou a zaroven Posun Bez preskoku: public bool JdeOLegalniPosunBezPreskoku(Pozice odkud, Pozice kam) { return(!JePolePrazdne(odkud) && JePolePrazdne(kam) && // pole odkud neni prazdne a pole kam je prazdne a zaroven musi byt splnena jedna z podminek: (RozdilPozicVyska(odkud, kam, true) == RozdilPozicSirka(odkud, kam, true) || // 1. absolutni rozdil vysek, sirek je stejny (Diagonalni posun) RozdilPozicVyska(odkud, kam, true) == 0 || // 2. rozdil vysek je 0, cili vodorovny posun RozdilPozicSirka(odkud, kam, true) == 0) && // 3. rozdil sirek je 0, cili svisly posun JsouPoleMeziPosunemPrazdne(odkud, kam)); // 4. pole mezi posunem jsou prazdna }
// Pomocna metoda Klonuj() - vyrabim si novou identickou instanci objektu Pozice public Pozice Klonuj() { Pozice poz = new Pozice(); poz.SetVyska(vyska); poz.SetSirka(sirka); return(poz); }
// Za zadanych [sirka,vyska] intů si vytvorim Pozici - objekt se sloty x,y: public Pozice VytvorPozici(int sirka, int vyska) { Pozice pozice = new Pozice(); pozice.SetVyska(vyska); pozice.SetSirka(sirka); return(pozice); }
// Skok o jedno policko (rakticky 8 ruznych smeru) public bool JePosunPreskokem(Pozice odkud, Pozice kam) { return (((RozdilPozicVyska(odkud, kam, true) == 2 && RozdilPozicSirka(odkud, kam, true) == 2) && // skacu ob-jedno policko // tady jsem mel chybu, bylo potreba osetrit 3 mozne stavy, kdy jsou bud obe s,v stejne !JePolePrazdne(odkud) && JePolePrazdne(kam)) || // a zaroven skacu z neprazdneho na prazdne policko ((RozdilPozicVyska(odkud, kam, true) == 2 && RozdilPozicSirka(odkud, kam, true) == 0) && // stav kdy je pouze v rozdilna o 2 policka !JePolePrazdne(odkud) && JePolePrazdne(kam)) || ((RozdilPozicVyska(odkud, kam, true) == 0 && RozdilPozicSirka(odkud, kam, true) == 2) && // stav kdy je pouze s rozdilna o 2 policka !JePolePrazdne(odkud) && JePolePrazdne(kam))); }
// Rozdil 2-ou pozic SIRKOVY (univerzalni pouziti): public int RozdilPozicSirka(Pozice odkud, Pozice kam, bool abs) { if (abs) { return(Math.Abs(kam.GetSirka - odkud.GetSirka)); } else { return(kam.GetSirka - odkud.GetSirka); } }
// Test, zda-li se jedna o Objekt Pozice a zda-li obsahuje sloty vyska, sirka: public bool equals(Object srovnavana) { if (typeof(Object) != typeof(Pozice)) { return(false); } Pozice sr = (Pozice)srovnavana; return(vyska == sr.GetVyska && sirka == sr.GetSirka); }
// zjistuje prazdne pozice nebo preskocitelne(protihracova pozice) v danem smeru sirka, vyska: private List <Pozice> ZjistiPoziceVeSmeru(Deska deska, Pozice vychoziPozice, Pozice pomocnaPozice, int sirka, int vyska, bool jenPreskok, bool bezPreskoku) { // rekurzivne si pricitam nebo odecitam o jednicku (sirku a vysku Pozice) int novaVyska = vychoziPozice.GetVyska + vyska; int novaSirka = vychoziPozice.GetSirka + sirka; if (Pozice.OdpovidaRozsahu(novaSirka) && Pozice.OdpovidaRozsahu(novaVyska)) { pomocnaPozice.SetSirka(novaSirka); pomocnaPozice.SetVyska(novaVyska); // Jestlize je vedlejsi policko prazdne if (deska.JePolePrazdne(pomocnaPozice)) { // bool hodnota - kdyz chci zjistit jen ty pozice kdy neskacu pres protihrace: if (!jenPreskok) { List <Pozice> seznamPozic = new List <Pozice>(); //rekurzivne volam tutez funkci, dokud parametry novaVyska a novaSirka odpovidaji rozsahu desky: List <Pozice> vracenePozice = ZjistiPoziceVeSmeru(deska, pomocnaPozice, pomocnaPozice.Klonuj(), sirka, vyska, false, true); seznamPozic.Add(pomocnaPozice.Klonuj()); if (vracenePozice != null) { seznamPozic.AddRange(vracenePozice); } return(seznamPozic); } return(null); } // jestlize je vedleji policko obsazene: novaSirka = vychoziPozice.GetSirka + sirka * 2; novaVyska = vychoziPozice.GetVyska + vyska * 2; if (Pozice.OdpovidaRozsahu(novaSirka) && Pozice.OdpovidaRozsahu(novaVyska)) { pomocnaPozice.SetSirka(novaSirka); pomocnaPozice.SetVyska(novaVyska); // Jestlize se jedna o preskok kamene soupere: if (deska.JePosunPreskokemKameneProtihrace(vychoziPozice, pomocnaPozice)) { List <Pozice> seznamPozic = new List <Pozice>(); seznamPozic.Add(pomocnaPozice.Klonuj()); return(seznamPozic); } return(null); } return(null); } return(null); }
// Kdekoliv, kde si potrebuju vypsat seznamPozic v textovem formatu public string VratJakoText() { string result = "["; for (int i = 0; i < seznamPozic.Count(); ++i) { Pozice p = seznamPozic[i]; result = result + p.VratJakoText(); } result = result + "]"; return(result.ToUpper()); }
// Vysledkem teto metody je Pozice, ktera se pozdeji ma vymazat - preskocit pri ztv. ob-skoku pres soupere: public Pozice VratPoziciMeziPosunem(Pozice odkud, Pozice kam) { if (!JePosunPreskokem(odkud, kam)) // Vyvolani vyjimky kdyz nejde o ob-skokem { MessageBox.Show("Doslo k vyjimce v metode VratPoziciMeziPosunem pro aktualni desku"); throw new Exception("Tento skok neni preskokem!"); } int vyska = odkud.GetVyska + RozdilPozicVyska(odkud, kam, false) / 2; int sirka = odkud.GetSirka + RozdilPozicSirka(odkud, kam, false) / 2; return(VytvorPozici(sirka, vyska)); }
// Zahraj tah: // Pomocna kontrola, kde se mi stala chyba public bool ZahrajTah(Tah tah) { List <Pozice> seznamPozic = tah.GetSeznamPozic; Pozice odkud = null; List <Pozice> odehranePozice = new List <Pozice>(); foreach (Pozice kam in seznamPozic) { odehranePozice.Add(kam); if (odkud != null && !ProvedPosunKamene(odkud, kam, tah)) { MessageBox.Show("VYJIMKA: Metoda ProvedPosunKamene(odkud, kam) nebyla provedena !"); MessageBox.Show("ZahrajTah-vstupni parametr tah byl: " + tah.VratJakoText()); throw new Exception("metoda ZahrajTah byla zavolana pro neplatny tah !"); } odkud = kam; } return(true); }
// Generuje tahy - Pouze Preskoku: public void GenerujTahyPreskoku(Pozice odkud, Deska deska, List <Pozice> seznamPozicPreskoku, List <Tah> seznamVygenerovanychTahu) { List <Pozice> seznamPreskoku = new List <Pozice>(seznamPozicPreskoku); List <Pozice> poziceProPreskok = VratPoziceKamJdeSkocit(deska, odkud, true); // negace true je false - budu zjistovat preskoky if (poziceProPreskok.Count() == 0) { seznamVygenerovanychTahu.Add(MainWindow.VytvorTah(new List <Pozice>(seznamPreskoku))); return; } foreach (Pozice kam in poziceProPreskok) { seznamPreskoku.Add(kam); deska.ProvedPosunKamene(odkud, kam, null); GenerujTahyPreskoku(kam, deska, seznamPreskoku, seznamVygenerovanychTahu); int index = seznamPreskoku.Count() - 1; seznamPreskoku.RemoveAt(index); deska.VratZpetPosunKamene(kam, odkud, deska.VratPoziciMeziPosunem(kam, odkud)); } }
// Slozitejsi test, zda-li jsou policka mezi posunem prazdna - tzv. Posun Bez Preskoku: public bool JsouPoleMeziPosunemPrazdne(Pozice odkud, Pozice kam) { if (RozdilPozicVyska(odkud, kam, true) <= 1 && RozdilPozicSirka(odkud, kam, true) <= 1) { return(true); // Automaticky, kdyz je rozdil nulovy nebo jen o jednu pozici, vysledek je true } int pocet = Math.Max(RozdilPozicVyska(odkud, kam, true), RozdilPozicSirka(odkud, kam, true)); for (int i = 1; i < pocet; ++i) { int znamenko; int sirka; int vyska; if (odkud.GetSirka == kam.GetSirka) { sirka = odkud.GetSirka; } else { znamenko = Math.Sign(kam.GetSirka - odkud.GetSirka); sirka = odkud.GetSirka + i * znamenko; } if (odkud.GetVyska == kam.GetVyska) { vyska = kam.GetVyska; } else { znamenko = Math.Sign(kam.GetVyska - odkud.GetVyska); vyska = odkud.GetVyska + i * znamenko; } if (!JePolePrazdne(VytvorPozici(sirka, vyska))) // pokud na zadane nove vytvorene pozici neni nula, ukonci cyklus a vysledek metody je false { return(false); } } return(true); // pokud cyklus prosel cely, tak vysledek metody je true }
// pouziti pozdeji v metodach GenerujTahy a GenerujTahyPreskoku public bool VratZpetPosunKamene(Pozice odkud, Pozice kam, Pozice preskocena) { int odkudKamen = hraciDeska[odkud.GetVyska, odkud.GetSirka]; if (preskocena == null && JdeOLegalniPosunBezPreskoku(odkud, kam)) { hraciDeska[kam.GetVyska, kam.GetSirka] = odkudKamen; hraciDeska[odkud.GetVyska, odkud.GetSirka] = 0; return(true); } if (JePosunPreskokem(odkud, kam)) { Pozice preskakovanaPozice = VratPoziciMeziPosunem(odkud, kam); if (hraciDeska[preskakovanaPozice.GetVyska, preskakovanaPozice.GetSirka] == 0) { hraciDeska[kam.GetVyska, kam.GetSirka] = odkudKamen; hraciDeska[odkud.GetVyska, odkud.GetSirka] = 0; hraciDeska[preskakovanaPozice.GetVyska, preskakovanaPozice.GetSirka] = MainWindow.VratOpacnyTypKamene(odkudKamen); return(true); } return(false); } return(false); }
// pouziti pozdeji v metodach GenerujTahy, GenerujNejlepsiTah public bool vratTahZpet(Tah tah) { Pozice odkud = null; List <Pozice> seznamPozic = new List <Pozice>(tah.GetSeznamPozic); seznamPozic.Reverse(); List <Pozice> preskoceneKameny = new List <Pozice>(tah.GetPreskoceneKameny); foreach (Pozice kam in seznamPozic) { if (odkud != null) { Pozice preskocena = new Pozice(); if (preskoceneKameny.Count() == 0) { preskocena = null; } else { preskocena = preskoceneKameny.Last(); int index = preskoceneKameny.Count() - 1; preskoceneKameny.RemoveAt(index); } if (!VratZpetPosunKamene(odkud, kam, preskocena)) { MessageBox.Show("VYJIMKA: metoda vratTahZpet byla zavolana pro neplatny tah!"); MessageBox.Show("vratTahZpet Odkud: " + odkud.VratJakoText() + "vratTahZpet Kam: " + kam.VratJakoText() + "vratTahZpet preskocena: " + preskocena); throw new Exception("metoda vratTahZpet byla zavolana pro neplatny tah!"); } } odkud = kam; } return(true); }
// Prakticky presun, vymazani kamenu z desky, cili pole jako takove // meni hodnoty [8,8] svych prvku, muze to byt vzdy jen jedna ze tri hodnot: // 0 = volno, 1 = bily hrac, 2 = cerny hrac public bool ProvedPosunKamene(Pozice odkud, Pozice kam, Tah tah) { int odkudKamen = hraciDeska[odkud.GetVyska, odkud.GetSirka]; if (JdeOLegalniPosunBezPreskoku(odkud, kam)) { hraciDeska[kam.GetVyska, kam.GetSirka] = odkudKamen; hraciDeska[odkud.GetVyska, odkud.GetSirka] = 0; return(true); } if (JePosunPreskokemKameneProtihrace(odkud, kam)) { Pozice preskakovanyKamen = VratPoziciMeziPosunem(odkud, kam); hraciDeska[kam.GetVyska, kam.GetSirka] = odkudKamen; hraciDeska[odkud.GetVyska, odkud.GetSirka] = 0; hraciDeska[preskakovanyKamen.GetVyska, preskakovanyKamen.GetSirka] = 0; if (tah != null) { tah.PridejPreskocenyKamen(preskakovanyKamen); // ve tride Tah je slot na preskocene kameny } return(true); } return(false); }
// Zjisti seznam pozic kam vsude jde z vychozi pozice skocit. // Prakticky se jedna o zjisteni skoku do 8-mi smeru (existuje 8 okolnich policek, lisicich se x,y o jednicku) // bud jsou obsazene, nebo volne a mozna i jde skakat dal nez o jedno .... viz seznamPozic public List <Pozice> VratPoziceKamJdeSkocit(Deska deska, Pozice vychoziPozice, bool jenPreskok) { List <Pozice> seznamPozic = new List <Pozice>(); Pozice pomocnaPozice = new Pozice(); List <Pozice> generovanePozice = new List <Pozice>(); int sirka; int vyska; pomocnaPozice.SetSirka(vychoziPozice.GetSirka); pomocnaPozice.SetVyska(vychoziPozice.GetVyska); for (int i = 0; i < 8; ++i) { switch (i) { case 0: vyska = 1; sirka = 0; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { continue; } seznamPozic.AddRange(generovanePozice); continue; case 1: vyska = 1; sirka = 1; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { continue; } seznamPozic.AddRange(generovanePozice); continue; case 2: vyska = 0; sirka = 1; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { continue; } seznamPozic.AddRange(generovanePozice); continue; case 3: vyska = -1; sirka = 1; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { continue; } seznamPozic.AddRange(generovanePozice); continue; case 4: vyska = -1; sirka = 0; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { continue; } seznamPozic.AddRange(generovanePozice); continue; case 5: vyska = -1; sirka = -1; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { continue; } seznamPozic.AddRange(generovanePozice); continue; case 6: vyska = 0; sirka = -1; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { continue; } seznamPozic.AddRange(generovanePozice); continue; case 7: vyska = 1; sirka = -1; generovanePozice = ZjistiPoziceVeSmeru(deska, vychoziPozice, pomocnaPozice, sirka, vyska, jenPreskok, false); if (generovanePozice == null) { break; } seznamPozic.AddRange(generovanePozice); break; } } return(seznamPozic); }
public void PridejPreskocenyKamen(Pozice preskoceny) { preskoceneKameny.Add(preskoceny); }
// Test na celkovou legalnost meho pohybu po desce: public bool JePosunLegalni(Pozice odkud, Pozice kam) { return(JdeOLegalniPosunBezPreskoku(odkud, kam) || JePosunPreskokemKameneProtihrace(odkud, kam)); // mam jenom 2 druhy tahu: diagonalne-ortogonalni bez preskoků soupere // nebo ciste jen preskok soupere ob-policko }
// Test, jestli skacu ob-policko a na tom ob-policku byl souper: public bool JePosunPreskokemKameneProtihrace(Pozice odkud, Pozice kam) { return(JePosunPreskokem(odkud, kam) && // jedna se o ob-skok a zaroven !JePolePrazdne(VratPoziciMeziPosunem(odkud, kam)) && // policko, ktere jsem ob-skocil neni prazdne a zaroven VratObsahPole(odkud) != VratObsahPole(VratPoziciMeziPosunem(odkud, kam))); // obsah pole odkud (ja, treba 1=bily) se nerovna obsahu pole policka preskoceneho (trebas souper 2=cerny) }
// Metoda na kontrolu souperovych kamenu vedle - VratPoziceKamJdeSkocit->ZjisitiPozice VeSmeru->JePosunPreskokemKameneProtihrace->seznamPozic public bool JeMoznostPreskoku(Deska deska, Pozice vychoziPozice) { return(!(generator.VratPoziceKamJdeSkocit(deska, vychoziPozice, true).Count() == 0)); }
// Pozice je pomocny objekt, ma stejne cleny vyska(0-7), sirka(0-7) jako ma Deska, coz je pole [8,8] // na zadane pozici je bud cislo 1 (Bily) nebo cislo 2 (Cerny hrac): public int VratObsahPole(Pozice pozice) { return(hraciDeska[pozice.GetVyska, pozice.GetSirka]); }
// Kontrolni dotaz, jestli je pozice v poli prazdna [v,s] = 0: public bool JePolePrazdne(Pozice pozice) { return(VratObsahPole(pozice) == 0); }