Принятие решений нейронной сети в игре крестики нолики - C#
Формулировка задачи:
Собственно есть нейронная сеть(слизанная с хабра), там нейронная сеть была предназначена для распознавания изображений, то есть использовались двухмерные массивы я заменил его на одно мерный так как поле в крестики нолики можно записать в одну строку. Суть проблемы принятие решений нейронной сети по факту она их принимает ^_^, но как сделать так что бы она стремилась к победе.
Листинг программы
- using System;
- namespace GA
- {
- class Program
- {
- 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;
- }
- 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 массив из нуллей и единиц, ответы нейронов
- */
- 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 массив из вероятностей, ответы нейронов
- */
- 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 - если нет
- */
- 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 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
- #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();
- }
- }
- }
Решение задачи: «Принятие решений нейронной сети в игре крестики нолики»
textual
Листинг программы
- using System;
- using System.Windows.Forms;
- namespace NeuralNetwork
- {
- public partial class Form1 : Form
- {
- #region NeuralNetwork
- 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[9];
- 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;
- }
- }
- #endregion
- private NeuralNetwork nw = new NeuralNetwork();
- private int[] _table =
- {
- 0, 0, 0,
- 0, 0, 0,
- 0, 0, 0
- };
- public Form1()
- {
- InitializeComponent();
- #region Начальное обучение. Основанное на рандоме.
- for (int i = 0; i < 4608; i++)
- {
- answer1:
- int a = _random.Next(0, 9);
- if (_table[a] != 1 && _table[a] != 2)
- _table[a] = 1;
- else
- goto answer1;
- CheckWin();
- answer:
- int answer = nw.getAnswer(_table);
- if (_table[answer] != 1 && _table[answer] != 2)
- {
- _table[answer] = 2;
- if (answer == 0)
- button1.Text = @"O";
- if (answer == 1)
- button2.Text = @"O";
- if (answer == 2)
- button3.Text = @"O";
- if (answer == 3)
- button4.Text = @"O";
- if (answer == 4)
- button5.Text = @"O";
- if (answer == 5)
- button6.Text = @"O";
- if (answer == 6)
- button7.Text = @"O";
- if (answer == 7)
- button8.Text = @"O";
- if (answer == 8)
- button9.Text = @"O";
- CheckWin();
- }
- else
- {
- int index = _random.Next(0, 9);
- nw.study(_table, index);
- goto answer;
- }
- }
- TableEmpty();
- textBox1.Text = String.Empty;
- #endregion
- }
- public void CheckWin()
- {
- if (_table[0] == 1 && _table[1] == 1 && _table[2] == 1 ||
- _table[3] == 1 && _table[4] == 1 && _table[5] == 1 ||
- _table[6] == 1 && _table[7] == 1 && _table[8] == 1 ||
- _table[0] == 1 && _table[4] == 1 && _table[8] == 1 ||
- _table[2] == 1 && _table[4] == 1 && _table[6] == 1 ||
- _table[0] == 1 && _table[3] == 1 && _table[6] == 1 ||
- _table[1] == 1 && _table[4] == 1 && _table[7] == 1 ||
- _table[2] == 1 && _table[5] == 1 && _table[8] == 1)
- {
- textBox1.Text += @"Вы победили
- ";
- nw.study(_table, _random.Next(0, 9));
- TableEmpty();
- }
- else
- {
- if (_table[0] == 2 && _table[1] == 2 && _table[2] == 2 ||
- _table[3] == 2 && _table[4] == 2 && _table[5] == 2 ||
- _table[6] == 2 && _table[7] == 2 && _table[8] == 2 ||
- _table[0] == 2 && _table[4] == 2 && _table[8] == 2 ||
- _table[2] == 2 && _table[4] == 2 && _table[6] == 2 ||
- _table[0] == 2 && _table[3] == 2 && _table[6] == 2 ||
- _table[1] == 2 && _table[4] == 2 && _table[7] == 2 ||
- _table[2] == 2 && _table[5] == 2 && _table[8] == 2)
- {
- textBox1.Text += @"Победила нейронная сеть
- ";
- nw.study(_table, _random.Next(0, 9));
- TableEmpty();
- }
- else
- {
- int counter = 0;
- for (int i = 0; i < _table.Length; i++)
- {
- if (_table[i] != 1 && _table[i] != 2)
- counter++;
- }
- if (counter == 0)
- {
- textBox1.Text += @"Ничья!
- ";
- nw.study(_table, _random.Next(0, 9));
- TableEmpty();
- }
- }
- }
- }
- #region Кнопки
- private void button1_Click(object sender, EventArgs e)
- {
- if (_table[0] != 1 && _table[0] != 2)
- {
- _table[0] = 1;
- button1.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button2_Click(object sender, EventArgs e)
- {
- if (_table[1] != 1 && _table[1] != 2)
- {
- _table[1] = 1;
- button2.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button3_Click(object sender, EventArgs e)
- {
- if (_table[2] != 1 && _table[2] != 2)
- {
- _table[2] = 1;
- button3.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button4_Click(object sender, EventArgs e)
- {
- if (_table[3] != 1 && _table[3] != 2)
- {
- _table[3] = 1;
- button4.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button5_Click(object sender, EventArgs e)
- {
- if (_table[4] != 1 && _table[4] != 2)
- {
- _table[4] = 1;
- button5.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button6_Click(object sender, EventArgs e)
- {
- if (_table[5] != 1 && _table[5] != 2)
- {
- _table[5] = 1;
- button6.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button7_Click(object sender, EventArgs e)
- {
- if (_table[6] != 1 && _table[6] != 2)
- {
- _table[6] = 1;
- button7.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button8_Click(object sender, EventArgs e)
- {
- if (_table[7] != 1 && _table[7] != 2)
- {
- _table[7] = 1;
- button8.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- private void button9_Click(object sender, EventArgs e)
- {
- if (_table[8] != 1 && _table[8] != 2)
- {
- _table[8] = 1;
- button9.Text = @"X";
- CheckWin();
- Answer();
- }
- }
- #endregion
- public void TableEmpty()
- {
- _table = new[]
- {
- 0, 0, 0,
- 0, 0, 0,
- 0, 0, 0
- };
- button1.Text = "";
- button2.Text = "";
- button3.Text = "";
- button4.Text = "";
- button5.Text = "";
- button6.Text = "";
- button7.Text = "";
- button8.Text = "";
- button9.Text = "";
- }
- public void Answer()
- {
- answer:
- int answer = nw.getAnswer(_table);
- if (_table[answer] != 1 && _table[answer] != 2)
- {
- _table[answer] = 2;
- if (answer == 0)
- button1.Text = @"O";
- if (answer == 1)
- button2.Text = @"O";
- if (answer == 2)
- button3.Text = @"O";
- if (answer == 3)
- button4.Text = @"O";
- if (answer == 4)
- button5.Text = @"O";
- if (answer == 5)
- button6.Text = @"O";
- if (answer == 6)
- button7.Text = @"O";
- if (answer == 7)
- button8.Text = @"O";
- if (answer == 8)
- button9.Text = @"O";
- CheckWin();
- }
- else
- {
- int index = _random.Next(0, 9);
- nw.study(_table, index);
- goto answer;
- }
- }
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д