MODULE Schaken; (* ZET HIER UW NAAM !!!! *) (* Het schaakbord bestaat uit een matrix van 8 rijen en 8 kolommen. Het schaakspel wordt gespeeld tussen de witte en zwarte stukken, we beperken het hier tot 3 types van stukken: dame, loper en toren. Een dame mag in alle 8 richtingen (ook schuin) bewegen, een loper mag enkel schuin bewegen en een toren mag enkel recht bewegen. Alle drie mogen per zet een onbeperkt aantal vakjes in een bepaalde richting zetten, zolang ze maar binnen het bord blijven. Gegeven is een bepaalde schaaksituatie (run het programma). Gevraagd: (1) Maak de procedure 'IsZetBinnenBord' die voor een gegeven stuk en gegeven richting nagaat of het stuk nog binnen het bord is als het 1 stap in die richting zet. Gebruik hier best de gegeven array 'gZetVectoren', bestudeer deze!! (2) Maak de procedure 'KanStukSlaanInRichting' die voor een gegeven stuk en richting nagaat of het stuk in die richting een ander vijandelijk stuk kan slaan. De procedure geeft terug of dit kan en indien dit kan de index van het vijandelijk stuk in de lijst 'gStukken'. Het stuk voert de zet NIET uit. Merk bovendien op dat een stuk niet over een ander mag springen. (3) Maak de procedure 'IsGeldigeRichting' die nagaat of een stuk in een bepaalde richting mag bewegen (zie schaakregels). Gebruik voor de berekening liefst ORD(richting). (4) Tel voor alle stukken hoeveel vijandelijke stukken het kan slaan (in alle geldige richtingen) en druk dit af. Tip: maak gebruik van (3). (5) Speel het schaakspel vanuit de gegeven situatie: wit en zwart spelen om beurten, wit begint. Elke kleur pakt om beurten 1 vijandelijk stuk. Speel tot geen van beide kleuren nog een stuk kan slaan. Als 1 kleur niets kan pakken, moet hij niets zetten (voor de gemakkelijkheid). Druk de zetten en de overblijvende stukken af. Er zijn soms meerdere zetten mogelijk. Indien haalbaar zoek je tussen alle keuzes degene die het voordeligst is voor wit (= meest overblijvende stukken), anders mag je een zet naar keuze uitvoeren. Opmerkingen: - maak de procedures algemeen, zodat ze voor elke gegeven schaaksituatie blijven werken. - merk op dat je in een procedure een RETURN niet noodzakelijk op het einde moet zetten. Je mag de RETURN ook in het midden binnen iteraties zetten, de procedure wordt dan onmiddellijk beeindigd. Dit kan handig zijn. - maak gebruik van de procedure 'WrStukRc' voor het afdrukken, definitie: PROCEDURE WrStukRc(stuk: StukRc); *) FROM IO IMPORT WrStr, WrLn, RdCard, WrCard, RdInt, WrInt, RdKey, RdLn, WrFixReal; CONST AANTAL_STUKKEN = 6; (* aantal stukken op het bord *) BORD_GROOTTE = 8; TYPE RichtingEn = (VOORUIT, VOORUIT_RECHTS, RECHTS, ACHTERUIT_RECHTS, ACHTERUIT, ACHTERUIT_LINKS, LINKS, VOORUIT_LINKS); (* alle 8 mogelijke richtingen, schuin & recht, in wijzerszin *) VectorRc = RECORD rij, kolom: INTEGER; END; TypeEn = (DAME, TOREN, LOPER); KleurEn = (WIT, ZWART); StukRc = RECORD (* eigenschappen van een stuk *) type: TypeEn; kleur: KleurEn; positie: VectorRc; gepakt: BOOLEAN; (* of stuk gepakt is, staat initieel op FALSE *) END; VAR (* globale variabelen *) gStukken: ARRAY[1..AANTAL_STUKKEN] OF StukRc; (* lijst met alle stukken van het bord *) gBord: ARRAY[1..BORD_GROOTTE],[1..BORD_GROOTTE] OF [0..AANTAL_STUKKEN]; (* het schaakbord, 0 betekent een lege vak, een stuk op die positie wordt aangegeven met de index uit gStukken *) gZetVectoren: ARRAY RichtingEn OF VectorRc; (* voor elke richting bepaalt de vector hoe 1 stap in die richting te zetten, vector voor VOORUIT is (1, 0), VOORUIT_LINKS is (1, -1), ACHTERUIT_RECHTS is (-1, 1), enz. gebruik dit in combinatie met de gegeven procedure VoegVectorToe, definitie: PROCEDURE VoegVectorToe(VAR vector1: VectorRc; vector2: VectorRc); procedure telt vector2 op bij vector 1 *) (************************** GEGEVEN PROCEDURES ***********************************) PROCEDURE Initialisatie(); (* Initialisatie van alle globale variabelen *) VAR i: CARDINAL; positie: VectorRc; BEGIN gZetVectoren[VOORUIT] := VectorRc{ 1, 0}; (* merk op dat dit net hetzelfde is als (maar korter): gZetVectoren[VOORUIT].rij := 1; gZetVectoren[VOORUIT].kolom := 0; *) gZetVectoren[VOORUIT_RECHTS] := VectorRc{ 1, 1}; gZetVectoren[RECHTS] := VectorRc{ 0, 1}; gZetVectoren[ACHTERUIT_RECHTS] := VectorRc{-1, 1}; gZetVectoren[ACHTERUIT] := VectorRc{-1, 0}; gZetVectoren[ACHTERUIT_LINKS] := VectorRc{-1, -1}; gZetVectoren[LINKS] := VectorRc{ 0, -1}; gZetVectoren[VOORUIT_LINKS] := VectorRc{ 1, -1}; gStukken[1] := StukRc{DAME, WIT, VectorRc{4, 1}, FALSE}; (* merk op dat dit net hetzelfde is als (maar korter): gStukken[1].type := DAME; gStukken[1].kleur := WIT; gStukken[1].positie := VectorRc{4, 1}; gStukken[1].gepakt := FALSE; *) gStukken[2] := StukRc{LOPER, WIT, VectorRc{1, 1}, FALSE}; gStukken[3] := StukRc{TOREN, WIT, VectorRc{8, 4}, FALSE}; gStukken[4] := StukRc{TOREN, ZWART, VectorRc{1, 4}, FALSE}; gStukken[5] := StukRc{LOPER, ZWART, VectorRc{6, 6}, FALSE}; gStukken[6] := StukRc{DAME, ZWART, VectorRc{8, 8}, FALSE}; FOR i := 1 TO AANTAL_STUKKEN DO (* vullen gBord *) positie := gStukken[i].positie; gBord[positie.rij][positie.kolom] := i; END; END Initialisatie; PROCEDURE VoegVectorToe(VAR vector1: VectorRc; vector2: VectorRc); (* procedure telt vector2 op bij vector 1 *) BEGIN vector1.rij := vector1.rij + vector2.rij; vector1.kolom := vector1.kolom + vector2.kolom; END VoegVectorToe; PROCEDURE WrStukRc(stuk: StukRc); (* schrijft de eigenschappen van een stuk naar het scherm *) BEGIN IF stuk.kleur = WIT THEN WrStr("witte "); ELSE WrStr("zwarte ");END; CASE stuk.type OF DAME: WrStr("dame"); | LOPER: WrStr("loper"); | TOREN: WrStr("toren"); END; WrStr(" op ");WrCard(stuk.positie.rij, 0);WrStr(", ");WrCard(stuk.positie.kolom, 0); END WrStukRc; (********************************************************************************) (******** wat hierboven staat, moet je normaal gezien niet aan te passen *********) (************************ ZET HIER UW PROCEDURES *********************************) (* PROCEDURE IsZetBinnenBord( ) ; BEGIN END IsZetBinnenBord; PROCEDURE KanStukSlaanInRichting( ) ; BEGIN END KanStukSlaanInRichting; PROCEDURE IsGeldigeRichting( ) ; BEGIN END IsGeldigeRichting; *) (*********************************************************************************) VAR x: CHAR; i: CARDINAL; BEGIN WrLn; Initialisatie(); WrStr("De initieel gegeven schakensituatie:");WrLn; FOR i := 1 TO AANTAL_STUKKEN DO WrStukRc(gStukken[i]);WrLn; END; END Schaken.