Как сделать крестики нолики в c

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

Репутация: нет
Всего: нет

Задание по непрофильному предмету.

Игра "крестики-нолики" должна соответствовать 5 пунктам:
1.Должна быть написана языке си без использования элементов си++
2.С интерфейсом командной строки без использования графических библиотек (по сути один фаил с разрешением .с)
3.В самой игре компьютер не совершает ходов, ходы совершают два игрока по очереди
4.Размер поля 3x3
5.Подобные комментарии к каждому этапу
6.При написании можно пользоваться только: конструкциями выбора,циклами,массивами,структурам и,указателями и функциями.Ну и библиотеки понятно самые простые.

В целом игра должна быть написана в самом простом виде.

Думаю опытному человеку на 10 мин.

Репутация: нет
Всего: 3

Цитата(maks1289 @ 17.4.2012, 14:17)
Задание по непрофильному предмету.
Игра "крестики-нолики" должна соответствовать 5 пунктам:
Думаю опытному человеку на 10 мин.

Вообще-то была программка для крестиков-ноликов на калькуляторе Б3-34. По-моему, в книге Дьяконова. Или Трохименко и Любича (кажется, так. )

Репутация: 11
Всего: 135

Репутация: 1
Всего: 196

M
bsa
Для домашних заданий, курсовых и т.п. существует \"Центр Помощи\".

Тема перенесена.

Репутация: 33
Всего: 37

Потратил минут 30. Видать ещё не опытный

//---------------------------------------------//
// Функция приобразует значение символа в индекс массива
unsigned CharToPos(char ch)
static const int COffs = 49;

return (ch - COffs);
>
//---------------------------------------------//
// Вывод на экран игрового поля
void PrintField(const char* arr)
static const char CField[] = " 1 | 2 | 3 \n"
"---+---+---\n"
" 4 | 5 | 6 \n"
"---+---+---\n"
" 7 | 8 | 9 \n";

const char* ch = CField;

if (arr[pos] == 0)
arr[pos] = val;

int main()
static const char CVal[] = ;
char arr[9] = ;
unsigned notUsed = sizeof(arr) / sizeof(*arr);

unsigned player = 0;
char ch;

bool isPlay = true;

while (isPlay)
printf("[%c]: ", CVal[player]);
scanf("%c", &ch);
fflush(stdin);
printf("\n");

if (CheckWin(arr))
isPlay = false;
printf("Player '%c' is win!\n", CVal[!player]);
>
else if (notUsed == 0)
isPlay = false;
printf("Game over\n");
>
>

user posted image

Присоединённый файл ( Кол-во скачиваний: 20 )
archive.7z 2,18 Kb

user posted image

Я знаю, что ничего не знаю© Сократ

Репутация: нет
Всего: нет

Репутация: нет
Всего: нет

Репутация: нет
Всего: нет

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

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

[ Время генерации скрипта: 0.1288 ] [ Использовано запросов: 21 ] [ GZIP включён ]

turn++ делается в цикле который выполняется 10 раз после ввода, поэтому номер хода достигает числа 9 и т.к. проверка на win возвращает false выходит ничья

там где проверка на вин, всегда будет возвращать false потому что после первой же итерации (j=0) будет проверка что count==3, а он никак не может быть равен 3 на первой итерации. return false должен быть после обоих циклов for


первое что бросается в глаза: get_move(); вызывается один раз до цикла, без обработки результата, это ок?

Мышкоблудка

Мышкоблудка



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

nvc123

nvc123


Meddin

Meddin


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

biridius

biridius


turn++ делается в цикле который выполняется 10 раз после ввода, поэтому номер хода достигает числа 9 и т.к. проверка на win возвращает false выходит ничья

там где проверка на вин, всегда будет возвращать false потому что после первой же итерации (j=0) будет проверка что count==3, а он никак не может быть равен 3 на первой итерации. return false должен быть после обоих циклов for


biridius, раздел QA это не раздел "сделайте все за меня", а ты взял и все сделал сам вместо автора вопроса, не надо приучать людей к плохим привычкам! Достаточно было бы указать на проблемы, причем желательно по одной-две за раз, чтобы не перегружать информацией и дать автору шанс самостоятельно найти следующую проблему после решения предыдущей, а готовый код выложить только если это что-то совсем срочное и нет другого выбора.

nvc123

nvc123


Meddin, разжигать огонь можно изи с помощью трения палки об палку
вот только всё же лучше использовать зажигалку или спички
вариант листочек с ручкой в основном используют студенты в лабах когда надо сдать и забыть ибо лень учиться как делать по нормальному
или если в языке нету нормальных средств отлова ошибок для записи их в лог (например jass)
у большинства прогеров по умолчанию в дебаг версии включена запись лога
да и в релизной тоже

Массивы

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

В Java массивы являются объектами, их создают с помощью директивы new . При создании указываем количество элементов массива или инициализируем его набором значений. Приведенный код иллюстрирует оба варианта:

С элементами массива можно работать как с обычными переменными, присваивая им результат выражения и читая хранимые значения. При этом в квадратных скобках указывается индекс элемента массива. Индексация в Java идёт с 0 (с нуля). Первый цикл инициализирует элементы массива arr при помощи значений из массива arrInit . Каждый массив имеет поле length , содержащее количество его элементов. Второй цикл выводит элементы массива в консоль, используя второй вариант for — без счётчика цикла.

Методы

Кроме main() класс может содержать и другие методы. Рассмотрим в качестве примера класс с методом add() , который вычисляет и возвращает сумму двух значений, переданных как параметры. Обратите внимание на тип int , который стоит перед именем метода — это тип возвращаемого значения. Две переменные в скобках — параметры. Совокупность имени и параметров называют сигнатурой метода. Вызов метода происходит по имени, в скобках указывают передаваемые значения. В методе они попадают в параметры-переменные. Команда return возвращает результат сложения этих двух переменных и обеспечивает выход из метода.

Слово static означает, что метод статический. Если мы обращается к какому-либо методу из статического метода, то вызываемый тоже должен быть статическим. Вот почему add() статический — он вызывается из статического main() . Использование статических методов — скорее исключение, чем правило, поэтому давайте посмотрим как сделать add() нестатическим.

Решение одно — создать объект на основании класса. И затем вызывать метод через точку после имени объекта. В этом случае метод может быть нестатическим. Представленный ниже код это иллюстрирует.

Поля класса

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

Приведённый выше код иллюстрирует работу с нестатическим полем int a . Описание полей принято размещать первыми в коде класса, затем идут описания методов. Возможность обращаться к полю (запись, чтение) мы получаем только после создания объекта. Также видно, что это поле доступно во всех нестатических методах объекта, а в статическом main() — через точку после имени объекта.

Крестики-нолики. Шаблон класса

Приступим к написанию кода игры. Начнём с шаблона класса и определения нужных полей. Именно это содержит приведённый ниже код. Первые две строки — импорт классов. Первыми в теле класса идут описания полей, затем методов. Метод main() используется для создания объекта (так как поля и методы нестатические) и вызова метода game() с игровой логикой.

В качестве полей используем три символьные константы: SIGN_X , SIGN_O и SIGN_EMPTY . Их значения нельзя изменять, об этом говорит модификатор final . Двумерный символьный массив table будет нашим игровым полем. Потребуется также объект random для генерации ходов компьютера и scanner для ввода данных от пользователя.

Имена методов принято писать с маленькой буквы. Однако в коде мы видим метод TicTacToe() — есть ли тут нарушение? Нет, поскольку этот метод особенный и в объектно-ориентированном программировании называется конструктор. Конструктор вызывается сразу после того, как объект создан. Его имя, как видим, должно совпадать с именем класса. Мы используем конструктор для инициализации полей.

Игровая логика

Игровая логика располагается в методе game() и базируется на бесконечном цикле while . Ниже в фрагменте кода последовательность действий описана через комментарии:

Реализация вспомогательных методов

Также потребуется метод, отображающий текущее состояние игровой таблицы printTable() .

Валидность ячейки определяет метод isCellValid() . Он возвращает логическое значение: true — если ячейка свободна и существует, false — если ячейка занята или указаны ошибочные координаты.

Метод isTableFull() во вложенном двойном цикле проходит по всем ячейкам игровой таблицы и, если они все заняты, возвращает true . Если хотя бы одна ячейка ещё свободна, возвращается false.

Теперь осталось собрать все эти методы внутри TicTacToe . Последовательность их расположения в теле класса не важна. А после этого можно попробовать сыграть с компьютером в крестики-нолики.

Заключение

Если язык Java вас заинтересовал — приглашаем на факультет Java-разработки. Если ещё не совсем уверены — посмотрите истории успеха наших Java-выпускников:


Массивы

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

В Java массивы являются объектами, их создают с помощью директивы new . При создании указываем количество элементов массива или инициализируем его набором значений. Приведенный код иллюстрирует оба варианта:

С элементами массива можно работать как с обычными переменными, присваивая им результат выражения и читая хранимые значения. При этом в квадратных скобках указывается индекс элемента массива. Индексация в Java идёт с 0 (с нуля). Первый цикл инициализирует элементы массива arr при помощи значений из массива arrInit . Каждый массив имеет поле length , содержащее количество его элементов. Второй цикл выводит элементы массива в консоль, используя второй вариант for — без счётчика цикла.

Методы

Кроме main() класс может содержать и другие методы. Рассмотрим в качестве примера класс с методом add() , который вычисляет и возвращает сумму двух значений, переданных как параметры. Обратите внимание на тип int , который стоит перед именем метода — это тип возвращаемого значения. Две переменные в скобках — параметры. Совокупность имени и параметров называют сигнатурой метода. Вызов метода происходит по имени, в скобках указывают передаваемые значения. В методе они попадают в параметры-переменные. Команда return возвращает результат сложения этих двух переменных и обеспечивает выход из метода.

Слово static означает, что метод статический. Если мы обращается к какому-либо методу из статического метода, то вызываемый тоже должен быть статическим. Вот почему add() статический — он вызывается из статического main() . Использование статических методов — скорее исключение, чем правило, поэтому давайте посмотрим как сделать add() нестатическим.

Решение одно — создать объект на основании класса. И затем вызывать метод через точку после имени объекта. В этом случае метод может быть нестатическим. Представленный ниже код это иллюстрирует.

Поля класса

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

Приведённый выше код иллюстрирует работу с нестатическим полем int a . Описание полей принято размещать первыми в коде класса, затем идут описания методов. Возможность обращаться к полю (запись, чтение) мы получаем только после создания объекта. Также видно, что это поле доступно во всех нестатических методах объекта, а в статическом main() — через точку после имени объекта.

Крестики-нолики. Шаблон класса

Приступим к написанию кода игры. Начнём с шаблона класса и определения нужных полей. Именно это содержит приведённый ниже код. Первые две строки — импорт классов. Первыми в теле класса идут описания полей, затем методов. Метод main() используется для создания объекта (так как поля и методы нестатические) и вызова метода game() с игровой логикой.

В качестве полей используем три символьные константы: SIGN_X , SIGN_O и SIGN_EMPTY . Их значения нельзя изменять, об этом говорит модификатор final . Двумерный символьный массив table будет нашим игровым полем. Потребуется также объект random для генерации ходов компьютера и scanner для ввода данных от пользователя.

Имена методов принято писать с маленькой буквы. Однако в коде мы видим метод TicTacToe() — есть ли тут нарушение? Нет, поскольку этот метод особенный и в объектно-ориентированном программировании называется конструктор. Конструктор вызывается сразу после того, как объект создан. Его имя, как видим, должно совпадать с именем класса. Мы используем конструктор для инициализации полей.

Игровая логика

Игровая логика располагается в методе game() и базируется на бесконечном цикле while . Ниже в фрагменте кода последовательность действий описана через комментарии:

Реализация вспомогательных методов

Также потребуется метод, отображающий текущее состояние игровой таблицы printTable() .

Валидность ячейки определяет метод isCellValid() . Он возвращает логическое значение: true — если ячейка свободна и существует, false — если ячейка занята или указаны ошибочные координаты.

Метод isTableFull() во вложенном двойном цикле проходит по всем ячейкам игровой таблицы и, если они все заняты, возвращает true . Если хотя бы одна ячейка ещё свободна, возвращается false.

Теперь осталось собрать все эти методы внутри TicTacToe . Последовательность их расположения в теле класса не важна. А после этого можно попробовать сыграть с компьютером в крестики-нолики.

Заключение

Если язык Java вас заинтересовал — приглашаем на факультет Java-разработки. Если ещё не совсем уверены — посмотрите истории успеха наших Java-выпускников:

Войдите как ученик, чтобы получить доступ к материалам школы

Создание конфигураций 1С: пишем "Крестики-нолики" часть 3/3

Автор уроков и преподаватель школы: Владимир Милькин

krestiki-noliki

Заключительная часть разработки Крестиков-ноликов на 1С. После четырнадцатого
шага мы создали пустую процедуру "ХодКомпьютера" и добавили её вызов сразу после нашего хода.

Если вы прерывались (закрывали конфигуратор) после предыдущей части - выполните шаг №2 (открытие конфигуратора) и шаг №3 (открытие дерева конфигурации) . В дереве конфигурации откройте обработку "КрестикиНолики":
- найдите в ней закладку "Формы"
- откройте там элемент "Форма"
- перейдите в модуль формы (закладка "Модуль" внизу)
- уже после этого переходите к шагу №15

Шаг №15: добавляем переменную Поле для хранения состояний кнопок

Чтобы компьютер смог походить ему нужно проанализировать текущее состояние поля - какие клетки заняты, а какие свободны. Специально для хранения нашего поля заведём переменную "Поле" и расположим её в самом начале модуля:

56

Завести переменную - пол дела. Нужно её правильно инициализировать (присвоить начальное значение). И делать это лучше всего в самом начале выполнения программы - в обработчике открытия нашей формы.

Шаг №16: добавляем обработчик открытия формы

Чтобы попасть в этот обработчик - вернёмся в визуальное представление формы (закладка "Форма") и выделим (двойным щелчком) элемент "Форма" в окне с элементами:

51

В окне свойств формы (справа) промотаем полосу прокрутки вниз и найдём там событие "ПриОткрытии". Щелкнем на кнопке с лупой:

52

Программа предлагает нам создать обработчик для этого события. Выберем вариант "Создать на клиенте" и нажмем кнопку "ОК":

53

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

54

Шаг №17: в обработчике открытия формы инициализируем переменную Поле

Обработчик ПриОткрытии создан. Чем будем инициализировать переменную Поле? А давайте ещё раз вспомним, что именно мы собираемся в ней хранить. Мы собираемся хранить состояние поля. А вернее состояние его ячеек. Для хранения набора каких-то однотипных данных идеально подойдёт тип массив. Вот его мы и создадим в переменной Поле.

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

Чтобы вам стало понятнее, что из себя будет представлять массив "Поле" я приведу такую картинку:

07

Массив "Поле" это двумерная таблица, к элементам которой мы сможем обращаться по номеру строки и номеру столбца.

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

Вставим в эту процедуру следующий код:

55

Войдите на сайт как ученик

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

Шаг №18: переименовываем все кнопки

Следующая задача дать кнопкам на форме такие имена, чтобы мы смогли из кода легко находить имя кнопки по номеру строки и столбца на поле.

К примеру, кнопку располагающуюся в нулевой строке и нулевом столбце (отсчет будем вести с нуля) назовём "Кнопка00", а кнопку в первой строке и втором столбце "Кнопка12" и т.д.

Для этого перейдем в визуальное представление формы (закладка "Форма") и выделим двойным щелчком кнопку с именем "НажатиеНаКнопку":

57

В окне свойств этой кнопки (справа) найдём свойство "Имя" и изменим его значение на "Кнопка00":

06

Изменим имена всех кнопок так, чтобы в итоге все кнопки в группах назывались следующим образом:

58

Шаг №19: пишем содержание процедуры ХодКомпьютера

Наконец, мы можем определить работу процедуры "ХодКомпьютера". Что будет делать эта процедура? В ней нужно будет пробежаться по каждой из ячеек массива Поле, в котором хранятся состояния ячеек (свободна, занята компьютером, занята игроком). Сравнить каждую из ячеек с пустой строкой (признак того, что она свободна и в неё можно походить) . И если такая ячейка найдётся, поставить в неё "Х" (признак того, что в неё походил компьютер) и не забыть отобразить крестик в соответствующей кнопке на форме.

Код будет таким:

59

Войдите на сайт как ученик

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

Шаг №20: уже можно играться!

Запустим 1С в режиме Предприятие (меню "Отладка"->"Начать отладку"), откроем обработку ("Сервис"->"Крестики нолики") и убедимся, что, в принципе, уже можно играть:

60

Но вот незадача - компьютер перезатирает наши ходы! А всё дело в том, что в процедуре "НажатиеНаКнопку" мы нолик-то на кнопке отображаем, а вот в массив "Поле" этот нолик не ставим. Поэтому компьютер и не видит наши ходы.

Шаг №21: избавляемся от затирания наших ходов

Изменим процедуру "НажатиеНаКнопку" так, чтобы наш ход проставлялся не только на кнопке, но и в массиве "Поле" (добавленный код очерчен жёлтым цветом):

61

Войдите на сайт как ученик

Попробуем запустить 1С в режиме Предприятие (меню "Отладка"->"Начать отладку") вновь и поиграть с компьютером. На этот раз наши ходы не будут перезатираться компьютером.

Шаг №22: программируем логику окончания игры

Но есть другая проблема - логика игры не учитывает её окончание, когда один из игроков выстроил свои крестики или нолики в строку, столбец или диагональ.

Добавим такую проверку. Для этого напишем отдельную функцию "ИграОкончена", которая будет возвращать Истина или Ложь в зависимости от того - присутствует ли на поле выигрышная комбинация.

Пока определим эту функцию пустой (добавьте её в конец модуля формы) , всегда возвращающей Ложь:

62

65

Войдите на сайт как ученик

Разработка игры почти окончена. Нам осталось определить логику выполнения функции "ИграОкончена", которая пока что всегда возвращает "Ложь".

Ещё раз вспомним представление нашего массива "Поле":

07

И сделаем элементарную проверку всех возможных выигрышных комбинаций на поле:

Снова запускаем режим 1С:Предприятие (меню "Отладка"->"Начать отладку") и наслаждаемся игрой в Крестики-нолики против компьютера.

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

На этом разработка крестиков-ноликов окончена, давайте же перейдём к следующему проекту.

Войдите на сайт как ученик

Для учеников

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

На вопросы учеников — отвечаю по почте, но прежде загляните в ЧАВО (ссылка) .

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