1 svar
44 visningar
Anto 196
Postad: 26 dec 2023 19:16

tre i rad, minimax-algoritm

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tre_i_Rad_V8._0
{
    internal class Program
    {
        static Random slump = new Random();
        static string notation = "";
        static void visuelltBräde(char[,] bräde)
        {
            for (int i = 2; i >= 0; i--)
            {
                Console.WriteLine("   *---*---*---*");
                Console.WriteLine(i + 1 + ". | " + bräde[i, 0] + " | " + bräde[i, 1] + " | " + bräde[i, 2] + " | ");
            }
            Console.WriteLine("   *---*---*---*");
            Console.WriteLine("     A   B   C");
        }
        static bool vinst(char[,] bräde, char markör)
        {
            bool vinst = false;
            for (int i = 0; i < 3; i++)
            {
                if (bräde[i, 0] == markör && bräde[i, 1] == markör && bräde[i, 2] == markör)
                    vinst = true;
                if (bräde[0, i] == markör && bräde[1, i] == markör && bräde[2, i] == markör)
                    vinst = true;
            }
            if (bräde[0, 0] == markör && bräde[1, 1] == markör && bräde[2, 2] == markör)
                vinst = true;
            if (bräde[2, 0] == markör && bräde[1, 1] == markör && bräde[0, 2] == markör)
                vinst = true;
            return vinst;
        }
        static bool lika(char[,] bräde)
        {
            bool lika = false;
            bool finnsTomRuta = false;
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                    if (bräde[i, j] == ' ')
                        finnsTomRuta = true;
            if (finnsTomRuta == false)
                lika = true;
            return lika;
        }
        static void vinstUtskrift(char[,] bräde, char markör)
        {
            if (vinst(bräde, markör) == true)
            {
                visuelltBräde(bräde);
                Console.WriteLine(markör + " vinner");
                Console.WriteLine(notation + "#");
                Console.ReadLine();
                Environment.Exit(0);
            }
        }
        static void likaUtskrift(char[,] bräde)
        {
            if (lika(bräde) == true)
            {
                visuelltBräde(bräde);
                Console.WriteLine("Lika");
                Console.WriteLine(notation + "=");
                Console.ReadLine();
                Environment.Exit(0);
            }
        }
        static int betyg(char[,] bräde)
        {
            int betyg = 10;
            if (vinst(bräde, 'X') == true)
                betyg = 1;
            else if (vinst(bräde, 'O') == true)
                betyg = -1;
            else if (lika(bräde) == true)
                betyg = 0;
            return betyg;
        }
        static int minimax(char[,] bräde, int djup, bool maximeraresTur)
        {
            int poäng;
            if (betyg(bräde) != 10)
            {
                poäng = betyg(bräde);
                return poäng;
            }
                
            if (maximeraresTur == true)
            {
                int bästaPoäng = -1000;
                for (int rad = 0; rad < 3; rad++)
                {
                    for (int kolumn = 0; kolumn < 3; kolumn++)
                    {
                        if (bräde[rad, kolumn] == ' ')
                        {
                            bräde[rad, kolumn] = 'X';
                            poäng = minimax(bräde, djup + 1, false);
                            bräde[rad, kolumn] = ' ';
                            bästaPoäng = Math.Max(poäng, bästaPoäng);
                        }
                    }
                }
                return bästaPoäng;
            }
            else
            {
                int bästaPoäng = 1000;
                for (int rad = 0; rad < 3; rad++)
                {
                    for (int kolumn = 0; kolumn < 3; kolumn++)
                    {
                        if (bräde[rad, kolumn] == ' ')
                        {
                            bräde[rad, kolumn] = 'O';
                            poäng = minimax(bräde, djup + 1, true);
                            bräde[rad, kolumn] = ' ';
                            bästaPoäng = Math.Min(poäng, bästaPoäng);
                        }
                    }
                }
                return bästaPoäng;
            }
        }
        static char[,] datorDrag(char[,] bräde)
        {
            int nuvarandePoäng;
            int bästaPoäng = -1000;
            int bästaRad = 0;
            int bästaKolumn = 0;
            for(int rad = 0; rad < 3; rad++)
            {
                for (int kolumn = 0; kolumn < 3; kolumn++)
                {
                    bräde[rad, kolumn] = 'X';
                    nuvarandePoäng = minimax(bräde, 0, false);
                    bräde[rad, kolumn] = ' ';
                    if (nuvarandePoäng > bästaPoäng)
                    {
                        bästaPoäng = nuvarandePoäng;
                        bästaRad = rad;
                        bästaKolumn = kolumn;
                    }
                }
            }
            bräde[bästaRad, bästaKolumn] = 'X';
            Console.WriteLine("Datorn spelar: " + Convert.ToString(Convert.ToChar(bästaKolumn + 65)).ToLower() + (bästaRad + 1).ToString());
            notation = notation + Convert.ToString(Convert.ToChar(bästaKolumn + 65)).ToLower() + (bästaRad + 1).ToString() + " ";
            vinstUtskrift(bräde, 'X');
            likaUtskrift(bräde);
            return bräde;
        }
        static char[,] spelarDrag(char[,] bräde)
        {
            Console.Clear(); 
            visuelltBräde(bräde);
            string drag;
            for (; ; )
            {
                Console.WriteLine("Spelare O: Ditt drag");
                drag = Console.ReadLine().ToUpper();
                if (tillåtetDrag(bräde, drag) == true)
                {
                    notation = notation + drag + " ";
                    break;
                }
                else
                    Console.WriteLine("Fel input");
            }
            bräde[Convert.ToInt32(Convert.ToString(drag[1])) - 1, Convert.ToInt32(drag[0]) - 65] = 'O';
            vinstUtskrift(bräde, 'O');
            likaUtskrift(bräde);
            return bräde;
        }
        static bool tillåtetDrag(char[,] bräde, string drag)
        {
            bool tillåtetDrag = false;
            if (drag.Length == 2)
                if (drag[0] == 'A' || drag[0] == 'B' || drag[0] == 'C')
                    if (drag[1] == '1' || drag[1] == '2' || drag[1] == '3')
                        if (bräde[Convert.ToInt32(Convert.ToString(drag[1])) - 1, Convert.ToInt32(drag[0]) - 65] == ' ')
                            tillåtetDrag = true;
            return tillåtetDrag;

        }
        static void Main(string[] args) //Datorns markör: X. Spelarens markör O.
        {
            char[,] bräde = { { ' ', ' ', ' ' }, { ' ', ' ', ' ' }, { ' ', ' ', ' ' } }; // [rad, kolumn]
            for (; ; )
            {
                bräde = spelarDrag(bräde);
                bräde = datorDrag(bräde);
            }
        }
    }
}

Det är något konstigt med denna kod. Det är tre i rad i C# där datorn väljer drag mha en minimaxalgoritm. Men utskriften blir fel. Det är enbart det senaste drag som skrivs ut och spelarens drag skrivs aldrig ut. Vi får nog utgå från att minmaxalgoritmen inte är perfekt, men det borde inte orsaka detta problemet. Likaså bör spelDrag och visuelltBräde inte ha felet då de fungerade perfekt i en tidigare version där datorDrag valdes med en annan algoritm, samtidigt som de är oförändrade. Ser någon felet?

Skriv om ni vill se den version som fungerade!

anders_k Online 234
Postad: 28 dec 2023 10:18

Du kanske skulle ta och skriva ut brädet efter spelare/dator har gjort sina drag. Om du tittar t.ex. i din "spelarDrag" skriver du ut först, sen ändrar du i brädet. Jag föreslår du lägger det in din huvud loop istället, men du gör som du vill.

for (;;)
{
  bräde = spelarDrag(bräde);
  visuelltBräde(bräde);
  bräde = datorDrag(bräde);
  visuelltBräde(bräde);
}

Sen behöver du inte returnera hela matrisen efter spelarDrag/datorDrag, du kan använda samma bräde och istället returnera true om draget gjorde att spelaren/datorn vann.

bool done{false};
do {
  done = spelarDrag(bräde);
  visuelltBräde(bräde);

  if (!done) {
    datorDrag(bräde);
    visuelltBräde(bräde);
  }
} while (!done);
Svara Avbryt
Close