Собственно есть нейронная сеть(слизанная с хабра), там нейронная сеть была предназначена для распознавания изображений, то есть использовались двухмерные массивы я заменил его на одно мерный так как поле в крестики нолики можно записать в одну строку. Суть проблемы, принятие решений нейронной сети, по факту она их принимает ^_^, но как сделать так что бы она стремилась к победе?
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();
}
}
}