Как сделать крестики нолики с компьютером

Добавил пользователь Alex
Обновлено: 04.10.2024

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

Что еще можно сделать в программе?
Программа не воспроизводится оптимально обеими сторонами, потому что ходы выбираются случайным образом. Программу можно легко модифицировать, чтобы оба игрока играли оптимально (что подпадает под категорию искусственного интеллекта). Также программа может быть изменена так, что пользователь сам вводит данные (используя scanf () или cin).
Вышеуказанные изменения оставлены в качестве упражнения для читателей.

// Программа на C ++ для игры в крестики-нолики

using namespace std;


// Функция для отображения текущего статуса доски

void showBoard( char board[][SIDE])

printf ( "\t\t\t %c | %c | %c \n" , board[0][0],

printf ( "\t\t\t %c | %c | %c \n" , board[1][0],

printf ( "\t\t\t %c | %c | %c \n\n" , board[2][0],


// Функция для отображения инструкций

printf ( "\t\t\t Tic-Tac-Toe\n\n" );

printf ( "Choose a cell numbered from 1 to 9 as below"

printf ( "\t\t\t 1 | 2 | 3 \n" );

printf ( "\t\t\t 4 | 5 | 6 \n" );

printf ( "\t\t\t 7 | 8 | 9 \n\n" );


// Функция для инициализации игры

void initialise( char board[][SIDE], int moves[])

// Инициируем генератор случайных чисел так, чтобы

// та же конфигурация не возникает

srand ( time (NULL));

// изначально доска пуста

// Заполняем ходы числами

random_shuffle(moves, moves + SIDE*SIDE);


// Функция для объявления победителя игры

void declareWinner( int whoseTurn)

if (whoseTurn == COMPUTER)

printf ( "COMPUTER has won\n" );

printf ( "HUMAN has won\n" );


// Функция, которая возвращает true, если какая-либо строка
// пересекается с тем же ходом игрока

bool rowCrossed( char board[][SIDE])

if (board[i][0] == board[i][1] &&


// Функция, которая возвращает true, если какой-либо из столбцов
// пересекается с тем же ходом игрока

bool columnCrossed( char board[][SIDE])

if (board[0][i] == board[1][i] &&


// Функция, которая возвращает true, если любая из диагоналей
// пересекается с тем же ходом игрока

bool diagonalCrossed( char board[][SIDE])

if (board[0][0] == board[1][1] &&

if (board[0][2] == board[1][1] &&


// Функция, которая возвращает true, если игра окончена
// иначе он возвращает ложь

bool gameOver( char board[][SIDE])

return (rowCrossed(board) || columnCrossed(board)


// Функция для игры в крестики-нолики

void playTicTacToe( int whoseTurn)

// 3 * 3 Tic-Tac-Toe доска для игры

// Показать инструкции перед игрой

int moveIndex = 0, x, y;

// Продолжайте играть до конца игры

while (gameOver(board) == false &&

if (whoseTurn == COMPUTER)

x = moves[moveIndex] / SIDE;

y = moves[moveIndex] % SIDE;

printf ( "COMPUTER has put a %c in cell %d\n" ,

else if (whoseTurn == HUMAN)

x = moves[moveIndex] / SIDE;

y = moves[moveIndex] % SIDE;

printf ( "HUMAN has put a %c in cell %d\n" ,

// Если игра нарисована

if (gameOver(board) == false &&

moveIndex == SIDE * SIDE)

printf ( "It's a draw\n" );

// Переключение пользователя для объявления фактического

if (whoseTurn == COMPUTER)

else if (whoseTurn == HUMAN)

// Давайте поиграем в игру с компьютером, начинающимся первым

Интересный вариант этой игры
Как сказано выше, если два опытных игрока играют в крестики-нолики, игра всегда будет вничью.
Существует еще один вирусный вариант этой игры — Ultimate Tic-Tac-Toe, цель которого — сделать обычный Tic-Tac-Toe более интересным и менее предсказуемым.
Посмотрите на игру здесь — Link1 Link2

В вышеприведенной статье реализованы простые крестики-нолики, в которых движения выполняются случайным образом. Пожалуйста, обратитесь к статье ниже, чтобы увидеть, как сделать оптимальные шаги.
Минимаксный алгоритм в теории игр | Набор 3 (Tic-Tac-Toe AI — Поиск оптимального хода)

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

Здрасте,написал консольную игру на С++,называеться "Хресити-Нолики". Теперь мне нужно Добавить функционал повторения игры (После того, как показали результат игры, спросить у пользователя, хочет ли он повторить игру. Если пользователь выбирает вариант "да" - игра начинается с начала, "нет" - оформить завершения игры). Можете показать как вывести вот эту статистику в конце,и если человек хочет играть снова,начать игру сначала.Буду очень благодарен,мне нужно модефицировать вот этот код(ну,зделать то,что я написал вверху,буду благодарен если покажете как вы зделали эту статистику и повторенее игры)вот код который нужно это зделать:

2 ответа 2

Примерно так. Переименовываем main() в, скажем, game() , а main пишем так:

Джаноян Елена Владимировна

Искусственный интеллект (ИИ, англ. Artificialintelligence, AI) — наука и технология создания интеллектуальных машин, особенно интеллектуальных компьютерных программ. ИИ связан со сходной задачей использования компьютеров для понимания человеческого интеллекта, но не обязательно ограничивается биологически правдоподобными методами.

В работе описан интерфейс игры, алгоритм программы.

ВложениеРазмер
krestiki-noliki.docx 121.42 КБ

Предварительный просмотр:

Тема: «Как научить компьютер играть в «Крестики-

Джиджоев Владислав Муратович

Джаноян Елена Владимировна,

Описание интерфейса игры……………………………………………… 5

Описание алгоритма игры ………………………………………………. 6

Обычно по завершении партии выигравшая сторона зачёркивает чертой свои три знака (нолика или крестика), составляющих сплошной ряд.

Вот некоторые стратегии игры:

Искусственный интеллект (ИИ, англ. Artificialintelligence, AI) — наука и технология создания интеллектуальных машин, особенно интеллектуальных компьютерных программ. ИИ связан со сходной задачей использования компьютеров для понимания человеческого интеллекта, но не обязательно ограничивается биологически правдоподобными методами.[2]

FreePascalCompiler (FPC) - это свободно распространяемый компилятор языка Паскаль с открытыми исходными кодами. Он совместим с BorlandPascal 7 и ObjectPascal – Delphi, но при этом обладает рядом дополнительных возможностей, например, поддерживает перегрузку операторов. [3]

Описание интерфейса игры

Если было выбрано 2 игрока, то в игре участвуют два человека.

Если был выбран 1 игрок, то человек играет с компьютером.

Причем, при игре с компьютером есть возможность выбора сложности игры.

Для хода игрока необходимо указать номер столбика и номер строки. Отсчет производится с верхнего левого угла.

Окончание игры: фиксируется результат и дается возможность выбора продолжения игры.

Описание алгоритма игры

В простом режиме компьютер сделает ходы на первую попавшуюся пустую клетку.


Поскольку игра получается совсем простая и маленькая, то добавим дополнительные настройки – возможность выбора, кто делает первый ход и кто играет крестиками или ноликами. Для этого создадим еще одну форму и на ней укажем эти настройки


  • вывод на экран поля и крестиков-ноликов (графическая часть)
  • проверка текущего состояния игры (победа, ничья, игра не закончена)
  • первый ход компьютера (если он ходит первым)
  • во время хода компьютера - проверка на две занятые клетки в одной линии, чтобы занять последнюю свободную и выиграть самому или не дать выиграть игроку
  • ход компьютера в зависимости от занятых клеток на поле
  • обработка хода игрока
  • начало и завершение игры.

Создаем 3 формы: Form1 (основная), Form2 (настройки), AboutBox (о программе). На основной форме расположено меню (MainMenu1), панель StatusBar1, таймер, компонент Image – im1 (для отображения графики). В форму загружен значок (Icon). Все графические изображения для игры можно создать в приложении Image Editor, входящем в состав пакета C++Builder 6. Размер компонента im1 – 256 на 256 пикселей. Вывод рисунков будет четко по размерам, поэтому нужно нарисовать еще два файла bmp размерами 55х55 (с иконками крестика и нолика).
Основная форма в режиме разработки

Graphics::TBitmap *gamerIcon, *compIcon, *back; //графические объекты
TRect BackRct; //область для копирования чистого поля
int iTurn; //если 0 – первый ход у игрока, иначе начинает игру компьютер
int iPict; //если 0 – пользователь играет крестиками, иначе - ноликами
int GameStatus; //0-ход игрока, 1 – компьютера, 2 – начало новой игры
int a[9]=; //если 0 – клетка пустая, 1 – занял компьютер, 2 - игрок
int xPos[]=; //координаты клеток
int yPos[]=;

Все клетки хранятся в массиве а. Вывод на экран производится с помощью графических объектов и копирования областей.
Начало игры (функция FormCreate – создание основной формы).

void __fastcall TForm1::FormCreate(TObject *Sender)
iPict=0; //по умолчанию игрок играет крестиками
iTurn=0; //и имеет право первого хода
GameStatus=iTurn; //игровой статус – ход игрока
gamerIcon = new Graphics::TBitmap; //создание новых графич.
compIcon = new Graphics::TBitmap; //объектов
back = new Graphics::TBitmap;

back->LoadFromFile("List1.bmp"); //загрузка рисунка для фона из файла
Form1->im1->Canvas->Draw(0,0,back); //рисунок размещается на канве
//компонента im1
BackRct=Bounds(0,0,im1->Width,im1->Height); //сохраняем область чистого поля
// для новой игры

NewGame();
>

Функция NewGame() – новая игра.
Здесь нужно обнулить массив клеток поля (они пока все свободны); загрузить рисунки крестика и нолика в графические объекты TBitmap, определить прозрачные пиксели в рисунках (чтобы выводить только сами изображения, без фона); если первый ход у компьютера, то сделать его; запустить таймер.

Проверка на победу
Проверяем строки, столбцы и диагонали поля. Если все три клетки заняты одним значком, то возвращаем чью-нибудь победу, если все клетки заняты, но все линии не содержат трех одинаковых значков, то ничья. В противном случае – продолжаем игру.

void __fastcall TForm1::Timer1Timer(TObject *Sender)
if(GameStatus==2) //новая игра
NewGame();
>
if(GameStatus==0)
StatusBar1->Panels->Items[0]->Text="Ход игрока";
Timer1->Enabled=false;
>
if(GameStatus==1)
StatusBar1->Panels->Items[0]->Text="Ход компьютера";
Step(); //функция хода компьютера
GameStatus=0; //переход хода игроку
if(Checking()) //если игра закончена, то есть проверка возвращает не ноль
Victory(Checking()); //вызываем функцию победы - окончание игры
>
>
>

void __fastcall Victory(int v)
Form1->Timer1->Enabled=false;
if(v==1)
ShowMessage("Победа компьютера");
Form1->StatusBar1->Panels->Items[0]->Text="Победа компьютера";
>
else if(v==2)
ShowMessage("Вы победили");
Form1->StatusBar1->Panels->Items[0]->Text="Победа игрока";
>
else if(v==3)
ShowMessage("Ничья");
Form1->StatusBar1->Panels->Items[0]->Text="Ничья";
>
>

Определение критической ситуации
Проверка на наличие линии с двумя занятыми клетками и одной свободной. В функцию передается переменная n – значение, которым может быть элемент массива. Эта функция вызывается во время хода компьютера.

int __fastcall Varning(int n)
< //есть ли линия с двумя занятыми клетками и одной пустой
//если есть – то передается номер пустой клетки
//если нет, то возврат -1

for(int p=0;p

Ход компьютера
Компьютер решает, куда бы ему сходить. Если есть одна свободная клетка в линии с двумя занятыми им же, то он ее занимает и побеждает. Если есть свободная клетка в линии, занятой игроком, то он ее занимает и не дает победить игроку. Если свободна средняя кнопка, то он ее занимает, как самую выгодную позицию. Следующая позиция – угловая клетка, позволяет контролировать три линии. И, если больше некуда податься, то занимает среднюю боковую клетку. После установки значок крестика или нолика рисуется на форме.

Ход игрока
Игрок ходит, нажимая левой кнопкой мыши на свободную ячейку поля. Номер ячейки определяется по координатам курсора мыши. Сначала по координате Y и массиву уPos определяем строку, затем по Х и хPos – столбец и номер клетки. Если клетка свободна, то занимаем ее, затем проводим проверку на победу. Если возвращается значение 0, то есть продолжение игры, то передаем ход компьютеру и включаем таймер. Если же игра закончена, то обрабатываем окончание игры.

Работа с формой Form2 – нажатие кнопки OK:
Работа с формой настроек, присваиваем значения внешним переменным в зависимости от выбора пользователя и сразу начинаем новую игру с новыми настройками. Форма в режиме разработки:


Читайте также: