//---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
/*
если один из игроков заполнил всю горизонталь / вертикаль / диагональ,
возвращает символ, которым он играет
если никто еще на заполнил линию, возвращает пробел
*/
int check(int** field, int size) {
// итераторы
int i, j;
// первый символ по горизонтали и первый по вертикали
int g, v;
// диагонали
int d1, d2;
// начинается цикл в n заходов, n равно размеру поля
for (i = 0; i < size; i++) {
// ПРОВЕРКА ПО ГОРИЗОНТАЛИ
// запоминаем символ из начала i строки поля
g = field[i][0];
// проходимся по i строке поля
for (j = 0; j < size; j++) {
// если натенемся на несовпадение с первым символом
// или если первый символ был пробелом, то
if (field[i][j] != g || g == ' ') {
// забиваем на проверку, записываем в g символ ' '
g = ' ';
// и выходим цикла принудительно
break;
}
}
// если в g хранится символ, отличный от пробела, это значит что в начале
// строки был крестик или нолик, и проходя по всей строке (в цикле выше)
// мы не наткнулись на символ, отличающийся от того, что в начале
// иными словами, один из игроков заполнил всю строку одним символом
// и выйграл
if (g != ' ') {
// если это условие выполнено, просто возвращаем символ, которым
// заполнена вся строка
return g;
}
// ПРОВЕРКА ПО ВЕРТИКАЛИ
// записываем символ из начала i столбца поля
v = field[0][i];
// проходим по i столбцу
for (j = 0; j < size; j++) {
// если натенемся на несовпадение с первым символом
// или если первый символ был пробелом, то
if (field[j][i] != v || v == ' ') {
// забиваем на проверку, записываем в v символ ' '
v = ' ';
// и выходим цикла принудительно
break;
}
}
// если в v хранится символ, отличный от пробела, это значит что в начале
// строки был крестик или нолик, и проходя по всей строке (в цикле выше)
// мы не наткнулись на символ, отличающийся от того, что в начале
// иными словами, один из игроков заполнил всю строку одним символом
// и выйграл
if (v != ' ') {
// в таком случае возвращаем этот символ
// это означает, что игрок с этим символом выйграл
return v;
}
}
// Записываем, какие символы в начале основной и побочной диагонали
d1 = field[0][0];
d2 = field[0][size - 1];
// проверка по основной диагонали
// ?##
// #?#
// ##?
for (i = 0; i < size; i++) {
// если наткнемся на несовпадение
if (field[i][i] != d1) {
// забиваем на проверку, записываем в d1 символ ' '
d1 = ' ';
// принудительно выходим их цикла
break;
}
}
// если все знаки на диагонали одинаковые, и знак не пробел, возвращаем знак
if (d1 != ' ') {
return d1;
}
// проверка по побочной диагонали
// ##?
// #?#
// ?##
for (i = 0; i < size; i++) {
// если наткнемся на несовпадение
if (field[i][size - 1 - i] != d2) {
// забиваем на проверку, записываем в d1 символ ' '
d2 = ' ';
// принудительно выходим их цикла
break;
}
}
// если все знаки на диагонали одинаковые, и знак не пробел, возвращаем знак
if (d2 != ' ') {
return d2;
}
// если ни одна из полос не заполнена, возвращаем пробел
return ' ';
}
// вывод поля
void out(int** field, int size) {
int i, j;
// очистка экрана
system("cls");
// верхняя граница поля
for (j = 0; j < size; j++) {
printf("--");
}
printf("-\n");
// выводим по очереди все ряды и деления
for (i = 0; i < size; i++) {
// ряд символов
for (j = 0; j < size; j++) {
printf("|%c", field[i][j]);
}
printf("|\n");
// деление
for (j = 0; j < size; j++) {
printf("--");
}
printf("-\n");
}
}
int main() {
// поле (массив массивов), размер
int **field;
int size;
// текущий игрок
int player = 'x';
// результат проверки игрового поля на заполнение полосы
int result;
// индикатор работы игры
int running = 1;
// итераторы
int i, j;
// вводим размер поля
printf("Enter field size: ");
scanf("%i", &size);
// выделяем память под массив из size указателей на массивы
// (читай size строк)
field = malloc(size * sizeof(int*));
// заполняем массив указателей указателями на новые массивы
// (читай size ячеек в каждой строке)
for (i = 0; i < size; i++) {
field[i] = malloc(size * sizeof(int));
// заполняем каждую ячейку пробелом
for (j = 0; j < size; j++)
field[i][j] = ' ';
}
// пока игра продолжается
while (running) {
do {
// выводим поле
out(field, size);
// выводим чей ход
if (player == 'x') {
printf("x turn\n");
} else {
printf("o turn\n");
}
// вводим координаты хода (от 1 до size)
printf("Type x y (separated by space): ");
scanf("%d %d", &i, &j);
// если пользователь введет что-то неправильно, цикл продолжается
// и спрашивает заново
// как только игрок введет координаты правильно, цикл остановится
} while(i > size || j > size || i < 0 || j < 0 || field[i - 1][j - 1] != ' ');
// зачеркиваем ячейку поля
field[i - 1][j - 1] = player;
// проверяем поле
result = check(field, size);
// если result не пробел, значит кто-то выйграл
if (result != ' ') {
// выводим символ победителя (хранится в result)
printf("%c wins!", result);
// останавливаем игру
running = 0;
}
// передаем ход другому игроку
if (player == 'x') {
player = 'o';
} else {
player = 'x';
}
}
return 0;
}