Advertisement
csaki

Készemélyes játékok (mestint)

Apr 2nd, 2014
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 23.28 KB | None | 0 0
  1. // http://hu.wikipedia.org/wiki/Nim
  2. // http://aries.ektf.hu/~gkusper/mesterseges_intelligencia.v.1.0.4.pdf
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8.  
  9. namespace mesintgyak_jatek
  10. {
  11.     // Az AbsztraktÁllpot osztályt ki kellett bővíteni a GetHeurisztika metódussal.
  12.     // Egyébként megegyezik az előző fejezetben tárgyalt változattal.
  13.     abstract class AbsztraktÁllapot : ICloneable
  14.     {
  15.         public abstract bool ÁllapotE();
  16.         public abstract bool CélÁllapotE();
  17.         public abstract int OperátorokSzáma();
  18.         public abstract bool SzuperOperátor(int i);
  19.         public virtual object Clone() { return MemberwiseClone(); }
  20.         public override bool Equals(Object a) { return false; }
  21.         public override int GetHashCode() { return base.GetHashCode(); }
  22.         // Ez a metódus adja vissza, mennyire jó az adott állapot
  23.         // Ez csak egy hook, felül kell írni, ha
  24.         // kétszemélyes játékot vagy best-first algoritmus alkalmazunk,
  25.         // vagy bármilyen más algoritmust, ami heurisztikán alapszik.
  26.         // Más esetben, pl. backtrack esetén, nem kell felülírni.
  27.         public virtual int GetHeurisztika() { return 0; }
  28.     }
  29.  
  30.     // Az előző fejezetben ismertetett Csúcs osztályt bővítettük
  31.     // egy-két metódussal, amely a két személyes játékok megvalósításához kell.
  32.     class Csúcs
  33.     {
  34.         AbsztraktÁllapot állapot;
  35.         int mélység;
  36.         Csúcs szülő;
  37.         // A szülőkön túl a gyermekeket is tartalmazza a Csúcs osztály.
  38.         List<Csúcs> gyermekek = new List<Csúcs>();
  39.         // Ez a mező tartalmazza, hogy melyik operátor segítségével jutottunk ebbe a csúcsba a szülő csúcsból.
  40.         // Ennek segítségével tudom megmondani, melyik az ajánlott lépés NegaMaxMódszer esetén.
  41.         int melyikOperátorralJutottamIde = -1; // ha -1, akkor még nincs beállítva
  42.         public Csúcs(AbsztraktÁllapot kezdőÁllapot)
  43.         {
  44.             állapot = kezdőÁllapot;
  45.             mélység = 0;
  46.             szülő = null;
  47.         }
  48.         public Csúcs(Csúcs szülő)
  49.         {
  50.             állapot = (AbsztraktÁllapot)szülő.állapot.Clone();
  51.             mélység = szülő.mélység + 1;
  52.             this.szülő = szülő;
  53.         }
  54.         // Erre a metódusra azért van szükség, hogy a kiterjesztés működjön a JátékCsúcsra is.
  55.         protected virtual Csúcs createGyermekCsúcs(Csúcs szülő) { return new Csúcs(szülő); }
  56.         public Csúcs GetSzülő() { return szülő; }
  57.         public int GetMélység() { return mélység; }
  58.         public bool TerminálisCsúcsE() { return állapot.CélÁllapotE(); }
  59.         public int OperátorokSzáma() { return állapot.OperátorokSzáma(); }
  60.         public bool SzuperOperátor(int i)
  61.         {
  62.             // megjegyzem, melyik operátorral jutottam ebbe az állapotba
  63.             melyikOperátorralJutottamIde = i;
  64.             return állapot.SzuperOperátor(i);
  65.         }
  66.         public override bool Equals(Object obj)
  67.         {
  68.             Csúcs cs = (Csúcs)obj;
  69.             return állapot.Equals(cs.állapot);
  70.         }
  71.         public override int GetHashCode() { return állapot.GetHashCode(); }
  72.         public override String ToString() { return állapot.ToString(); }
  73.         // Alkalmazza az összes alkalmazható operátort.
  74.         // Visszaadja az így előálló új csúcsokat.
  75.         public List<Csúcs> Kiterjesztés()
  76.         {
  77.             gyermekek = new List<Csúcs>();
  78.             for (int i = 0; i < OperátorokSzáma(); i++)
  79.             {
  80.                 // Új gyermek csúcsot készítek.
  81.                 // Ezzel a sorral nem működik a Kiterjesztés a JátékCsúcsban.
  82.                 // --- Csúcs újCsúcs = new Csúcs(this); ---
  83.                 // Ezért ezt használjuk:
  84.                 Csúcs újCsúcs = createGyermekCsúcs(this);
  85.                 // Kipróbálom az i.-dik alapoperátort. Alkalmazható?
  86.                 if (újCsúcs.SzuperOperátor(i))
  87.                 {
  88.                     // Ha igen, hozzáadom az újakhoz.
  89.                     gyermekek.Add(újCsúcs);
  90.                 }
  91.             }
  92.             return gyermekek;
  93.         }
  94.         // Visszaadja a csúcs heurisztikáját.
  95.         // Ha saját heurisztikát akarunk írni, akkor azt a saját állapot osztályunkba kell megírni.
  96.         public int GetHeurisztika() { return állapot.GetHeurisztika(); }
  97.         // Visszaadja melyik operátorral jutottunk ide.
  98.         // Ezzel az int értékkel kell majd meghívni a SzuperOperátor-t.
  99.         public int GetMelyikOperátorralJutottamIde() { return melyikOperátorralJutottamIde; }
  100.         // Nyomkövetéshez hasznos.
  101.         public void Kiir()
  102.         {
  103.             Console.WriteLine(this);
  104.             foreach (Csúcs gyermek in gyermekek) { gyermek.Kiir(); }
  105.         }
  106.     }
  107.  
  108.     // A
  109.     //játék csúcs a
  110.     //csúcs osztály kibővítése egy heurisztika értékkel.
  111.     // Ezt a fajta csúcsot fel lehet használni a best first algoritmushoz is.
  112.     class JátékCsúcs : Csúcs
  113.     {
  114.         int mennyireJó = -1; // mennyire jó, ha -1, akkor még nincs beállítva
  115.         // Konstruktor:
  116.         // A belső állapotot beállítja a start csúcsra.
  117.         // A hívó felelősége, hogy a kezdő állapottal hívja meg.
  118.         // A start csúcs mélysége 0, szülője nincs.
  119.         public JátékCsúcs(AbsztraktÁllapot kezdőÁllapot) :
  120.             base(kezdőÁllapot) { }
  121.         // Egy új gyermek csúcsot készít.
  122.         // Erre még meg kell hívni egy alkalmazható operátor is, csak azután lesz kész.
  123.         public JátékCsúcs(Csúcs szülő) : base(szülő) { }
  124.         // Erre a metódusra azért van szükség, hogy a kiterjesztés
  125.         // működjön a JátékCsúcsra is.
  126.         protected override Csúcs createGyermekCsúcs(Csúcs szülő)
  127.         {
  128.             return new JátékCsúcs(szülő);
  129.         }
  130.         // Visszaadja a csúcshoz tartozó heurisztikát.
  131.         // Ez a csúcsban lévő állapot heurisztikája
  132.         // megszorozva a paraméterben megkapott szor értékkel.
  133.         // NegaMax esetén a szor általában 1, ha az a játékos lép,
  134.         // akinek jó lépést keresünk, -1, ha az ellenfél lép.
  135.         // Mivel minden állapothoz csak egy heurisztika van, ami nem
  136.         // veszi figyelembe, hogy ki lép, ezért a MiniMax-nak is
  137.         // úgy kell használni ezt a metódust, mint a NegaMax-nak.
  138.         public int GetMennyireJó(int szor)
  139.         {
  140.             if (mennyireJó == -1) mennyireJó = GetHeurisztika() * szor;
  141.             return mennyireJó;
  142.         }
  143.     }
  144.  
  145.     // Ebből kell leszármaztatni a lépés ajánló algoritmusokat, mint a NegaMax módszer.
  146.     abstract class Stratégia
  147.     {
  148.         // Ha a start csúcs zsákutca, akkor null-t ad vissza.
  149.         // Egyébként azt a csúcsot, amibe a stratégia szerint érdemes lépni.
  150.         public abstract JátékCsúcs MitLépjek(JátékCsúcs start);
  151.     }
  152.  
  153.     // Egy lépést ajánl valamely játékosnak a
  154.     //NegaMax módszer alapján.
  155.     // Ehhez előre tekint és a heurisztika meghatározása után megkeresi a legkedvezőbb utat a játék fában.
  156.     // Ha a játékfa levelei terminális csúcsok, akkor a legkedvezőbb út a nyerő stratégia lesz.
  157.     class NegaMaxMódszer : Stratégia
  158.     {
  159.         int maxMélység; // Ennyi lépésre tekintünk előre.
  160.         // Minél több lépésre tekintünk előre, annál intelligensebbnek tűnik a gép, hiszen jobb lépést választ.
  161.         // Ezt a TicTacToe esetén figyelhetjük meg.
  162.         // Ugyanakkor minél több lépést generálunk, annál lassabb lesz az algoritmus.
  163.         // Ennek egy megoldása az Alfabéta-vágás, de ezt nem programoztuk le.
  164.         public NegaMaxMódszer(int intelligencia) { maxMélység = intelligencia; }
  165.         // Egy játékcsúcsot ad vissza.
  166.         // Ennek a GetMelyikOperátorralJutottamIde() függvénye mondja meg,
  167.         // melyik lépést ajánlja a NegaMax módszer.
  168.         // Ha zsákutcában van, akkor null-t ad vissza.
  169.         public override JátékCsúcs MitLépjek(JátékCsúcs start)
  170.         {
  171.             Csúcs levél = MaxLépés(start, start.GetMélység() + maxMélység);
  172.             if (levél == start) return null;
  173.             while (levél.GetSzülő() != start) { levél = levél.GetSzülő(); }
  174.             //levél.Kiir(); // Nyomkövetés esetén hasznos segítség
  175.             return (JátékCsúcs)levél;
  176.         }
  177.         // Feltételezi, hogy a start csúcsban a kérdező játékos kérdezi, mit lépjen.
  178.         // A kérdező játékos legjobb lépését, tehát a legnagyobb heurisztikájú
  179.         // csúcs felé vezető lépést választja.
  180.         // A gyermek csúcsok heurisztikáját NegaMax módszerrel számoljuk.
  181.         private JátékCsúcs MaxLépés(JátékCsúcs start, int maxMélység)
  182.         {
  183.             JátékCsúcs akt = start;
  184.             if (akt.GetMélység() == maxMélység) { return akt; }
  185.             if (akt.TerminálisCsúcsE()) { return akt; }
  186.             List<Csúcs> gyermekek = null;
  187.             gyermekek = akt.Kiterjesztés();
  188.             if (gyermekek.Count == 0) { return akt; }
  189.             JátékCsúcs elsőGyermek = (JátékCsúcs)gyermekek[0];
  190.             JátékCsúcs leg = MinLépés(elsőGyermek, maxMélység);
  191.             int h = leg.GetMennyireJó(+1);
  192.             for (int i = 1; i < gyermekek.Count; i++)
  193.             {
  194.                 JátékCsúcs gyermek = (JátékCsúcs)gyermekek[i];
  195.                 JátékCsúcs legE = MinLépés(gyermek, maxMélység);
  196.                 int hE = legE.GetMennyireJó(+1);
  197.                 if (hE > h) { h = hE; leg = legE; }
  198.             }
  199.             return leg;
  200.         }
  201.         // Felételezi, hogy a start csúcsban a a kérdező játékos ellenfele lép.
  202.         // Az ellenfél játékos legjobb lépését választja, tehát azt,
  203.         // ami a kérdező játékosnak a legrosszabb.
  204.         // Egybe lehetne vonni a MaxLépéssel, hiszen csak 5 helyen más.
  205.         // Ezek a sorokat megjelöltük.
  206.         private JátékCsúcs MinLépés(JátékCsúcs start, int maxMélység)
  207.         {
  208.             JátékCsúcs akt = start;
  209.             if (akt.GetMélység() == maxMélység) { return akt; }
  210.             if (akt.TerminálisCsúcsE()) { return akt; }
  211.             List<Csúcs> gyermekek = null;
  212.             gyermekek = akt.Kiterjesztés();
  213.             if (gyermekek.Count == 0) { return akt; }
  214.             JátékCsúcs elsőGyermek = (JátékCsúcs)gyermekek[0];
  215.             JátékCsúcs leg = MaxLépés(elsőGyermek, maxMélység); //más
  216.             int h = leg.GetMennyireJó(-1); // más
  217.             for (int i = 1; i < gyermekek.Count; i++)
  218.             {
  219.                 JátékCsúcs gyermek = (JátékCsúcs)gyermekek[i];
  220.                 JátékCsúcs legE = MaxLépés(gyermek, maxMélység); //más
  221.                 int hE = legE.GetMennyireJó(-1); //más
  222.                 if (hE < h) { h = hE; leg = legE; } //más
  223.             }
  224.             return leg;
  225.         }
  226.     }
  227.  
  228.     // A Tic Tac Toe játék állapot osztálya.
  229.     class TicTacToeÁllapot : AbsztraktÁllapot
  230.     {
  231.         private static int N = 3; // 3 szor 3-mas tábla
  232.         // NxN-es char mátrix
  233.         // ' ': üres, 'X':első játékos jele, 'O': második játékos jele
  234.         private char[,] tábla;
  235.         private int countX, countO; // X-ek és O-k száma
  236.         private bool nyert; // nyertes állapt-e
  237.         private int üresekSzáma;
  238.         public TicTacToeÁllapot()
  239.         {
  240.             tábla = new char[N, N];
  241.             for (int i = 0; i < N; i++)
  242.             {
  243.                 for (int j = 0; j < N; j++) { tábla[i, j] = ' '; }
  244.             }
  245.             countX = 0; // kezdetben egy X sincs
  246.             countO = 0; // kezdetben egy O sincs
  247.             nyert = false;
  248.             üresekSzáma = N * N;
  249.         }
  250.         public override bool ÁllapotE() { return true; }
  251.         public override bool CélÁllapotE() { return nyert || üresekSzáma == 0; }
  252.         private bool preRak(int x, int y)
  253.         {
  254.             return x >= 0 && x < N && y >= 0 && y < N && tábla[x, y] == ' ';
  255.         }
  256.         private bool rak(int x, int y)
  257.         {
  258.             if (!preRak(x, y)) return false;
  259.             char c;
  260.             if (countX > countO) c = 'O'; else c = 'X';
  261.             tábla[x, y] = c;
  262.             bool régiNyert = nyert;
  263.             nyert = // nem elég általános, csak N = 3-ra jó!
  264.             (tábla[0, y] == c && tábla[1, y] == c && tábla[2, y] == c) ||
  265.             (tábla[x, 0] == c && tábla[x, 1] == c && tábla[x, 2] == c);
  266.             nyert = nyert || (x == y &&
  267.             tábla[0, 0] == c && tábla[1, 1] == c && tábla[2, 2] == c);
  268.             nyert = nyert || (x + y == N - 1 &&
  269.             tábla[0, 2] == c && tábla[1, 1] == c && tábla[2, 0] == c);
  270.             üresekSzáma--;
  271.             if (c == 'X') countX++; else countO++;
  272.             if (ÁllapotE()) return true;
  273.             tábla[x, y] = ' '; // visszavonás
  274.             nyert = régiNyert;
  275.             üresekSzáma++;
  276.             if (c == 'X') countX--; else countO--;
  277.             return false;
  278.         }
  279.         public override int OperátorokSzáma() { return 9; }
  280.         public override bool SzuperOperátor(int i)
  281.         {
  282.             switch (i)
  283.             {
  284.                 case 0: return rak(0, 0);
  285.                 case 1: return rak(0, 1);
  286.                 case 2: return rak(0, 2);
  287.                 case 3: return rak(1, 0);
  288.                 case 4: return rak(1, 1);
  289.                 case 5: return rak(1, 2);
  290.                 case 6: return rak(2, 0);
  291.                 case 7: return rak(2, 1);
  292.                 case 8: return rak(2, 2);
  293.                 default: return false;
  294.             }
  295.         }
  296.         // Ezt most felül kell írni, mert tömb típusú mezőnk is van.
  297.         // Egy szűk területre kell koncentrálni.
  298.         public override object Clone()
  299.         {
  300.             TicTacToeÁllapot új = new TicTacToeÁllapot();
  301.             új.tábla = (char[,])tábla.Clone();
  302.             új.countX = countX;
  303.             új.countO = countO;
  304.             új.nyert = nyert;
  305.             új.üresekSzáma = üresekSzáma;
  306.             return új;
  307.         }
  308.         public override bool Equals(Object a)
  309.         {
  310.             TicTacToeÁllapot másik = (TicTacToeÁllapot)a;
  311.             return tábla.Equals(másik.tábla);
  312.         }
  313.         public override int GetHashCode() { return tábla.GetHashCode(); }
  314.         // Ez a metódus adja vissza, mennyire jó az adott állapot.
  315.         public override int GetHeurisztika()
  316.         {
  317.             if (nyert) return 100 * (3 * N + 1);
  318.             // szabad sorok, oszlopok, és átlok száma
  319.             // szabad a sor, ha csak egy fajta szimbolum van benne
  320.             return szabad('X');
  321.         }
  322.         // Ez egy kicsit általánosra sikerült, hiszen csak
  323.         // szabad('X') formában fogjuk hívni, habár hívható lenne
  324.         // szabad('0') formában is. Ez akkor lesz hasznos, ha a
  325.         // GetHeurisztika() függvényt át akarjuk írni.
  326.         private int szabad(char c)
  327.         {
  328.             int count = 0;
  329.             for (int i = 0; i < N; i++)
  330.             {
  331.                 int sorX = 0, sorO = 0;
  332.                 int oszlopX = 0, oszlopO = 0;
  333.                 for (int j = 0; j < N; j++)
  334.                 {
  335.                     if (tábla[i, j] == 'X') sorX++;
  336.                     if (tábla[i, j] == 'O') sorO++;
  337.                     if (tábla[j, i] == 'X') oszlopX++;
  338.                     if (tábla[j, i] == 'O') oszlopO++;
  339.                 }
  340.                 if (c == 'X' && sorX > 0 && sorO == 0) count += sorX;
  341.                 if (c == 'O' && sorO > 0 && sorX == 0) count += sorO;
  342.                 if (c == 'X' && oszlopX > 0 && oszlopO == 0) count += oszlopX;
  343.                 if (c == 'O' && oszlopO > 0 && oszlopX == 0) count += oszlopO;
  344.             }
  345.             int átló1X = 0, átló1O = 0;
  346.             int átló2X = 0, átló2O = 0;
  347.             for (int i = 0; i < N; i++)
  348.             {
  349.                 if (tábla[i, i] == 'X') átló1X++;
  350.                 if (tábla[i, i] == 'O') átló1O++;
  351.                 if (tábla[N - 1 - i, i] == 'X') átló2X++;
  352.                 if (tábla[N - 1 - i, i] == 'O') átló2O++;
  353.             }
  354.             if (c == 'X' && átló1X > 0 && átló1O == 0) count += átló1X;
  355.             if (c == 'O' && átló1O > 0 && átló1X == 0) count += átló1O;
  356.             if (c == 'X' && átló2X > 0 && átló2O == 0) count += átló2X;
  357.             if (c == 'O' && átló2O > 0 && átló2X == 0) count += átló2O;
  358.             return count;
  359.         }
  360.         public override string ToString()
  361.         {
  362.             StringBuilder sb = new StringBuilder();
  363.             for (int i = 0; i < N; i++)
  364.             {
  365.                 sb.Append('\n');
  366.                 for (int j = 0; j < N; j++)
  367.                 {
  368.                     sb.Append(tábla[i, j]);
  369.                     sb.Append(',');
  370.                 }
  371.                 sb.Remove(sb.Length - 1, 1);
  372.             }
  373.             return sb.ToString();
  374.         }
  375.     }
  376.  
  377.     class Fejben21Állapot : AbsztraktÁllapot
  378.     {
  379.         private static int N = 21; // fejben 21, 21-ig kell menni
  380.         private static int K = 3; // max K-t lehet hozzáadni a számhoz
  381.         private int szám;
  382.         public Fejben21Állapot() { szám = 0; } // az első játékos 0-tól indul
  383.         public override bool ÁllapotE() { return szám <= N; }
  384.         public override bool CélÁllapotE() { return szám == N; }
  385.         // Ennek a játéknak egyszerű nyerő stratégiája van.
  386.         // A kezdő játékos nyer, ha 1-et mond, majd rendre:
  387.         // 5, 9, 13, 17, 21.
  388.         // Ha valaki 1-gyel kezd, akkor az ellenfél mondhat 2, 3, vagy 4-et.
  389.         // Bármelyiket is mondja az ellenfél, a kezdő játékos mondhat 5-öt.
  390.         // Így az 1, 5, 9, 13, 17, 21 sor tartható.
  391.         // Hogy a rendszer megtalálja ezt a sorozatot, ezért a sorozat elemeire
  392.         // 100-at ad a heurisztika, minden más értékre csak 1-et.
  393.         public override int GetHeurisztika() { return szám % (K + 1) == 1 ? 100 : 1; }
  394.         private bool preLép(int i) { return i >= 0 && i < K; }
  395.         private bool lép(int i)
  396.         {
  397.             if (!preLép(i)) return false;
  398.             i++; // ha i=0, akkor 1-et kell hozzáadni, stb..
  399.             szám += i;
  400.             if (ÁllapotE()) return true;
  401.             szám -= i;
  402.             return false;
  403.         }
  404.         // Itt szerencsére nem kellett belső switch-t írni.
  405.         // Ez inkább kivételes eset.
  406.         public override bool SzuperOperátor(int i) { return lép(i); }
  407.         public override int OperátorokSzáma() { return K; }
  408.         public override string ToString() { return szám.ToString(); }
  409.     }
  410.  
  411.     class NimÁllapot : AbsztraktÁllapot
  412.     {
  413.         int a, b, c;
  414.  
  415.         public NimÁllapot(int a, int b, int c = 0) // keződállapot
  416.         {
  417.             this.a = a;
  418.             this.b = b;
  419.             this.c = c;
  420.         }
  421.         public override bool ÁllapotE()
  422.         {
  423.             return a >= 0 && b >= 0 && c >= 0;
  424.         }
  425.  
  426.         public override bool CélÁllapotE()
  427.         {
  428.             return a == 0 && b == 0 && c == 0;
  429.         }
  430.  
  431.         public override int OperátorokSzáma()
  432.         {
  433.             return a + b + c;
  434.         }
  435.  
  436.         public override bool SzuperOperátor(int i)
  437.         {
  438.             return Elvesz(i);
  439.         }
  440.  
  441.         private bool Elvesz(int i)
  442.         {
  443.             if (!preElvesz(i)) return false;
  444.             if (i < a)
  445.             {
  446.                 a -= (i + 1);
  447.             }
  448.             else if (i < a + b)
  449.             {
  450.                 b -= (i + 1 - a);
  451.             }
  452.             else
  453.             {
  454.                 c -= (i + 1 - a - b);
  455.             }
  456.  
  457.             return ÁllapotE();
  458.         }
  459.  
  460.         private bool preElvesz(int i)
  461.         {
  462.             return i >= 0 && i < a + b + c;
  463.         }
  464.  
  465.         public override int GetHeurisztika()
  466.         {
  467.             return a == b ? 100 : 1;
  468.         }
  469.         public override string ToString()
  470.         {
  471.             return string.Format("a: {0}, b: {1}, c: {2}", a, b, c);
  472.         }
  473.     }
  474.  
  475.  
  476.     // Egy játékot vezényel le.
  477.     // Ez egybevonható a főprogramból, hiszen abból emeltük ki.
  478.     class Játék
  479.     {
  480.         AbsztraktÁllapot startÁllapot;
  481.         Stratégia start;
  482.         public Játék(AbsztraktÁllapot startÁllapot, Stratégia strat)
  483.         {
  484.             this.startÁllapot = startÁllapot;
  485.             this.start = strat;
  486.         }
  487.         public void Start()
  488.         {
  489.             JátékCsúcs akt = new JátékCsúcs(startÁllapot);
  490.             Console.WriteLine("Játszhat a gép ellen!");
  491.             while (!akt.TerminálisCsúcsE())
  492.             {
  493.                 // Saját lépésem.
  494.                 bool b = false;
  495.                 while (!b)
  496.                 {
  497.                     Console.WriteLine("Jelenlegi állás: {0}", akt);
  498.                     Console.WriteLine("Melyik operátort választja? (0,..,{0}): ", akt.OperátorokSzáma() - 1);
  499.                     int k = 0;
  500.                     try
  501.                     {
  502.                         k = int.Parse(Console.ReadLine());
  503.                     }
  504.                     catch (Exception e)
  505.                     {
  506.                         Console.WriteLine("Hiba: {0}", e.ToString());
  507.                         Console.WriteLine("Érvénytelen lépés. Újra!");
  508.                         continue;
  509.                     }
  510.                     b = akt.SzuperOperátor(k);
  511.                     if (!b) Console.WriteLine("Ez az operátor nem alkalmazható. Újra!");
  512.                 }
  513.                 // Ellenfél lépése.
  514.                 Console.WriteLine("Jelenlegi állás: {0}", akt);
  515.                 akt = start.MitLépjek(akt);
  516.                 int i = akt.GetMelyikOperátorralJutottamIde();
  517.                 Console.WriteLine("A gép ezt az operátort választotta: {0}", i);
  518.                 // Nyertes állás?
  519.                 if (akt.TerminálisCsúcsE()) break;
  520.                
  521.             }
  522.             Console.WriteLine("Jelenlegi állás: {0}", akt);
  523.             Console.WriteLine("Aki utoljára lépett, az nyert, vagy döntetlen.");
  524.         }
  525.     } // Főprogram.
  526.     class Program
  527.     {
  528.         static void Main(string[] args)
  529.         {
  530.             Stratégia start = new NegaMaxMódszer(5); // 5 mélységbe tekint előre
  531.             //AbsztraktÁllapot startFejben21Állapot = new Fejben21Állapot();
  532.             //Játék fejben21 = new Játék(startFejben21Állapot, start);
  533.             //Console.WriteLine("A Fejben 21 játék kezdetét veszi!");
  534.             //fejben21.start();
  535.             //Console.ReadLine();
  536.             //AbsztraktÁllapot startTTTÁllapot = new TicTacToeÁllapot();
  537.             //Játék tictactoe = new Játék(startTTTÁllapot, start);
  538.             //Console.WriteLine("A Tic Tac Toe játék kezdődik!");
  539.             //tictactoe.Start();
  540.             AbsztraktÁllapot nimstart = new NimÁllapot(7, 7);
  541.             Játék nimjáték = new Játék(nimstart, start);
  542.             Console.WriteLine("Nim játék!");
  543.             nimjáték.Start();
  544.             Console.ReadLine();
  545.         }
  546.     }
  547. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement