Главная » Язык программирования C#

Крестики-нолики: код программы на C#

крестики нолики код на c#

Код игры «крестики-нолики» на языке программирования C#

Доброго времени суток. На данной странице я приведу пример создания всеми любимой логической игры под названием «крестики-нолики». Так как программирую я в основном на C#, то и представленная программа будет так же на данном языке программирования. Но даже если Вы не знакомы с C#, а программируете на C++, Java, Delphi или на любом другом языке, данный пост в любом случае поможет Вам, так как тут я приведу алгоритм работы такой программы.

Рассматривать программу, предназначенную для игры вдвоем, мы не будем. Сейчас мы рассмотрим программу, в которой противником пользователя будет компьютер, ведь для программа для игры двоих будет состоять только из необходимости прорисовки ходов, что, думаю, довольно просто. Поэтому мы рассмотрим игру компьютера.

Всю программу можно поделить на две большие части:

  1. Компьютер ходит первым(крестики)
  2. Компьютер ходит вторым(нолики)

Далее я опишу стратегию игры компьютера, которого мы собираемся сделать непобедимым.

Стратегия игры «крестики-нолики»

Основополагающие правила

Независимо от того, кто ходит первым и какая сейчас позиция, компьютер перед каждый ходом должен проверить две вещи:

  1. Можно ли выиграть? Если да, то компьютер выигрывает!
  2. Угрожает ли нам опасность проиграть следующим ходом? Если да, то закрываем такую возможность!

Компьютер ходит первым

Компьютер свой первый ход делает в центр. Тут другого варианта нет. Дальше ходит пользователь, у которого есть только два варианта: либо сходить в угол, либо сходить на сторону. Если пользователь ходит в угол, то компьютер отвечает ходом в противоположный угол. Если же пользователь ходит на сторону, то компьютер должен сходить в один из углов, которые расположены дальше всего от хода пользователя. Таких углов, если Вы понимаете о чем я, всего два. Разницы в какой из них сходить нет. Если эти противоположные углы заняты, компьютер ходит в любое свободное место(это условие актуально и если пользователь сходил в угол, и если он сходил на сторону). Данное правило ходить как можно дальше от предыдущего хода соперника актуально до конца игры, в которой компьютер сходил первым.

Компьютер ходит вторым

Когда компьютер ходит вторым, а пользователь, соответственно, первым, может возникнуть несколько ситуаций:

  1. Первый ход в центр. Тогда ходим до конца игры в любой из углов, а если это невозможно, то в любую свободную клетку.
  2. Первый ход в угол. Отвечаем ходом в центр. Следующие ходы — в любой из свободных углов, иначе — в свободные клетки.
  3. Первый ход в сторону. Ситуация аналогичная предыдущей: по максимуму закрываем углы, после чего ходим туда, где осталось место.

Вот такая стратегия игры в «крестики-нолики». Она не слишком сложная, и теперь мы попытаемся ее реализовать.

Реализация программы «крестики-нолики»

Предлагать Вам полный код всей программы я не буду, все же лучше чему то научится самим. Но основной костяк программы я вам предложу. Собирать же воедино останется Вам. Итак, начнем мы с основополагающих правил. Надеюсь, вы не забыли, что эти правила должны проверяться перед каждый ходом.

Проверка на возможность победы

Перед тем как писать код, необходимо уяснить смысл ее работы. Выигрышных комбинаций всего 8. Можете посмотреть скриншоты: я специально выделил и указал номер этих комбинаций(они понадобятся нам). Эти номера комбинаций будет хранить переменная cherta, которая сразу после выигрыша отдаст команду нарисовать выигрышную черту.

крестики нолики
крестики нолики
крестики нолики
Мы должны проверить каждую из этих комбинаций на предмет того, стоят ли там две наши крестики(или нолики), а так же свободно ли третья клетка. Но перед тем как мы перейдем к этому, я немного познакомлю вас с другой основой программы.

Для хранения ходов как компьютера, так и пользователя прекрасно подходит обычная матрица 3×3, в которой можно указывать специальный номер ходившей стороны. Для своей игры я задал такие значения:

  • Изначально матрица обнуляется и это значит, что все 9 клеток пусты. Перед каждый ходом нужно проверять, пустая ли клетка, и можно ли на нее сходить. Полезно, пользуйтесь.
  • Для обозначения компьютера я использовал цифру 1.
  • Для обозначения пользователя я использовал цифру 2.

Далее нам необходимо будет создать специальный метод, который будет отрисовывать игровое поле, используя данные этой матрицы(метод paint, который будет мелькать в коде). А вот собственно и код данного метода:

if (((a[0, 0] + a[0, 1] + a[0, 2]) == 2) && (a[0, 0] == 1 || a[0, 1] == 1 || a[0, 2] == 1))
{
for (int j = 0; j < 3; j++)
{
if (a[0, j] == 0)
{
a[0, j] = 1;
}
}
win = 1;
paint();
cherta = 4;
}
else
{
if (((a[1, 0] + a[1, 1] + a[1, 2]) == 2) && (a[1, 0] == 1 || a[1, 1] == 1 || a[1, 2] == 1))
{
for (int j = 0; j < 3; j++)
{
if (a[1, j] == 0)
{
a[1, j] = 1;
}
}
win = 1;
paint();
cherta = 5;
}
else
{
if (((a[2, 0] + a[2, 1] + a[2, 2]) == 2) && (a[2, 0] == 1 || a[2, 1] == 1 || a[2, 2] == 1))
{
for (int j = 0; j < 3; j++)
{
if (a[2, j] == 0)
{
a[2, j] = 1;
}
}
win = 1;
paint();
cherta = 6;
}
else
{
if (((a[0, 0] + a[1, 0] + a[2, 0]) == 2) && (a[0, 0] == 1 || a[1, 0] == 1 || a[2, 0] == 1))
{
for (int i = 0; i < 3; i++)
{
if (a[i, 0] == 0)
{
a[i, 0] = 1;
}
}
win = 1;
paint();
cherta = 1;
}
else
{
if (((a[0, 1] + a[1, 1] + a[2, 1]) == 2) && (a[0, 1] == 1 || a[1, 1] == 1 || a[2, 1] == 1))
{
for (int i = 0; i < 3; i++)
{
if (a[i, 1] == 0)
{
a[i, 1] = 1;
}
}
win = 1;
paint();
cherta = 2;
}
else
{
if (((a[0, 2] + a[1, 2] + a[2, 2]) == 2) && (a[0, 2] == 1 || a[1, 2] == 1 || a[2, 2] == 1))
{
for (int i = 0; i < 3; i++)
{
if (a[i, 2] == 0)
{
a[i, 2] = 1;
}
}
win = 1;
paint();
cherta = 3;
}
else
{
if (((a[0, 0] + a[1, 1] + a[2, 2]) == 2) && (a[0, 0] == 1 || a[1, 1] == 1 || a[2, 2] == 1))
{
if (a[0, 0] == 0)
a[0, 0] = 1;
if (a[1, 1] == 0)
a[1, 1] = 1;
if (a[2, 2] == 0)
a[2, 2] = 1;
win = 1;
paint();
cherta = 7;
}
else
{
if (((a[2, 0] + a[1, 1] + a[0, 2]) == 2) && (a[2, 0] == 1 || a[1, 1] == 1 || a[0, 2] == 1))
{
if (a[2, 0] == 0)
a[2, 0] = 1;
if (a[1, 1] == 0)
a[1, 1] = 1;
if (a[0, 2] == 0)
a[0, 2] = 1;
win = 1;
paint();
cherta = 8;
}
}
}
}
}
}
}
}

Тут так же появляется переменная win, которая хранит значение победившей стороны. Я использовал только два значения: 0-ничья, 1 — победа компьютера. В моей программе нет даже поздравления пользователя с возможной победой, так как это невозможно.

Проверка на возможность проигрыша следующим ходом

if ((a[0, 0] + a[0, 1] + a[0, 2]) == 4 && a[0, 0]!=1 && a[0, 1]!=1 && a[0, 2]!=1)   //1-4-7  - защита
{
for (int j = 0; j < 3; j++)
{
if (a[0, j] == 0)
{
a[0, j] = 1;
hdpc = false;
paint();
}
}
}
 else
{
if ((a[1, 0] + a[1, 1] + a[1, 2]) == 4 && a[1, 0] != 1 && a[1, 1] != 1 && a[1, 2] != 1)   //2-5-8  - защита
{
for (int j = 0; j < 3; j++)
{
if (a[1, j] == 0)
{
a[1, j] = 1;
hdpc = false;
paint();
}
}
}
else
{
if ((a[2, 0] + a[2, 1] + a[2, 2]) == 4 && a[2, 0] != 1 && a[2, 1] != 1 && a[2, 2] != 1)   //3-6-9  - защита
{
for (int j = 0; j < 3; j++)
{
if (a[2, j] == 0)
{
a[2, j] = 1;
hdpc = false;
paint();
}
}
}
else
{
if ((a[0, 0] + a[1, 0] + a[2, 0]) == 4 && a[0, 0] != 1 && a[1, 0] != 1 && a[2, 0] != 1)   //1-2-3  - защита
{
for (int i = 0; i < 3; i++)
{
if (a[i, 0] == 0)
{
a[i, 0] = 1;
hdpc = false;
paint();
}
}
}
else
{
if ((a[0, 1] + a[1, 1] + a[2, 1]) == 4 && a[0, 1] != 1 && a[1, 1] != 1 && a[2, 1] != 1)   //4-5-6  - защита
{
for (int i = 0; i < 3; i++)
{
if (a[i, 1] == 0)
{
a[i, 1] = 1;
hdpc = false;
paint();
}
}
}
else
{
if ((a[0, 2] + a[1, 2] + a[2, 2]) == 4 && a[0, 2] != 1 && a[1, 2] != 1 && a[2, 2] != 1)   //7-8-9  - защита
{
for (int i = 0; i < 3; i++)
{
if (a[i, 2] == 0)
{
a[i, 2] = 1;
hdpc = false;
paint();
}
}
}
else
{
if ((a[0, 0] + a[1, 1] + a[2, 2]) == 4 && a[0, 0] != 1 && a[1, 1] != 1 && a[2, 2] != 1)   //1-5-9  - защита
{
if (a[0, 0] == 0)
a[0, 0] = 1;
if (a[1, 1] == 0)
a[1, 1] = 1;
if (a[2, 2] == 0)
a[2, 2] = 1;
hdpc = false;
paint();
}
else
{
if ((a[2, 0] + a[1, 1] + a[0, 2]) == 4 && a[2, 0] != 1 && a[1, 1] != 1 && a[0, 2] != 1)   //3-5-7  - защита
{
if (a[2, 0] == 0)
a[2, 0] = 1;
if (a[1, 1] == 0)
a[1, 1] = 1;
if (a[0, 2] == 0)
a[0, 2] = 1;
hdpc = false;
paint();
}
}
}
}
}
}
}
}

Как видите, смысл защиты от возможного поражения является почти что точной копией предыдущего метода. Тут стоит лишь напомнить и уточнить несколько вещей:

  • Ходы противника мы отмечаем значением 2. Для этого используется массив a.
  • Метод paint вызывает отрисовку на основе данных матрицы.
  • Переменная булевого типа hdpc(hod pc, ход компьютера) принимает значение false, если пришла очередь ходить пользователю.

Дирижер всех ходов компьютера

Я использовал несколько переменных, которые сохраняли некоторое значение, на основании которых можно было бы понять, чей сейчас ход и кто ходил первым. Очень важным моментом всей программы является необходимость передавать управление то пользователю, то компьютеру. Для этого я рекомендую простой способ: лично я использовал элемент panel, который выполняет роль игрового поле. С помощью булевой переменной hdpc, я либо разрешал принимать нажатие мышкой пользователя на panel, либо нет, что обеспечивало только своевременный ход пользователя. Так же сразу после хода пользователя я запускал на действие специальный метод, который я образно назвал дирижером всех ходом компьютера. В чем это определение очень даже подходит для него, ведь именно здесь будут приниматься решения, какой метод активировать, то есть именно тут можно увидеть всю стратегию данной игры:

nichia();  //проверяем, если хотя бы одно свободное место на поле. Если да, то ходим. Если нет, то вывод сообщения о ничье. Данный метод предлагаю написать вам самим, он довольно прост.
pobeda();  //это тот самый метод для проверки возможности выигрыша
if (win == 0)  //как помните мы использовали переменную win, чтобы обозначить победу компьютера. Если компьютер еще не выиграл, то продолжаем
{
zachita();  //этот метод мы так же описали. Компьютер защищается от возможного проигрыша
if (hdpc == true) //до сих пор ход компьютера, а это значит компьютер пока не может выиграть и поражением никто не пугает, а значит можно ходить по стратегии
{
if (pc == 1) //данная переменная хранит информацию о том, кто первым ходил. Если первым ходил компьютер, то значение равно 1, если пользователь - то 2.
{
krestiki();   //так называется метод, который выполняет ход в самый отдаленный угол от предыдущего хода пользователя
}
else //компьютер ходит вторым
{
if (xfir == 1 && yfir == 1) //пользователь первым ходом сходил в центр
{
ugol();  //ищем любой свободный угол и ходим туда, если это невозможно, ходим в любую свободную клетку
}
else //пользователь первым ходом не сходил в центр
{
if (pervhod)  //данная булевая переменная хранит true, если пользователь собирается сделать первый ход в этой партии
{
hod1(); //ходим в центр
pervhod = false;
}
else
{
ugol();   //ходим в свободный угол
}
}
}
} //конец противоположного хода
nichia();
}
else
{
winner();
}

В данной методе, который я заботливо уложил комментариями, и хранится вся стратегия игры в «крестики-нолики». Нам же остается дописать все необходимые методы.

Ход в противоположный от предыдущего хода угол

Данный метод, который в представленном коде был назван как krestiki, выполняет ход в противоположный от предыдущего шага пользователя угол. Чтобы выполнить данную операцию, мы должны знать, куда последним шагом сходил пользователь. Именно для этих целей я использую специальные переменные. Парочку из них(xfir и yfir — сократил от x first и y first) я уже использовал в предыдущем методе. Данные переменный запоминают только первый ход пользователя. Следующие переменные, которые вы встретите, будут хранить каждый последний шаг пользователя.

if (xlast == 0 && ylast == 0) //если 0,0
{
if (a[2, 2] == 0)
{
a[2, 2] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
else
{
if (xlast == 2 && ylast == 0) //2.0
{
if (a[0, 2] == 0)
{
a[0, 2] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
else
{
if (xlast == 0 && ylast == 2) //0.2
{
if (a[2, 0] == 0)
{
a[2, 0] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
else
{
if (xlast == 2 && ylast == 2) //2.2
{
if (a[0, 0] == 0)
{
a[0, 0] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
else
{
if (xlast == 0 && ylast == 1) //0.1
{
if (a[2, 0] == 0)
{
a[2, 0] = 1;
hdpc = false;
paint();
}
else
{
if (a[2, 2] == 0)
{
a[2, 2] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
}
else
{
if (xlast == 1 && ylast == 0) //1.0
{
if (a[0, 2] == 0)
{
a[0, 2] = 1;
hdpc = false;
paint();
}
else
{
if (a[2, 2] == 0)
{
a[2, 2] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
}
else
{
if (xlast == 2 && ylast == 1) //2.1
{
if (a[0, 0] == 0)
{
a[0, 0] = 1;
hdpc = false;
paint();
}
else
{
if (a[0, 2] == 0)
{
a[0, 2] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
}
else
{
if (xlast == 1 && ylast == 2) //1.2
{
if (a[0, 0] == 0)
{
a[0, 0] = 1;
hdpc = false;
paint();
}
else
{
if (a[2, 0] == 0)
{
a[2, 0] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
}
}
}
}
}
}
}
}

В данном методе мы знакомимся с новым методом random, который отвечает, надеюсь вы догадались, за абсолютно рандомный(случайный шаг). Помните, в стратегии есть и такие ходы. Данный метод я так же оставлю для реализации Вам.

Ход в любой из углов

Последний метод, который я опишу в данной статье, которая неимоверно растянулась, это ход в любой из пустых углов, если конечно такая возможность имеется. Любуйтесь!

if (a[0, 0] == 0)
{
a[0, 0] = 1;
hdpc = false;
paint();
}
else
{
if (a[2, 0] == 0)
{
a[2, 0] = 1;
hdpc = false;
paint();
}
else
{
if (a[0, 2] == 0)
{
a[0, 2] = 1;
hdpc = false;
paint();
}
else
{
if (a[2, 2] == 0)
{
a[2, 2] = 1;
hdpc = false;
paint();
}
else
{
random();
}
}
}
}

Данный метод сделан на основе предыдущего метода, разница лишь в том, что в нем отсутствуют лишние проверки. Тут все просто: находим пустой угол — ходим, не находим — ходим рандомно.

Я понимаю, что приведенная часть это только половина всей программы. Но это основная половина всей программы. В ближайшее время я напишу еще одну статью, в которой опишу «рисовательную» часть этой программы, а так же укажу как отловить ход пользователя на panel`и. Напомню, что все это будет на языке C#. Так же напомню, что мы только что писали код программы, которая имитирует игру компьютера с пользователем в «Крестики-нолики»

Update: Боюсь у меня нет времени и еще больше нет желания заново разбираться в игре, которую я некогда написал и поэтому, скорее всего, обещанная рисовательная часть программы и прочие фишки никогда не увидят свет на страницах сайта About-windows.ru. В связи с этим просто предлагаю вам скачать исходник этой игры и дальше уже самим разобраться в ее коде. Прошу не судить строго по поводу «красоты» программирования.

Ссылка на скачивание игры Крестики и нолики.

P.S. Для тех кто заявляет, что программу можно выиграть, просьба предоставить доказательства(скриншот; порядок ходов с указанием того, кто начинает партию). При этом не нужно обременять себя рассказами про Ваши геройства, если вы играли нечестно(защита от дурака и хакера не продумана так же хорошо, так алгоритм программы).

26 комментариев к записи “Крестики-нолики: код программы на C#
  1. Алексей в cказал :

    Где можно найти продолжение статьи?

    • admin в cказал :

      Боюсь я забыл о своем обещании.

  2. Noizico в cказал :

    То есть, продолжения не будет?

    • admin в cказал :

      Боюсь что нет, но я добавил ссылку в статью на архив с исходником этой игры.

  3. Junior c# в cказал :

    Да уж столько кода а приложение с баггом и не одним!! Хотел скрин шот прикрепить да нельзя

  4. Junior c# в cказал :

    еще так смело заявляете что нельзя выйграть компьютер

    • admin в cказал :

      Я не говорю что в приложении нельзя найти какие-то лазейки, помнится другу это тоже удалось. Но если действовать строго по правилам: выбрал кто будет ходить первым и начать игру, не отвлекаясь на попутные телодвижения, то у меня и друзей, что тестировали, выиграть компьютер не удавалось!

      Различные рода ошибки могут быть, так как программа не была прилизана до блеска, но думаю что и не в этом главная суть. Если есть какие-то ошибки в самом алгоритме хода компьютера, думаю все будут рады услышать и увидеть код лучше, более красивый, более компактный. А скрины можете на залить на любой файловый хостинг, в случае надобности смогу добавить к записи.

  5. Олег в cказал :

    Да уж… ну и код…

  6. Карл в cказал :

    Программа не реагирует на выигрыш человека, а продолжает играть ))

    • admin в cказал :

      А там просто нет алгоритма действий при выигрыше человека. Если играть по правилам и не искать где-то потайные ходы, которые я не успел закрыть, то человек может рассчитывать только ничью как максимум.

  7. Некто в cказал :

    Очень похвально, что вы сами придумали код и реализовали его. Однако вы не учли одну комбинацию (а ее просто невозможно пропустить при тестировании): а что, если юзер будет ставить свои фишки в противоположные углы? вот тут-то программа и падает. В этом случае нужно, чтоб программа быстренько закрыла клетки a[1,0] и a[1,2]. Тогда юзеру придется отбиваться.

    • admin в cказал :

      Спасибо за внимание, но я по-прежнему утверждаю то, что программу не умеет проигрывать и описанный вами случай прекрасно обрабатывается как в случае если компьютер ходит первым, так и в случае если юзер ходит первым. Чтобы проверить я даже не поленился найти и запустить эту игрушку и проверить все на деле. Вот скрины:
      Случай, когда комп ходит первым. Видно что компьютер сделал четыре хода, в то время как юзер кликал по углам. Результат — программа выиграла!

      Случай, когда юзер ходит первым сразу в угол:

      Как видите юзера приглашают ходить. И у компа и у юзера по три хода. Видим что юзер сумел занять два противоположных угла и для чистоты эксперимента занял и последний свободный угол.

      Исходя из всего этого заявляю, что программа еще никогда не проигрывала.

  8. Вадим в cказал :

    Тут как бы это, апдейт выпускать надо… Либо фиксить, либо все-таки сообщение о победе пользователя надо вводить, ибо при проигрыше компьютера он в наглую утверждает, что ничья)))
    Алгоритм игры таков, начинаем первым и ходим, сначала верхний левый, затем нижний левый, затем правый нижний и потом центр. В итоге наступает победа.
    Вот скрин
    https://yadi.sk/i/d-dV5zUjrUnMn

    • admin в cказал :

      Добрый день!

      Спасибо за уточнение. Однако потестив игру еще раз, я понял, что проблема вовсе не в вашем алгоритме действий, а в том, что после нажатия кнопки очистить программа начинает допускать ошибки при новой игре. Но если игру запустить с нуля, то при вашем алгоритме(как впрочем и при любом другом), программа не позволит пользователю выиграть.

      Сей алгоритм брался с Википедии и он не позволяет противнику выиграть, при его соблюдении. Однако еще раз повторюсь, косяк все же имеется)) И вряд ли кого-то устроит перезапускать игру каждый раз.

      Однако желания перебирать и заново разбираться в коде практически полностью отсутствует, а исходники доступны для скачивания. Думаю было бы неплохо если за дальнейшую поддержку взялось сообщество!) А я всегда буду рад разместить новую, обновленную версию игру.

  9. Jigalag в cказал :

    В чем прикол программы? Если она никогда не подтверждает выигрыш человека? Я выиграл у нее уже много раз. В случае когда я первый ставлю крестик, образуя линию, программа следом ставит нолик, тоже образуя линию и выигрывает.. У создателя чсв???

    • admin в cказал :

      Повторюсь еще раз для тех кто с чсв: программу нельзя выиграть, если использовать ее по назначению. Если Вам кажется, что Вам удалось выиграть программу, то закройте ее, запустите заново, поставьте галочку напротив «Пользователь», нажмите Начать и играйте. Уверен, чсв у Вас в таком случае пропадет.

  10. Jigalag в cказал :

    Обычно не люблю влазить в споры. Но не люблю ложь.
    https://yadi.sk/i/kTKH5KbfyWNST
    вот специально записал видео последовательностей моих действий.

  11. Jigalag в cказал :

    Ахаха чсв.. в программе нет даже ни одного случая присвоения win = 2. Сделал программу — умничка. Но зачем кидать слова, мол выиграть нельзя?

    • admin в cказал :

      Прошу прощения. Проверил сам, действительно программа проигрывает.

      При первом ходе игрока в угол, нужно занять центр. Вторым ходом нужно занять противоположный первому ходу противника угол, если это невозможно, занять любую из четырех сторон. В таком случае победа пользователя невозможна. Но вместе этого программа занимает один из свободных углов, что и есть ошибка.

      Я никогда не скрывал, что в программе по-просто не заложено поздравление пользователя с победой. При выполнении всех правил, программу выиграть нельзя. Данный случай — небольшая неприятность.

  12. abubakr в cказал :

    Ребят я тоже выиграл но программа при этом молчит как так сделать чтоб она при выигрыше пользователя обявила победу пользователя, спаибо буду очень рад.

    • admin в cказал :

      Можно поступить проще: довести программу до совершенства, чтобы она правильно ходила при любых действиях.

  13. abubakr в cказал :

    Я только понял что баг начинается после новой игры(очистить), искал не нашел.
    Ребят кому не сложно подскажите где исправить нужно, и спасибо админу за подсказку.
    Если честно то я взял тему курсовой эту игру и нужно ее допилить.

    • admin в cказал :

      Я это делал как обычное приложение в течении семестра. Везет, что такая задача на целую курсовую.

  14. DDoS в cказал :

    Игра не рабочая, логики нет. Компьютер выиграть проще простого, но почему-то в программа это игнорирует.

  15. ruslano98 в cказал :

    Тоже взял тему курсовой крестики-нолики, вы доделали программу?

    • admin в cказал :

      Если Вы спрашиваете о том, исправил ли я баг, который нашли пользователи в комментариях, то нет, не исправил. А так программа сделана и работает, просто в ней есть уязвимость, которая позволяет победить комп.

Добавить комментарий

Ваш комментарий появится после модерации.