@mrcanore

[C#] Как переписать нейронную сеть для игры в «Крестики-нолики»?

Собственно есть нейронная сеть(слизанная с хабра), там нейронная сеть была предназначена для распознавания изображений, то есть использовались двухмерные массивы я заменил его на одно мерный так как поле в крестики нолики можно записать в одну строку. Суть проблемы, принятие решений нейронной сети, по факту она их принимает ^_^, но как сделать так что бы она стремилась к победе?
using System;

namespace GA
{
    internal class Program
    {
        private static Random _random = new Random();

        public static int length = 9; // Колличество входных параметров

        public class Neuron
        {
            public int[] weight; // Веса нейронов
            public int minimum = 50; // Порог

            /**
             * Конструктор нейрона, создает веси и устанавливает случайные значения
             */

            public Neuron()
            {
                weight = new int[length];
                randomizeWeights();
            }

            /**
             * ответы нейронов, жесткая пороговая
             * @param input - входной вектор
             * @return ответ 0 или 1
             */

            public int transferHard(int[] input)
            {
                int Power = 0;
                for (int r = 0; r < length; r++)
                {

                    Power += weight[r]*input[r];
                }
                //Debug.Log("Power: " + Power);
                return Power >= minimum ? 1 : 0;
            }

            /**
             * ответы нейронов с вероятностями
             * @param input - входной вектор
             * @return n вероятность
             */

            public int transfer(int[] input)
            {
                int Power = 0;
                for (int r = 0; r < length; r++)
                    Power += weight[r]*input[r];

                //Debug.Log("Power: " + Power);
                return Power;
            }

            private void randomizeWeights()
            {
                for (int r = 0; r < length; r++)
                    weight[r] = _random.Next(0, 10);
            }

            /**
             * изменяет веса нейронов
             * @param input - входной вектор
             * @param d - разница между выходом нейрона и нужным выходом
             */

            public void changeWeights(int[] input, int d)
            {
                for (int r = 0; r < length; r++)
                    weight[r] += d*input[r];
            }
        }
        public class NeuralNetwork
        {
            public Neuron[] neurons;

            /**
             * Конструктор сети создает нейроны
             */

            public NeuralNetwork()
            {
                neurons = new Neuron[10];

                for (int i = 0; i < neurons.Length; i++)
                    neurons[i] = new Neuron();
            }

            /**
             * Функция распознавания символа, используется для обучения
             * @param input - входной вектор
             * @return массив из нуллей и единиц, ответы нейронов
             */

            private int[] handleHard(int[] input)
            {
                int[] output = new int[neurons.Length];
                for (int i = 0; i < output.Length; i++)
                    output[i] = neurons[i].transferHard(input);

                return output;
            }

            /**
             * Функция распознавания, используется для конечново ответа
             * @param input -  входной вектор
             * @return массив из вероятностей, ответы нейронов
             */

            private int[] handle(int[] input)
            {
                int[] output = new int[neurons.Length];
                for (int i = 0; i < output.Length; i++)
                    output[i] = neurons[i].transfer(input);

                return output;
            }

            /**
             * Ответ сети
             * @param input - входной вектор
             * @return индекс нейронов предназначенный для конкретного символа
             */

            public int getAnswer(int[] input)
            {
                int[] output = handle(input);
                int maxIndex = 0;
                for (int i = 1; i < output.Length; i++)
                    if (output[i] > output[maxIndex])
                        maxIndex = i;

                return maxIndex;
            }

            /**
             * Функция обучения
             * @param input - входной вектор
             * @param correctAnswer - правильный ответ
             */

            public void study(int[] input, int correctAnswer)
            {
                int[] correctOutput = new int[neurons.Length];
                correctOutput[correctAnswer] = 1;

                int[] output = handleHard(input);
                while (!compareArrays(correctOutput, output))
                {
                    for (int i = 0; i < neurons.Length; i++)
                    {
                        int dif = correctOutput[i] - output[i];
                        neurons[i].changeWeights(input, dif);
                    }
                    output = handleHard(input);
                }
            }

            /**
             * Сравнение двух вектор
             * @param true - если массивы одинаковые, false - если нет
             */

            private bool compareArrays(int[] a, int[] b)
            {
                if (a.Length != b.Length)
                    return false;

                for (int i = 0; i < a.Length; i++)
                    if (a[i] != b[i])
                        return false;

                return true;
            }
        }

        private static void Main(string[] args)
        {
            NeuralNetwork nw = new NeuralNetwork();

            int[] table =
            {
                0, 0, 0,
                0, 0, 0,
                0, 0, 0
            };

            var win = false;

            while (!win)
            {
                #region PlayerInput

                int x;

                do
                {
                    input:
                    Console.Write("Введите номер клетки где поставить крестик: ");

                    try
                    {
                        x = Convert.ToInt16(Console.ReadLine());
                    }
                    catch (Exception ex)
                    {
                        goto input;
                    }

                } while (table[x - 1] == 1 || table[x - 1] == 2);

                table[x - 1] = 1;

                #endregion

                if (table[0] == 1 && table[1] == 1 && table[2] == 1 ||
                    table[0] == 2 && table[1] == 2 && table[2] == 2 ||
                    table[3] == 1 && table[4] == 1 && table[5] == 1 ||
                    table[3] == 2 && table[4] == 2 && table[5] == 2 ||
                    table[6] == 1 && table[7] == 1 && table[8] == 1 ||
                    table[6] == 2 && table[7] == 2 && table[8] == 2 ||
                    table[0] == 1 && table[4] == 1 && table[8] == 1 ||
                    table[0] == 2 && table[4] == 2 && table[8] == 2 ||
                    table[2] == 1 && table[4] == 1 && table[6] == 1 ||
                    table[2] == 2 && table[4] == 2 && table[6] == 2 ||
                    table[0] == 1 && table[3] == 1 && table[6] == 1 ||
                    table[0] == 2 && table[3] == 2 && table[6] == 2 ||
                    table[1] == 1 && table[4] == 1 && table[7] == 1 ||
                    table[1] == 2 && table[4] == 2 && table[7] == 2 ||
                    table[2] == 1 && table[5] == 1 && table[8] == 1 ||
                    table[2] == 2 && table[5] == 2 && table[8] == 2)
                {
                    win = true;
                }
                else
                {
                    #region NeuralNetwork

                    int o;
                    do
                    {
                        nw.study(table, _random.Next(0, 9));
                        o = nw.getAnswer(table);
                    } while (table[o] == 1 || table[o] == 2);

                    table[o] = 2;

                    #endregion

                    if (table[0] == 1 && table[1] == 1 && table[2] == 1 ||
                        table[0] == 2 && table[1] == 2 && table[2] == 2 ||
                        table[3] == 1 && table[4] == 1 && table[5] == 1 ||
                        table[3] == 2 && table[4] == 2 && table[5] == 2 ||
                        table[6] == 1 && table[7] == 1 && table[8] == 1 ||
                        table[6] == 2 && table[7] == 2 && table[8] == 2 ||
                        table[0] == 1 && table[4] == 1 && table[8] == 1 ||
                        table[0] == 2 && table[4] == 2 && table[8] == 2 ||
                        table[2] == 1 && table[4] == 1 && table[6] == 1 ||
                        table[2] == 2 && table[4] == 2 && table[6] == 2 ||
                        table[0] == 1 && table[3] == 1 && table[6] == 1 ||
                        table[0] == 2 && table[3] == 2 && table[6] == 2 ||
                        table[1] == 1 && table[4] == 1 && table[7] == 1 ||
                        table[1] == 2 && table[4] == 2 && table[7] == 2 ||
                        table[2] == 1 && table[5] == 1 && table[8] == 1 ||
                        table[2] == 2 && table[5] == 2 && table[8] == 2)
                    {
                        win = true;
                    }
                }


                #region WriteTable

                for (int i = 0; i < table.Length; i++)
                {
                    Console.Write(table[i] == 1 ? "X" : table[i] == 2 ? "O" : "-");

                    if ((i + 1) % 3 == 0 && i != 0)
                    {
                        Console.WriteLine();
                    }
                }
                Console.WriteLine();

                #endregion
            }

            Console.WriteLine("Кто-то кого-то нагнул.");
            Console.ReadKey();
        }
    }
}
  • Вопрос задан
  • 8265 просмотров
Пригласить эксперта
Ответы на вопрос 1
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы