Разработка приложения, представляющего собой компьютерную игру 'Крестики нолики'
Технология
программирования
Методические
указания по курсовому проектированию для студентов специальности 230201
"Информационные системы и технологии"
Разработка
приложения, представляющего собой компьютерную игру "Крестики нолики"
Владивосток
Содержание
Введение
. Интерфейс пользователя и Сценарии
использования программы
. Функциональные требования
. Нефункциональные требования
. Файловые интерфейсы
. Исключительные ситуации
. Поэтапное описание создание кода
игры
Заключение
Список литературы
Введение
Разрабатывается консольное приложения,
представляющего собой игру "Крестики нолики".
Разработчик:
Смысл игры: заключается в том чтобы играть
крестиками или ноликами и набрать больше выиграшных комбинаций.
Правила и описание программы: в игру играют два
пользователя, которые выбирают между собой чем будут играть крестиком или
ноликом и поочереди вводят в окне консоли посредством клавиатуры числа
отвечающие за ячейки. Выигрывает тот пользователь который первым составит
выиграшную комбинацию из из 3-х подряд крестиков или ноликов по горизонтали,
повертикали или по диагонали.
1. Интерфейс
пользователя и Сценарии использования
В меню Menu hodov отображаются цифры в клетках
которые отвечают за клетки игровой доски. Пользователи вводят числа от 1 до 9 в
строке Vvod chisla и для отображение символа нужно нажать Enter. Если
пользаватель вводит 1 то символ икса отобразится в левой нижней клетке, а если
введёт 5 символ нолика отобразится в средней клетке и т.д.
Пользователь ввёл выигрышную комбинацию из
крестиков и отобразилось меню статистики в котором игроку играющему иксом
отобразился счёт +1. Ниже отображается запрос для пользователя, желает ли он
продолжить игру и допустимые ответы y
или n. Для продолжения
нужно ввести y или для выхода из
игры n нажать Enter
2. Функциональные требования
Для запуска игры нужно дважды кликнуть на
исполняемом файле с названием игры с расширением exe.
Для продолжения нужно ввести y
или для выхода из игры n
и нажать Enter. Для игры нужно использовать кнопки клавиатуры от 1 до 9, если
будут введены другие числа то появится сообщение в котором говорится что бы
пользователь ввёл число от 1 до 9.
. Нефункциональные требования
Приложение игра работает под операционной
системой Windows
и Linux с установленным wine.
Приложение работает быстро и поскольку эта небольшая программа консольное
приложение то требования для Персонального компьютера на котором будит
использоваться минимальны.
. Исключительные ситуации
Если ввести число более 9-и символов или символ
буквы программа перестаёт работать и сваливается в "штопор". Если
такое случится то нужно срочно закрыть программу нажав красный крестик вверху
окна. Почему программа реагирует именно так, решения не нашёл. Решение:
добавить дополнительную проверку для символов букв, числа символов числа, самих
символов, что бы при вводе таких символов появлялось сообщение "Vvedite
chislo ot
<1 do 9>"
5. Поэтапное описание создание кода игры
Введение в объектно-ориентированное программирование.
Объектно-ориентированное программирование
представляет собой чуть более автоматизированный способ программирования.
Объектно-ориентированные программы - это не просто процедурные программы,
переведенные на новый синтаксис. Они должны строится на новой философии
разработки. Для них требуется новая стратегия программирования, которую часто
бывает трудно освоить. сновная идея ООП: программа состоит из группы объектов,
часто связанных между собой. В С++ объекты описываются при помощи нового типа
данных class.
Класс включает в себя набор переменных (данных)
и операций (методов или функций-членов), которые действуют на эти переменные.
Полученными объектами можно управлять при помощи сообщений. В ООП объекты
включают в себя не только данные (данные-члены), но и методы (функции-члены)
воздействия на эти данные. Эти две части в сочетании образуют функциональную
единицу программы. Другими словами, объекты содержат данные и методы работы с
этими данными. Ниже приведены три основных преимущества объектно-ориентированных
программ по сравнению с эквивалентными программами, разработанными сверху вниз.
Сопровождение программы. Программы проще читать
и понимать, ООП позволяет управлять сложностью программы, оставляя видимыми
программисту только существенные детали.
Модификация программы (добавление или исключение
возможностей). Вы можете часто делать дополнения или исключения в программе,
например при работе с базой данных, просто добавляя и исключая объекты. Новые
объекты могут наследовать все свойства базовых объектов, необходимо только
добавить или убрать отличающиеся свойства. Повторное использование. Можно
сохранить грамотно разработанный объект в наборе полезных программ и затем
вставить его в новую программу с небольшими изменениями или без изменений..
Основные термины и положения ООП.
Функция это кусок кода, который можно
неоднократно вызывать из любого места программы состоящая из 2-х частей:
объявление функции(прототип функции) содержит информацию о типе и определения.
Формат прототипа функции состоит:
<тип результата> <название функции>
([<тип> [<название
параметра1>][,..,<тип> [<название параметраN>]]]
параметр <тип результата> задаёт тип
значения, которое возвращает функция с помощью оператора return. Если функция
не возвращает никакого значения, то вместо типа указывается ключевое слово
void. Название функции должно быть допустимым индетификатором. После названия
функции, внутри круглых скобок указывается тип и название параметра через
запятую. Название параметров в прототипе функций можно не задавать вообще. Если
функция не принимает параметров, то указываются только круглые скобки()или
внутри задаётся ключивое слово void (void). После объявления функции должна
стоять точка с запятой(;) Определение функции содержит описание типа и название
параметров и реализацию:
<тип результата> <название функции>
([<тип> [<название параметра1>]
[,..,<тип> [<название параметраN>]]]
{
<тело функции>возвращаемое_значение;
}
В отличие от прототипа в определении функции
после типа обязательно должно быть указанно название параметра, которое
является локальной переменной и она создаётся при вызове функции, а после
выхода из функции удоляется. Таким образом, локальная переменная видна только в
внутри функции.
После описания параметров, внутри фигурных
скобок размещаются инструкции, которые будут выполнятся при каждом вызове
функции. Фигурные скобки {} указываются в любом случае,даже если тело функции
состоит только из одной инструкции. Точка с запятой(;) после закрывающей
фигурной скобки не указывается.
Вернуть значение из функции позваляет оператор
return. После исполнения этого оператора выполнение функии останавливается и
управление передаётся обратно в точку вызова функции.
Если перед названием функии указанно ключевое
слово void, то оператора return может не быть, а если неоходимо досрочно
прервать выполнение функции, то оператор return указывается без возвращаемого
значения.
При вызове функции из программы указывается
название функции, после которого в круглых скобках передаются значения. Если
функция не пренимает параметров, то указываются только круглые скобки. Если
функция фозвращает значение, то его можно присвоить переменной или
проигнорировать.
Количество и тип параметров в определении
функции должны совпадать с количеством и типом параметров при вызове.
Переданные значения присваиваются переменным, расположенным в той же позиции в
определении функции. Объявление фукции должно распологатся перед вызовом и
тогда название функции всегда является глобальным идентификатором.
В небольших программах допускается объявление
функциё не указывать, при условии, что определение функций расположенно перед
функцией main().Функция main()так же не требует объявления т.к. она вызывается
первой.
При увеличении количества фукций объявление
фукций следует размещать в начале программы перед функцией main(),а определения
после функции main() и в этом случае порядок следования определений функций не
имеет значения.
При увеличении размеров программ объявление
функций выносят в заголовочный файл с расширением h(иногда hpp), а определения
функций размещаются в одноимённом файле с расширением срр. Все файлы
распологаются в одной папке с основным файлом, содержащем функцию main()и в
дальнейшем с помощью дерективы #include заголовочный файл подключают во всех
остальных файлах.
Инкапсуляция данных. Этот термин включает в себя
логическое связывание данных с конкретной операцией. Она так же означает, что
они являются не -глобальными доступными всей программе, а локальными -
доступными только малой ее части. Инкапсуляция также автоматически
подразумевает защиту данных. Именно для этого предназначена структура class в
С++. В классе управление функциональными деталями объекта осуществляется при
помощи спецификаторов private, public, protected.
Иерархия классов. В общем случае можно
представить себе иерархию классов как родословную в генеалогическом древе, где
класс С++ представляет собой шаблон для создания классов-потомков. Объекты,
полученные из описания класса, называют экземплярами этого класса. Можно
создать иерархию классов с классом-родителем и несколькими классами-потомками.
Основой для этого являются производные классы.
Наследование.
Наследование в ООП позволяет классу получать
свойства другого класса объектов. Родительский класс служит шаблоном для
производного класса; этот шаблон можно менять различными способами.
Наследование является важным положением, поскольку оно позволяет повторно
использовать определение класса без значительных изменений в коде.
Полиморфизм. Строится на описанной выше
концепции наследования. Программа посылает одно и тоже сообщение как объекту
родительского класса, так и всем объектам производных классов. И родительский
класс, и классы-потомки ответят на сообщение соответствующим образом.
Полиморфизм дает возможность дополнять уже существующие части программы.
Виртуальные функции определяются в родительском
классе, а в производных классах происходит доопределение этих функций и для них
создаются новые реализации. При работе с виртуальными функциями сообщения
передаются как указатели, которые указывают на объект вместо прямой передачи
объекту. Виртуальные функции используют таблицу для адресной информации. Эта
таблица инициализируется во время выполнения при помощи конструктора.
Конструктор вызывается каждый раз, когда создается объект его класса. Задача
конструктора в данном случае состоит в связывании виртуальной функции с
таблицей адресной информации. Во время компиляции адрес виртуальной функции
неизвестен; вместо этого ей отводится позиция в таблице адресов.
Циклы. Операторы цикла(for)позволяют выполнить
одни и те же инструкции многократно. Цикл(for)выполняется до тех пор пока
<условие> не вернёт false(ложь) и если это не произойдёт цикл будит
бесконечным. for(<начальное_значение> присваивает переменной-счётчику
начальное значение; <условие> содержит логическое выражение и пока логическое
выражение возвращает true(истина) выполняются инструкции внутри цикла;
<приращивание> задаёт изменение переменной-счётчика на каждой интерации
на указанное ++ означает увеличить на 1)Выполнение выражений в цикле
продолжается до тех пор, пока логическое выражение истинно.
ООП полностью принадлежит к миру С++, поскольку
в С нет основного ядра- абстрактного типа данных class. Поэтому переписать
процедурно-ориентированную программу как объектно-ориентированную гораздо
сложнее, чем просто подставить вместо одного ключевого слова другое.
ООП представляет собой технику программирования,
которая позволяет рассматривать основные идеи как множество объектов. Используя
объекты, можно представить задачи, которые необходимо выполнить, их
взаимодействие и любые заданные условия, которые должны быть соблюдены.
Структура данных часто образует основы объектов.
Таким образом в С или С++ тип struct может
образовывать элементарный объект. Связь с объектом можно организовать при
помощи сообщений. Использование сообщений похоже на вызов функций в
процедурно-ориентированной программе. Когда объект получает сообщение, вступают
в действие методы, содержащиеся в объекте. Методы (их иногда называют функциями
- членами) аналогичны функциям процедурно-ориентированного программирования.
Тем не менее метод является частью объекта, а не чем-то отдельным, как было бы
в процедурном аналоге.
Объектно-ориентированное программирование - это
новый способ подхода к программированию. Такое программирование, взяв лучшие
черты структурного программирования, дополняет его новыми идеями, которые
переводят в новое качество подход к созданию программ.
Наиболее важное понятие языков
объектно-ориентированного программирования -это понятие объекта (object).
Объект - это логическая единица, которая содержит данные и правила (методы)
обработки этих данных. В языке С++ в качестве таких правил обработки выступают
функции, т. е. объект в Borland C++ объединяет в себе данные и функции,
обрабатывающие эти данные. Одним из самых главных понятий языка С++ является
понятие класса. В языке С++ для того, чтобы определить объект, надо сначала
определить его форму с помощью ключевого слова Ближайшей аналогией класса
является структура. Память выделяется объекту только тогда, когда класс
используется для его создания. Любой объект языка С++ имеет одинаковые атрибуты
и функциональность с другими объектами того же класса. За создание своих
классов и поведение объектов этих классов полную ответственность несет сам
программист. Работая в некоторой среде, программист получает доступ к обширным
библиотекам стандартных классов. Обычно, объект находится в некотором
уникальном состоянии, определяемом текущими значениями его атрибутов.
Функциональность объектного класса определяется возможными операциями над
экземпляром этого класса.
Структуры.
Структура-группа данных различных типов и(или)
назначения, которые представляют собой единый информационный элемент.
Поскольку в объектах также можно хранить группы
разнотипных данных, то они тоже содержат структуры. Отличие структуры от класса
в том, что в структуре нет закрытых и защищенных членов. Все члены структуры
открыты.
Объявление структуры аналогично объявлению
класса но вместо ключевого слова class ставится ключевое слово Struct :
идентификатор
{
Объявление данных или объектов
};
Объявлений структуры не подразумевает создание
объекта или переменной. Объявление-это просто описание будущего объекта, в
данном случае змейки. Чтобы использовать объект определенного класса или
переменную определенного типа их сначала необходимо объявить в качестве объекта
этого класса или переменной этого типа.
Аналогично для использования структурной
переменной необходимо объявить переменную этой структуры.
Графический интерфейс.
Пользовательский интерфейс-это средства общения
пользователя с вашей программой. которые могут включать в себя изображения ,
звуки и текст. Ориентируясь на среднего пользователя интерфейс должен быть
простым и удобным. Это снизит вероятность ошибок.
. Поэтапное описание создание кода игры (8
этапов)
Изменения в коде обозначены красным цветом.
) Создание доски в которой пользователь будит
вводить данные. Подключается файл <iostream> , в котором объявлен объект
cout, при помощи директивы include. Далее создаётся функция main внутри которой
расположены инструкции ограниченные фигурными скобками ( { } ). Перед названием
функции указывается тип возвращаемого значения. Ключевое слово int означает,
что функция возвращает целое число. Вывод строки на экран с помощью объекта
cout. Чтобы исключить конфликт имён все стандартные идентификаторы в языке С++
определены в пространстве имён std. Поэтому перед именем объекта cout
необходимо указать название пространства имён. Между названием пространством
имён и названием объекта указывается два двоеточия (std::cout ). С помощью
std::cout в окно выводится заголовок Menu hodov: и номирацию ячеек
"-7-|-8-|-9-" и т.д. Строки заканчиваются операторами \n(оператор
перехода на новую строчку) и endl в конце строк ( ;) Оператор return возвращает
функции main() 0(ноль).
КОД: (меню выбора)
#include
<iostream>main(){::cout<<"Menu hodov:
\n";::cout<<"-7-|-8-|-9-" <<
std::endl;::cout<<"-4-|-5-|-6-" << std::endl;::cout<<"-1-|-2-|-3-"
<< std::endl;::cout<<"\n\n";//два оператора \n означает
пропуск 2-х строк0;
}
Консоль выводит:
) Выводится ниже пустая доска с заголовком
"Game board" ( игровое поле) в которой и будут отображаться X или О.
Для ввода X или О в ячейках пустой доски пользователь вводит цифру в строке
ниже пустой доски, по средством ввода цифр отвечающих за данную клетку. К
примеру введя цифру 5 для ячейки принадлежащей цифре 5 в доске "Menu
hodov" и отобразится X или О, но в пустой доске расположенной ниже.
КОД:
#include
<iostream>main(){::cout<<"Menu hodov: \n";//Меню
ходов/вводов для пользователя::cout<<"-7-|-8-|-9-" <<
std::endl;::cout<<"-4-|-5-|-6-" <<
std::endl;::cout<<"-1-|-2-|-3-" <<
std::endl;::cout<<"\n\n"::cout<<"Game board:
\n"; //Игровая доска::cout<<"--|--|--" <<
std::endl;::cout<<"--|--|--" <<
std::endl;::cout<<"--|--|--" <<
std::endl;::cout<<"Your move";0;
}
Консоль выводит:
) Создаётся своя функция которая и будит рисовать
доску. Что бы не загромождать main. В main останется главная логика (начать
программу, взять у пользователя его выбор, нарисовать его на доске). Функция
эта будит называться "get_move()" (Получить ввод пользователя).
Переносится в неё из main строки досок (в листинге выделены красным и в main
останется только оператор return ,возвращающий ноль 0; )и размещаются в { },
точка с запятой после закрывающей функцию фигурной скобки не ставится. Что бы
получить вход пользователя создаётся переменная "move" и просим что
бы пользователь ввёл эту переменную (число) при помощи "std::cin
>>" и возвращаем оператором return значение "move". Но
пользователь может ввести/описаться число меньше 1 и больше 9. Чтобы напомнить
пользователю что цифры меньше 1 и больше 9 не играют, создаётся цикл "
while" который проверяет: "пока вход который дал пользователь больше
9 (move > 9) или (|| ) вход меньше 1 (move < 1 ). Если пользователь ввёл
число меньше 1 и больше 9 то выводится на экран при помощи std::cout<<сообщение
"Vvedite chislo ot 1 do 9:". Запрашивается с помощью std::cin>>
у пользователя другой вход move(ввод числа от 1 до 9). В функции main пишется
несколько строк что бы протестировать функцию. int move = get_move();
std::cout<< "the move you intereted is:" << move <<
std::endl; Пишется с помощью std::cout<< в окне консоли сообщение
"the move you intereted is:"
Код( )
#include <iostream>get_move(){// функция
которая и будит рисовать доску::cout<<"Menu hodov: \n";//Меню
Доска намирации клеток::cout<<"-7-|-8-|-9-" << std::endl;//Доска
намирации клеток::cout<<"-4-|-5-|-6-" <<
std::endl;::cout<<"-1-|-2-|-3-" <<
std::endl;::cout<<"\n";//C помощью оператора \n пропускается
одна строка::cout<< "Game board:" << std::endl;//Меню
пустой доски::cout<<"---|---|---" << std::endl;//Пустая
доска::cout<<"---|---|---" <<
std::endl;::cout<<"---|---|---" <<
std::endl;::cout<<" Vvod chisla ";move;// Что бы получить вход
пользователя создаётся переменная move::cin >> move;//Просим что бы
пользователь ввёл эту переменную (число)(move > 9 || move < 1){//Цикл
while проверяет вход который дал пользователь больше 9 (move > 9) или (|| )
вход меньше 1 (move < 1 )::cout<<"Vvedite chislo ot 1 do
9:";//Если пользователь ввёл число меньше 1 и больше 9 то выводится на
экран сообщение "Vvedite chislo ot 1 do 9:"::cin >>
move;//Запрашиваем с помощью std::cin >> у пользователя другой вход
move(ввод числа от 1 до 9)
}move;//Возвращаем оператором return значение
"move"
}main(){move = get_move();//Вызывается
функция_move()и помещается то что она вернет в переменную::cout <<
"the move you intereted is: " << move <<
std::endl;//Пишется с помощью std::cout<< в окне сообщение "the move
you intereted is: "0;
}
Консоль выводит:
) Сейчас программа получает ход пользователя и
рисует пустую доску. Чтобы отобразить ход(ввод)пользователя на доске
переписывается нынешняя. Доска будит состоять из 9-и однобуквенных стрингов
char. Заменяется переменная стринг (-) на переменную board[] с номером клетки,
т.к. переменные начинаются с нуля, то вместо 1 пишется 0, вместо 2 пишется 1 и
т.д. Пишется простой цикл for(int i=0; i<9; i++) для 9 ходов и два выражения
ставятся в цикл int move = get_move() std::cout <<
"the move you intereted is:" <<
move <<std::endl. Программа получает вход move, далее меняется массив
board[] и пишется board[move-1]([move-1] потому, что когда вводится 1 первая
клетка/ячейка по таблице то изменятся должен 0(нулевой) элемент массива, потому
как клетка/ячейка начинаются с 1, а элемент той ячейки в массиве начинается с
0(нуля)). Строкой if(i%2 == 0) проверяется чётное или нечётное число ввёл
пользователь т.е. если i по модулю 2 равняется 1, то это чётный ход, то для
board[move-1] задаётся значение ='X', а все остальные ходы будут нечётные и для
board[move-1] задаётся значение ='О'. В цикле while добавляется проверка
клеток/ячеек на случай если там уже установлен символ. Добавляется ||
board[move-1] != '-' т.е. board[move-1] (туда куда будит ставится знак) != (не
равняется) '-'(пустышке). КОД:
#include <iostream>board[9] = {'-', '-',
'-', '-', '-', '-', '-', '-', '-'};//9 элементов ( '-') char, доски
(board)get_move(){::cout<<"Menu hodov:
\n";::cout<<"-7-|-8-|-9-" <<
std::endl;::cout<<"-4-|-5-|-6-" <<
std::endl;::cout<<"-1-|-2-|-3-" <<
std::endl;::cout<<"\n";::cout << "Game board:"
<< std::endl;::cout <<
"-"<<board[6]<<"-|-"<<board[7]<<"-|-"<<board[8]<<"-
\n";//Заменяется переменная стринг (-) на переменную "board[ ]"
с номером клетки::cout <<
"-"<<board[3]<<"-|-"<<board[4]<<"-|-"<<board[5]<<"-
\n";//Переменные начинаются с нуля, поэтому вместо 1 пишется 0, вместо 2
пишется 1 и т.д.::cout << "-"<<board[0]<<"-|-"<<board[1]<<"-|-"<<board[2]<<"-
\n";::cout << "\nVvod chisla: ";move;::cin >> move;(move
> 9 || move < 1 ||board[move-1] != '-' ){ // Добавляется "
||board[move-1] != '-' " т.е. board[move-1] (туда куда будит ставится
знак) != (не равняется) '-' (пустышке)::cout<<"Vvedite chislo ot (1
do 9):\n";::cin >> move;
}move;
}main(){(int i=0; i<9; i++){//Пишется простой
цикл для 9 ходовmove = get_move();::cout << "the move you intereted
is: " << move << std::endl;(i%2 == 0){//Если i по модулю 2
равняется 1, то это чётный ход,[move-1]='X';//то тогда задаётся значение ='X'
}{// Все остальные ходы будут
нечётные,[move-1]='0';//то тогда задаётся значение ='О'
}
}0;
}
5) Создаётся функция void print_board(){ … }
которая будит выводить доску на экран. В фигурные скобки вырезается и
переносится 4 строки:
::cout << "Game board:" <<
std::endl;::cout << "-"<<board[6]<<"-|-"<<board[7]<<"-|-"<<board[8]<<"-
\n";::cout <<
"-"<<board[3]<<"-|-"<<board[4]<<"-|-"<<board[5]<<"-
\n";::cout <<
"-"<<board[0]<<"-|-"<<board[1]<<"-|-"<<board[2]<<"-
\n";
И заменяется эти выводы, т.е. место от куда их
вырезали, выводом print_board(). В main прописывается вывод сообщения "the
final board layout is: \n" в окне консоли "средством"
std::cout<< и ниже пишется строка print_board() т.е. используется функция
чтобы ещё раз напечатать доску(board). Создаётся функцияclearscreen() для очистки
экрана консоли, для этого заводится цикл for(int i = 0; i<100; i++) который
отсчитывает от 0 до 100 и при каждом повторении цикла выводит на экран
std::cout<<std::endl; новую строчку. Теперь функция clearscreen() в main
ставится в цикл. Создаётся функция void clearboard()которая очищает доску.
Далее для этого заводится циклfor(int i = 0; i<9; i++)) который в цикле
проходит по всем 9-и ячейкам на доске. board[i] поставит туда пустышку = '-‘.
Это возвращает доску в своё изначальное состояние. Для этого она
устанавливается в начале main. Остаётся char board[9] пустой массив {} потому,
что есть функция clearboard() которая очистит доску когда запустится main.
КОД:
#include <iostream>board[9] = {};//
Остаётся пустой массив потому, что есть функция void clearboard()(почистить
доску) которая очистит доску когда запустится mainclearscreen(){// Очищает окно
консоли, функция clearscreen ни чего не возвращает(int i = 0; i<100; i++){//
Цикл for который отсчитывает от 0 до 100 и при каждом повторении цикла::cout<<std::endl;//
цикла выводит на экран новую строчку
}
}clearboard(){//эта функция очищает доску и ни
чего не возвращает(int i = 0; i<9; i++){// для этого заводится цикл for (
for(int i = 0; i<9; i++) ) который в цикле проходит по всем 9-и ячейкам на
доске[i] = '-';// и board[i] поставит туда пустышку = '-‘
}
}print_board(){//В созданную функцию void
print_board(){}::cout <<
"-"<<board[6]<<"-|-"<<board[7]<<"-|-"<<board[8]<<"-
\n";// переносится 4 строки:::cout << "-"<<board[3]<<"-|-"<<board[4]<<"-|-"<<board[5]<<"-
\n";//::cout <<
"-"<<board[0]<<"-|-"<<board[1]<<"-|-"<<board[2]<<"-
\n";//
}get_move(){::cout<<"\nMenu hodov:
\n";::cout<<"-7-|-8-|-9-" <<
std::endl;::cout<<"-4-|-5-|-6-" <<
std::endl;::cout<<"-1-|-2-|-3-" <<
std::endl;::cout<<"\n";_board();//и заменяются эти выводы
print_board()::cout << "\nVvod chisla: ";move;::cin >>
move;(move > 9 || move < 1 || board[move-1]!=
'-'){::cout<<"Vvedite chislo ot (1 do 9):\n";::cin >>
move;
}move;
}main(){();// Это возвращает доску в своё
изначальное состояние, для этого она устанавливается в начале main(int i=0;
i<9; i++){();// функция clearscreen() в main ставится в циклmove =
get_move();::cout << "the move you intereted is: " <<
move << std::endl;(i%2 == 0){[move-1]='x';
}{[move-1]='0';
}
}::cout << "the final board layout
is: \n"// Прописывается вывод сообщения "the final board layout
is:"_board();//Используется функция чтобы ещё раз напечатать
доску(board)0;
)Создаётся функция bool has_wonQ(char
player)которая проверяет когда игра закончилась. Функция has_wonQ возвращает
bool(правда или ложь, т.е. bool это переменная с двумя состояниями либо 0(ноль)
если состояние ложь и либо 1(единица) если состояние правда) и передаётся знак
(char player)игрока которого проверяем. Ниже создаётся двухмерный массив
wins[8][3](8 по 3) в котором перечисляются все выигрышные варианты и пишется
рядом/ниже с доской(функцией которая очищает доску). Далее/ниже заводится цикл
for который повторяется 8 раз (int i = 0; i<8; i++)и в этом цикле
запускается ещё цикл for который повторяется 3 раза (int j = 0; j<3; j++).
Этими циклами проверяется если у одного из игроков есть фишки на всех трёх
местах из какой-нибудь из тройки. К примеру если один из игроков первым
поставил крестики или нолики в клетках 1, 2, 3 (т.к. переменные отсчитываются с
0(ноля) тогда эквивалент клеток 1, 2, 3 в окне консоли в коде {0,1,2} ) то он
выиграл. После/ниже первого цикла for [i] прописывается переменнаяint
счётчикcount и задаётся ей значение =0. Грубо говоря цикл for(int i = 0;
i<8; i++)проверяет массив[8], а цикл for(int j = 0; j<3; j++) проверяет
массив [3]. Далее: Ifесли(на boardдоске на квадратике который задан в
массиве[wins]по элементу[i] и [j] будит ровняться player (проверяемого X или О
(char player)) Если на этом месте в массиве доска стоит X то увеличивается
count на единицу ++. В конце цикла говорится Ifесли(счётчикcount ровняется== 3)
т.е. к примеру проходится троечка {0,1,2} и все три ровняются крестику(Х) или
нолику(О) то возвращаетсяreturn правдаtrue(он выиграл), а если это не произошло
то возвращаетсяreturn ложьfalse(он не выиграл). В int main создаётся переменная
turn(ход) типа int изначально будит первой ход и ровняться= 0. Ниже вместо
цикла for пишется цикл while(не! выиграл пользовательhas_wonQ играющий
иксом(X)('x') и&& не! выиграл пользовательhas_wonQ играющий
ноликом(О)('О')) то выполняется код ниже. В if(i%2 == 0) заменяется i на
turn(вход). В конце цикла говорится turn(ход) на единицу++
КОД:
#include <iostream>board[9] =
{};clearscreen(){// очищает окно консоли, функция clearscreen ни чего не возвращает.(int
i = 0; i<100; i++){::cout<<std::endl;
}
}clearboard(){//эта функция очищает доску и ни
чего не возвращает(int i = 0; i<9; i++){[i] = '-';
}
}has_wonQ(char player){ //wins[8][3] {{0,1,2},
{3,4,5}, {6,7,8}, {0,3,6}, {1,4,7}, {2,5,8}, {0,4,8}, {2,4,6}};(int i = 0;
i<8; i++){count =0;(int j = 0; j<3; j++){(board[wins][i][j]] ==
player)++;
}(count = 3){true;
}
}false;
}get_move(){::cout<<"\nMenu hodov:
\n";::cout<<"-7-|-8-|-9-" <<
std::endl;::cout<<"-4-|-5-|-6-" <<
std::endl;::cout<<"-1-|-2-|-3-" << std::endl;::cout<<"\n";_board();::cout
<< "\nVvod chisla: ";move;::cin >> move;(move > 9 ||
move < 1 || board[move-1]!= '-'){::cout<<"Vvedite chislo ot (1 do
9):\n";::cin >> move;
}move;
}main(){();turn = 0;(!has_wonQ('x') &&
!has_wonQ('0')){();move = get_move();::cout << "the move you
intereted is: " << move << std::endl;(turn%2 ==
0){[move-1]='x';
}{[move-1]='0';
}++;
}::cout << "the final board layout
is: \n";_board();
}
) Главная функция вынимается из main и
переносится выше. Создаётся функция play_and_get_winner() она будит возвращать
char(символ) т.е. сыграть в игру и получить выигравшего. После выбора Х или О
говорится ifесли(has_wonQ('X')пользователь играющий за 'X' если он выиграл, то
печатается поздравление "X,Pozdravlyau vi vuigrali!" и возвращаетreturn
из функции'X' что пользователь играющий 'X' выиграл. Тоже самое прописывается
для пользователя играющего ‘O’. Далее turnход ++увеличивается ifесли(turnвход
==ровняется 10). Ecли ввод равен 10, то НЕЧЬЯ. T.е. ставить крестик или нолик
некуда тогда выводится на экран сообщение "nechya" и операторreturn
возвращает значение D. Пишется чтобы функция print_board принимала стринг под
названием индент, void print_board(std::string indent){}. Находится ниже
print_board() и в скобках пишется пустой стринг (два двоеточие)
print_board(""), а в функции main талб\t print_board("\t
"). В главной функции main прописывается выполнение
play_and_get_winner()(главный цикл)и дать char winner(выигравший). char winner
ровняется= play_and_get_winner()
#include <iostream>board[9] =
{};clearscreen(){//Очищает окно консоли, функция clearscreen ни чего не
возвращает(int i = 0; i<100; i++){::cout<<std::endl;
}
}clearboard(){//Функция очищает доску и ни чего
не возвращает(int i = 0; i<9; i++){[i] = '-';
}
}has_wonQ(char player){wins[][3] = {{0,1,2},
{3,4,5}, {6,7,8}, {0,3,6}, {1,4,7},
{2,5,8}, {0,4,8}, {2,4,6}};(int i = 0; i<8;
i++){count = 0;(int j = 0; j<3; j++){(board[wins[i][j]] == player)++;
}(count == 3){true;
}
}false;
}print_board(std::string indent){::cout <<
"Game board:" <<
std::endl;::cout<<indent<<"-"<<board[6]<<"-|-"<<board[7]<<"-|-"<<board[8]<<"-
\n";::cout<<indent<<"-"<<board[3]<<"-|-"<<board[4]<<"-|-"<<board[5]<<"-
\n";::cout<<indent<<"-"<<board[0]<<"-|-"<<board[1]<<"-|-"<<board[2]<<"-
\n";
}get_move(){::cout<<"\nMenu hodov:
\n";::cout<<"-7-|-8-|-9-" <<
std::endl;::cout<<"-4-|-5-|-6-" <<
std::endl;::cout<<"-1-|-2-|-3-" <<
std::endl;::cout<<"\n";_board("");::cout <<
"\nVvod chisla: ";move;::cin >> move;(move > 9 || move <
1 || board[move-1]!= '-'){(move > 9 || move < 1 board[move-1]!= '-'
std::cout<<"Vvedite chislo ot (1 do 9):\n";::cin >> move;
}move;
}play_and_get_winner(){//Функция получить
выигравшегоturn = 1;(!has_wonQ('X') && !has_wonQ('0')){();move =
get_move();// Ввод::cout << "the final board layout is: \n"; //
Печатается вход(turn%2 == 1){// Выбор Х или
О[move-1]='X';(has_wonQ('X')){::cout <<"X,Pozdravlyau vi
vuigrali!\n";'X';
}{[move-1]='0';(has_wonQ('0')){::cout
<<"Y,Pozdravlyau vi vuigrali!\n";'0';
}++;(turn == 10){::cout <<
"nechya\n";'D';
}
}
}main(){();::cout << "the final board
layout is: \n";winner = play_and_get_winner();_board("\t ")
}
) В функции main первой строкой пишется строка
для вывода приветственное сообщения "Privetstvuyu" средством
std::cout и оператором <<, и ниже продекларировать стринг reply(ответ).
reply(ответ) по началу "y"(то бишь ДА(YES)).Строится цикл while пока
ответ положительный, т.е. пока ответ ==ровняется "y". Пишится
перечень переменных типаint x_wins=0(это количество раз когда пользователь
играющий иксами выиграл), o_wins=0(это количество раз когда пользователь
играющий ноликами выиграл), ties=0(количество нечьих)и всем присвоенно нулевое
значение. Пишется switch(это конструкция "если, то" при разных
значениях ((winner)выигравший) будут выполнятся разные куски кода). Первое
значениеcase 'X', если выграл пользователь играющий иксами тогда переменная
x_wins увеличивается на единицу++ и останавливается break. Второеое
значениеcase 'О', если выграл пользователь играющий ноликами тогда
переменнаяо_wins увеличивается на единицу++ и останавливается break. Третье
значениеcase 'D', если нечья тогда переменнаяties увеличивается на единицу++ и
останавливается break. Прописывается статистика,выводится статистика на экран/в
окно консоли с помощью std::cout <<
"Winer statistic\nPlayer X: " <<
x_wins, это сколько раз пользователь играющий Х выиграл, "Player 0:
"<<o_wins << " and Ties: "<<ties<<"
это сколько раз пользователь играющий О выиграл. Сколько нечьих,
"would you like to play again? (y/n):"
задаётся вопрос: "желаете продолжить игру?", а с помощью объекта cin
пользователь может ввести значениеreply(ответ) y, а если пользователь не хочет
играть то нужно ввести n. Далее пишется цикл while(пока значениеreply(ответ)
!=не равно "y" или&& пока значениеreply(ответ) !=не равно
"n") то цикл бесконечен. Следующая строка просит пользователя ввести
ещё значение,если до этого небыло введино y или n. Следующая строка с помощью
объекта cin выводит на экран введённое пользователем значение и опять
проверяется в цикле.
КОД:
консольный программа интерфейс
компьютерный
#include <iostream>board[9] =
{};clearscreen(){//Очищает окно консоли, функция clearscreen ни чего не
возвращает(int i = 0; i<100; i++){::cout<<std::endl;
}
}clearboard(){//эта функция очищает доску и ни
чего не возвращает(int i = 0; i<9; i++){[i] = '-';
}
}has_wonQ(char player){wins[][3] = {{0,1,2},
{3,4,5}, {6,7,8}, {0,3,6}, {1,4,7},
{2,5,8}, {0,4,8}, {2,4,6}};(int i = 0; i<8;
i++){count = 0;(int j = 0; j<3; j++){(board[wins[i][j]] == player)++;
}(count == 3){true;
}
}false;
}print_board(std::string indent){::cout <<
"Game board:" <<
std::endl;::cout<<indent<<"-"<<board[6]<<"-|-"<<board[7]<<"-|-"<<board[8]<<"-
\n";::cout<<indent<<"-"<<board[3]<<"-|-"<<board[4]<<"-|-"<<board[5]<<"-
\n";::cout<<indent<<"-"<<board[0]<<"-|-"<<board[1]<<"-|-"<<board[2]<<"-
\n";
}get_move(){::cout<<"\nMenu hodov:
\n";::cout<<"-7-|-8-|-9-" <<
std::endl;::cout<<"-4-|-5-|-6-" <<
std::endl;::cout<<"-1-|-2-|-3-" <<
std::endl;::cout<<"\n";_board("");::cout <<
"\nVvod chisla: ";move;::cin >> move;(move > 9 || move <
1 || board[move-1]!= '-'){(move > 9 || move < 1 board[move-1]!= '-'
std::cout<<"Vvedite chislo ot (1 do 9):\n";::cin >> move;
}move;
}play_and_get_winner(){// Функция получить
выигравшегоturn = 1;(!has_wonQ('X') && !has_wonQ('0')){();move = get_move();//
Ввод::cout << "the final board layout is: \n"; // Печатается
вход(turn%2 == 1){// Выбор Х или О[move-1]='X';(has_wonQ('X')){::cout
<<"X,Pozdravlyau vi vuigrali!\n";'X';
}{[move-1]='0';(has_wonQ('0')){::cout
<<"Y,Pozdravlyau vi vuigrali!\n";'0';
}++;(turn == 10){::cout <<
"nechya\n";'D';
}
}
}main(){::cout
<<"Privetstvuyu\n\n";::string reply = "y";(reply ==
"y"){();
//std::cout << "the final board
layout is: \n";winner = play_and_get_winner();_board("\t
");(winner){'X':_wins++;;'0':_wins++;;'D':++;;
}::cout << "\n\t*Winer
statistic*\nPlayer X: " << x_wins
<< ", Player 0: "<<o_wins
<< " and Ties: "<<ties<<"\n\n";::cout
<< "\n would you like to play again? (y/n): ";::cin >>
reply;(reply != "y" && reply !="n"){::cout <<
"please inter a valid reply (y/n):";::cin >> reply;
}
} // Конец play_and_get_winner
}
Крестики нолики 4*4
Изменения с первоначальным вариантом выделены
красным
Код:
#include <iostream>board[16] =
{};clearscreen(){// очищает окно консоли, функция clearscreen ни чего не
возвращае.(int i = 0; i<100; i++){::cout<<std::endl;
}
}clearboard(){//эта функция очищает доску и ни
чего не возвращает(int i = 0; i<17; i++){[i] = '-';
}
}has_wonQ(char player){wins[10][4] = {{0,1,2,3},
{4,5,6,7}, {8,9,10,11}, {12,13,14,15}, {0,4,8,12},{1,5,9,13},
{2,6,10,14}, {3,7,11,15}, {0,5,10,15},
{3,6,9,12}};(int i = 0; i<10; i++){count = 0;(int j = 0; j<4;
j++){(board[wins[i][j]] == player)++;
}(count == 4){true;
}
}false;
}print_board(std::string indent){::cout <<
std::endl;::cout<<indent<<"-"<<board[12]<<"-|-"<<board[13]<<"-|-"<<board[14]<<"-|-"<<board[16]<<"-
\n";::cout<<indent<<"-"<<board[8]<<"-|-"<<board[9]<<"-|-"<<board[10]<<"-|-"<<board[11]<<"-
\n";::cout<<indent<<"-"<<board[4]<<"-|-"<<board[5]<<"-|-"<<board[6]<<"-|-"<<board[7]<<"-
\n";::cout<<indent<<"-"<<board[0]<<"-|-"<<board[1]<<"-|-"<<board[2]<<"-|-"<<board[3]<<"-
\n";
}get_move(){::cout<<"\nMenu hodov:
\n";::cout<<"13-|-14|-15|-16" <<
std::endl;::cout<<"-9-|-10|-11|-12" <<
std::endl;::cout<<"-5-|-6-|-7-|-8-" <<
std::endl;::cout<<"-1-|-2-|-3-|-4-" <<
std::endl;::cout<<"\n";_board("");::cout <<
"\nVvod chisla: ";move;::cin >> move;(move > 16 || move <
1 || board[move-1]!= '-'){ //|| move >= 'A' && move <= 'Z' ||
move >= 'a' && move <= 'z'::cout<<"Vvedite chislo ot
(1 do 16):\n";::cin >> move;
}play_and_get_winner(){turn = 1;(!has_wonQ('X')
&& !has_wonQ('0')){();move = get_move();();(turn%2 ==
1){[move-1]='X';(has_wonQ('X')){::cout <<"X,Pozdravlyau vi
vuigrali!\n";'X';
}
}{[move-1]='0';(has_wonQ('0')){::cout
<<"Y,Pozdravlyau vi vuigrali!\n";'0';
}
}++;(turn == 17){::cout <<
"nechya\n";'D';
}
}
}main(){::cout
<<"Privetstvuyu\n\n";::string reply = "y";x_wins=0,
o_wins=0, ties=0;(reply == "y"){();winner =
play_and_get_winner();_board("\t
");(winner){'X':_wins++;;'0':_wins++;;'D':++;;
}::cout << "\n\t*Winer
statistic*\nPlayer X: " << x_wins
<< ", Player 0: "<<o_wins
<< " and Ties: "<<ties<<"\n\n";::cout
<< "\n would you like to play again? (y/n): ";::cin >>
reply;(reply != "y" && reply !="n"){::cout <<
"please inter a valid reply (y/n):";::cin >> reply;
}
}// конец ваил лупа0;
}
Заключение
Перспективы: Первое это проработать алгаритм что
бы при вводе символа отличного от 1-16 программа не завершалась ошибкой. Сейчас
либо крестики либо нолики ставятся либо на чётные либо нечётные число-клетке(настраивается
в коде). А так не интересно, поэтому в поиске чтобы пользователь мог стовить в
любой клетке любой символ т.е. крестик или нолик. Второе сделать код этой
программы что пользователь играл с компьютером, как сделать или по средством
случайных чисел компьютер отвечал на ход пользователя или искуственный
интелект. Третье это создпние сетевого приложения.
Список рекомендуемой литературы:
1. Начальный курс С и С++.: Учебник.
/Б. И. Березин. Москва:"ДИАЛОГ-МИФИ",1999г.
2. Язык программирования С++. :
Учебник. /. Страуструп. Киев:"ДиаСофт", 1993 г.
. Введение в язык С++: Учебник. /
Бьярн Страустрап.- СПб.: 1995.
4. Структуры и алгоритмы обработки
данных: Учебник. / Матьяш В.А., Путилов В.А., Фильчаков В.В. , Щёкин С.В. -
Апатиты, КФ Петр ГУ, 2000
. С++ /Дэвис Стефан Р.,4-е издание :
Пер. с англ.:- М.: Издательский дом "Вильямс",2003
. Основы программирования: Учеб. Для
сред. проф. образования /И.Г.Семакин, А.П.Шестаков. - М., 2006.
. С++ экспресс курс: Учебник.
/Лаптев В.В. - СПб.: БХВ- Петербург 2004.
. С++ учебный курс: Учебник. /Франка
П. - СПб.: Питер 2005.
. МОДЕЛИ И CТРУКТУРЫ ДАННЫХ:/
Учебное пособие/ Д.Далека, А.С. Деревянко, О.Г.Кравец, Л.Е. Тимановская
-Харьков: ХГПУ, 2000
.Высшая математика для экономистов:
учебник для студентов вузов/Н.Ш.Кремер,3-е издание.-М.:ЮНИТИ-ДАНА,2006