Репетиторские услуги и помощь студентам!
Помощь в написании студенческих учебных работ любого уровня сложности

Тема: Разработка приложения для Windows, представляющего собой компьютерную игру «Морской бой».

  • Вид работы:
    Курсовая работа (п) по теме: Разработка приложения для Windows, представляющего собой компьютерную игру «Морской бой».
  • Предмет:
    Информационное обеспечение, программирование
  • Когда добавили:
    22.09.2010 16:01:15
  • Тип файлов:
    MS WORD
  • Проверка на вирусы:
    Проверено - Антивирус Касперского

Другие экслюзивные материалы по теме

  • Полный текст:
    Оглавление
     
    Введение. 4
    Глава 1. Разработка эскизного и технического проектов программы.. 5
    1.1.   Назначение и область применения. 5
    1.2.   Технические характеристики. 5
    1.2.1.   Постановка задачи. 5
    1.2.2.   Описание алгоритма. 7
    1.2.3.   Организация входных и выходных данных. 9
    1.2.4.   Выбор состава технических и программных средств. 10
    Глава 2.   Разработка рабочего проекта. 11
    2.1.   Разработка программы.. 11
    2.2.   Написание программы.. 16
    2.3.   Спецификация программы.. 18
    2.4.   Текст программы.. 20
    2.5.   Тестирование программы.. 26
    Глава 3.   Внедрение. 27
    3.1.   Условия выполнения программы.. 27
    3.2.   Выполнение программы.. 27
    3.3.   Сообщение оператору. 27
    Заключение. 29
    Список литературы.. 30
    Приложение 1
    Приложение 2
    Введение  

    Разработка приложения для Windows, представляющего собой компьютерную игру «Морской бой».
    Условие задачи:
    Разработать программу, моделирующую игру «Морской бой». На поле 10 на 10 позиций стоят невидимые вражеские корабли: 4 корабля по 1 клетке, 3 корабля по 2 клетки, 2 корабля по 3 клетки, 1 корабль в 4 клетки. Необходимо поразить каждую из клеток кораблей. Два игрока вводят позиции кораблей в виде цифр (1, 2, 3, 4) в соответствующие элементы матрицы, тем самым определяя конфигурацию и положение кораблей. Игроки по очереди «наносят удары» по кораблям противника. Если позиция корабля указана верно, то она помечается крестиком на поле. Предусмотреть вариант игры, когда одним из играющих является ЭВМ.
     
    Глава 1.  Разработка эскизного и технического проектов программы Стандарт ГОСТ 19.404-79[1] устанавливает основные требования к содержанию и оформлению программного документа «Пояснительная записка», входящего в состав документов на стадиях разработки эскизного и технического проектов программы.
     
    1.1. Назначение и область применения  
    Необходимо разработать учебную программу. Область применения: досуг программиста. Поскольку ставится задача разработать приложение для Windows, то использоваться программа может под управлением Windows 9x.
     
    1.2. Технические характеристики 1.2.1.  Постановка задачи  
    Для отображения кораблей на поле будем использовать визуальный компонент TGridString. Расстановка кораблей производится мышью. Игрок, который расставляет корабли, сначала нажимает на клетку, в которой будет начинаться корабль, а потом на клетку, в которой он будет заканчиваться. Корабли расставляются по порядку, т.е. сначала 4-х палубный, затем два 3-х палубных, и т.д. Размер корабля проверяется, и корабль не поставится, если игрок ткнул в клетку, которая дальше или ближе запланированной. Для однопалубных кораблей нужно ткнуть в клетку только один раз.
    При запуске игры нужно сделать выбор, игра происходит против человека или против компьютера. Выбор будет храниться в глобальной переменной на протяжении игры для того, чтобы при смене хода определять, нужно ли визуально сменить поля. При игре против компьютера этого делать не следует.
    После расстановки кораблей первым (левым) игроком происходит расстановка кораблей другим игроком. Если игра идёт против человека, то левое поле скрывается, и правый игрок расставляет корабли. Если же выбран режим игры против компьютера, то компьютер расставляет корабли в случайном порядке. При расстановке кораблей компьютером должны быть соблюдено правило, что корабли не могут находиться в соседних или смежных клетках. Алгоритм расстановки наугад и проверки, может ли он там стоять – не самый лучший, т.к. если изменятся условия игры и надо будет поставить больше кораблей, может возникнуть ситуация, когда корабль может встать всего в одну точку, может потребоваться продолжительное время, пока компьютер случайным образом попадёт в эту точку. Алгоритм расстановки в игре следует реализовать следующим образом: для каждого корабля происходит перебор координат и проверка, может ли он встать в этой точке. Если может, то координаты той точки сохраняются. После просмотра всех точек поля случайным образом выбирается одна из сохранённых координат. С каждым следующим кораблём количество мест, в которые он может встать, будет уменьшаться.
    После расстановки кораблей случайным образом происходит выбор того, кто будет первым стрелять. В случае попадания игрок ходит ещё раз, в случае промаха происходит смена стреляющего. При игре против человека следует сделать двухсекундную паузу, чтобы первый игрок успел отвернуться, после чего показываются поля для другого игрока. В случае игры против компьютера, поля показывать не надо.
    После того, как первый игрок промахнулся, ход переходит к другому игроку. Для игры с компьютером добавим невизуальный компонент TTimer, который будет проверять каждые несколько секунд, можно ли стрелять. Если можно – будет произведён выстрел по полю первого игрока.
    Для отображения полей нам понадобится хранить реальное расположение кораблей и координаты промахов и попаданий для каждого игрока. После каждого выстрела нужно проверить, есть ли ещё неподбитые корабли. Если все корабли подбиты – выводится сообщение о выигрыше.
     
    1.2.2.  Описание алгоритма  
    При запуске игры программа просит выбрать противника и сохраняет выбор пользователя в глобальной переменной pcopponent. Элементы формы выбора противника скрываются и показывается второе поле.
    Первый игрок расставляет свои корабли. Глобальная переменная ведёт подсчёт расставленных кораблей. Когда количество кораблей станет равно 10, настанет очередь второго игрока расставлять корабли. Если была выбрана игра против компьютера, то корабли расставятся случайным образом. В случае игры против человека, поле первого игрока с расставленными кораблями будет скрыто, и второй игрок получит возможность расставить корабли на своё усмотрение. По окончании расстановки кораблей вторым игроком выбирается игрок, который будет ходить первым.
    Все последующие нажатия на поле будут трактоваться как выстрел. При промахе программа ждёт пару секунд и ход переходит к другому игроку. В случае попадания, проверяется, остались ли у противника ещё корабли. В случае наличия кораблей текущий игрок стреляет ещё раз. Если кораблей нет, значит следует вывести сообщение о победе.
    Обобщенная блок-схема алгоритма игры представлена на рисунке 1.
     
    начало
    Право хода = правый
    Ввод типа противника, установка значений по умолчанию
    Выбор клетки
    Право хода = левый
    Режим = расстановка
     
    Корабли обоих игроков расставлены
    стреляем
    да
    Ставим корабль
    Корабли игрока расставлены
    Оба игрока расставили корабли
    Режим = стрельба
    Выбор первого стреляющего
    Попали
    У противника есть корабли
    Право хода = другой игрок
    Сообщение о выигрыше
    конец
    нет
    да
    да
    да
    да
    нет
    нет
    нет
    нет
    Противник компьютер
    Расставить корабли
    да
    нет

    Рис. 1 Блок-схема алгоритма игры
     
    1.2.3.  Организация входных и выходных данных Входными данными являются: тип соперника и координаты расставленных кораблей.
    Глобальные переменные, используемые в программе и описанные в Unit1, приведены в таблице 1.
    Таблица 1
    Переменная
    Тип
    Описание
    leftfield
    Двумерный массив целого типа, состоящий из двух 10 строк и 10 столбцов
    Хранит реальное расположение кораблей для левого игрока.
    rightField
    Двумерный массив целого типа, состоящий из двух 10 строк и 10 столбцов
    Хранит реальное расположение кораблей для правого игрока.
    leftVisible
    Двумерный массив целого типа, состоящий из двух 10 строк и 10 столбцов
    Хранит открытые правым игроком клетки левого поля
    rightVisible
    Двумерный массив целого типа, состоящий из двух 10 строк и 10 столбцов
    Хранит открытые левым игроком клетки правого поля
    ships
    Массив целого типа, состоящий из 10 элементов
    Хранит конфигурацию кораблей (количество палуб)
    currentship
    Целый
    Текущий расставляемый корабль
    lastrow
    Целый
    Во время расстановки запоминает строку первой палубы
    lastcol
    Целый
    Во время расстановки запоминает столбец первой палубы
    firstpoint
    Логический
    Показывает, была ли поставлена первая палуба корабля
    beginduel
    Логический
    Режим игры: true для начала игры, false для расстановки кораблей
    pcopponent
    Логический
    Противник: true – компьютер, false – человек
    leftshoots
    Логический
    Право хода: true – стреляет левый, false – стреляет правый
    1.2.4.  Выбор состава технических и программных средств  
    Делается вывод о необходимости использования интегральной среды разработки программ Borland C++ Builder. Среда Borland C++ Builder позволяет достаточно быстро разрабатывать приложения для Windows. Технические характеристики компьютера: Pentium 166 МГц и выше; объём оперативной памяти 128 Мб; не меньше 115 Мб на жёстком диске. Дополнительных средств (принтер, сканер и т. д.) не требуется.
    Глава 2. Разработка рабочего проекта 2.1.   Разработка программы  
    Для разработки приложения «Морской бой» используются средства визуального программирования Borland C++ Builder. Проект программы содержит одно окно: Form1. При запуске игры в его правой части содержится форма выбора противника. При выборе противника форма скрывается и вместо неё появляется поле второго игрока. Форма выбора противника представлена на рисунке 3, окно программы после выбора противника – на рисунке 4.
     

    Рис. 3 Форма выбора противника
     
    1 - компонент Label1: TLabel
    Свойства:
    Caption = “Противник”:
    Событий нет.
     
    2 - компонент RadioButton1: TRadioButton
    Свойства:
    Caption = “Компьютер”
    Checked = True
    Событий нет.
     
    3 - компонент RadioButton2: TRadioButton
    Свойства:
    Caption = “Человек”
    Checked = False
    Событий нет.
     
    4 - компонент Button1: TButton
    Свойства:
    Caption = “Начать игру”
    События:
    OnClick = Button1Click – начать игру
     

    Рис. 4 Окно игры – Form1
     
    Компонент Form1 – окно игры
    Свойства:
    Caption = “Морской бой”
    Событий нет.
     
    5 - компонент Timer1: TTimer
    Свойства:
    Enabled = False
    Interval = 2000
    События:
    OnTimer = Timer1Timer – при игре против компьютера – выстрел компьютера, при игре против человека – смена ходящего.
     
    6 - компонент StringGrid1: TStringGrid
    Свойства:
    ColCount = 11
    Ctl3D = False
    DefaultColWidth = 25
    DefaultRowHeight = 25
    Enabled = False
    RowCount = 11
    События:
    OnDrawCell = StringGrid1DrawCell – показывает корабли на поле. Если стреляет левый игрок (leftshoots = true) - показывает полностью открытое поле, если правый – те клетки, куда он стрелял;
    OnSelectCell = StringGrid1SelectCell – в зависимости от режима игры, расставляет корабли или стреляет.
    компонент StringGrid2: TStringGrid
    Свойства:
    ColCount = 11
    Ctl3D = False
    DefaultColWidth = 25
    DefaultRowHeight = 25
    RowCount = 11
    Visible = False
    События:
    OnDrawCell = StringGrid2DrawCell – показывает корабли на поле. Если стреляет правый игрок (leftshoots = false) - показывает полностью открытое поле, если левый – те клетки, куда он стрелял;
    OnSelectCell = StringGrid2SelectCell – в зависимости от режима игры, расставляет корабли или стреляет.
    7 - компонент Panel1: TPanel
    Свойства:
      Width = 305
      Height = 305
    Событий нет.
    компонент Panel2: TPanel
    Свойства:
      Width = 305
      Height = 305
    Событий нет.
     
    8 - компонент StatusBar1: TStatusBar
    Свойства:
      Width = 617
      Panels = <
      item
      Width = 307
      end
      item
      Width = 50
      end>
    Событий нет.
     
     
    2.2.   Написание программы  
    Программную реализацию разработанных алгоритмов содержат обработчики событий.
    После запуска игры следует выбрать противника. При нажатии на кнопку Button1 обрабатывается событие Onclick, которое запоминает тип противника, прячет элементы формы выбора соперника, показывает поле второго игрока и вызывает функцию StartNewGame(), в которой происходит установка значений по умолчанию. Далее программа ожидает клика по левому полю.
    При нажатии мышью на клетку левого поля, StringGrid1, обрабатывается событие OnSelectCell. Если корабли ещё не расставлены, вызывается функция ManualPlacing, которая определяет, пытается ли игрок поставить начало корабля, или его конец, и ставит начало или конец корабля. В случае, если корабли уже расставлены, и идёт дуэль, вызывается функция PlayerShoots(), открывающая данную клетку.
    Каждый раз при отрисовке клетки поля игрока на форме срабатывает событие OnDrawCell, в котором вызывается функция CellColorer, раскрашивающая поля. В зависимости от того, кто сейчас ходит функция раскрашивает одно поле полностью открытым, а на другом – только те места, куда стрелял текущий игрок. Корабли левого игрока раскрашиваются синим цветом, корабли правого – красным. Попадание в корабль отмечается крестиком (на соответствующем цветном фоне), промах отмечается кружочком на белом фоне.
    На форме находится невизуальный компонент Timer1. В начале игры его свойство Enabled установлено в False. Момент включения таймера и его функция зависит от того, против кого мы играем. При игре против компьютера таймер включится после выбора того, кто будет стрелять первым. При игре против человека таймер включится в случае промаха игрока. Функциональность также различается. При игре против компьютера таймер будет проверять, настал ли черёд компьютера стрелять. Если настал – вызывается функция ComputerShoots(), которая стреляет по левому полю. При игре против человека, таймер включится после промаха игрока, подождёт две секунды, чтобы игрок успел отвернуться, после чего сменит поля и выключится.
     
    2.3.   Спецификация программы  
    Исполняемый файл программы «Морской бой» имеет название Seawar.exe. Его работоспособность не зависит от расположения на диске. Наименования файлов входящих в проект и краткая информация об их содержании отображены в таблице 3. 
     
     
    Таблица 3
    Наименование
    Обозначение
    Примечание
    seawar.bpr
    Файл описания проекта
    Содержит текущие установки проекта: настройки компилятора и компоновщика, имена служебных каталогов, условные директивы
    seawar.cpp
    Файл проекта
    Связывает все файлы, из которых состоит приложение, создаёт и запускает приложение
    seawar.obj
    Объектный файл для seawar.cpp
    Откомпилированная версия seawar.cpp
    seawar.res
    Файл ресурсов
    Содержит пиктограммы, графические изображения
    seawar.tds
    Служебная информация
    Содержит отладочную информацию о проекте
    Unit1.cpp
    Файл программного модуля
    Основная функциональность программы
    Unit1.dfm
    Файл описания формы
    Содержит список свойств всех компонентов, включённых в форму Form1
    Unit1.h
    Заголовочный файл формы
    Описание класса TForm1, указание на подключение необходимых файлов
    Unit1.obj
    Объектный файл для Unit1.cpp
    Откомпилированная версия Unit1.cpp
     
    2.4.   Текст программы  
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
     
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    int leftField[10][10], rightField[10][10];
    int leftVisible[10][10], rightVisible[10][10];
    int ships[] = {4, 3, 3, 2, 2, 2, 1, 1, 1, 1};
    int currentship;
    int lastrow, lastcol;
    bool firstpoint;
    bool beginduel;
    bool pcopponent; // противник
    bool leftshoots = TRUE;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    char c;
    int i;
     
    // определимся с противником
    if (RadioButton1->Checked)
      pcopponent = TRUE;
    else
      pcopponent = FALSE;
     
    StringGrid1->Enabled = TRUE;
    // спрячем элементы
    Label1->Visible = FALSE;
    RadioButton1->Visible = FALSE;
    RadioButton2->Visible = FALSE;
    Button1->Visible = FALSE;
    StringGrid2->Visible = TRUE;
     
    // нарисуем координаты
    for (i = 1; i <= 10; i++) {
      StringGrid1->Cells[i][0] = i;
      StringGrid2->Cells[i][0] = i;
      c = i + 96;
      StringGrid1->Cells[0][i] = c;
      StringGrid2->Cells[0][i] = c;
    }
     
    StartNewGame();
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::StartNewGame(void)
    {
    currentship = 1;
    beginduel = FALSE;
    firstpoint = FALSE;
    Timer1->Tag = 0;
     
    int i, j;
     
    // очистим поля
    for (i = 0; i < 10; i++) {
      for (j = 0; j < 10; j++) {
      leftField[i][j] = 0;
      leftVisible[i][j] = 0;
      rightField[i][j] = 0;
      rightVisible[i][j] = 0;
      }
    }
     
    StatusBar1->Panels->Items[0]->Text = "Левый игрок располагает корабли";
    // дальше обрабатывается в зависимости от нажатий
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::StringGrid1SelectCell(TObject *Sender, int ACol,
      int ARow, bool &CanSelect)
    {
     
    if (beginduel == FALSE) { // значит пока что расставляем корабли
      ManualPlacing(Sender, ACol, ARow);
    } else { // значит стреляем
      if (leftshoots == FALSE) { // на всякий случай проверим, его ли ход
      PlayerShoots(Sender, ACol, ARow);
      }
    }
    StringGrid1->Refresh();
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::StringGrid2SelectCell(TObject *Sender, int ACol,
      int ARow, bool &CanSelect)
    {
     
    if (beginduel == FALSE) { // значит пока что расставляем корабли
      ManualPlacing(Sender, ACol, ARow);
    } else { // значит стреляем
      if (leftshoots == TRUE) { // на всякий случай проверим, его ли ход
      PlayerShoots(Sender, ACol, ARow);
      }
    }
    StringGrid2->Refresh();
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::ManualPlacing(TObject *Sender, int ACol, int ARow)
    {
    TStringGrid* currentGrid = (TStringGrid*)Sender;
    int (*playerField)[10];
    if (((TStringGrid*)Sender)->Name == "StringGrid1") {
      playerField = leftField;
    } else {
      playerField = rightField;
    }
     
    int shipsize = ships[currentship - 1];
    int direction = -1; // всего четыре направления
    int currentrow, currentcol;
    int i;
     
      // продолжаем расставлять корабли только в том случае, если есть ещё
      if (currentship <= 10) {
      // расставляем кораблики
      if (firstpoint == FALSE || shipsize == 1) { //значит это будет первая точка
      playerField[ARow - 1][ACol - 1] = currentship;
      lastrow = ARow;
     lastcol = ACol;
     
      if (shipsize == 1)
      currentship++;
      else
      firstpoint = TRUE;
     
      currentGrid->Refresh();
      } else { // тогда ставим хвост корабля
      // определим конкретное направление
      if (ARow - lastrow == shipsize-1 && lastcol == ACol) // вверх
      direction = 0;
      else if (lastrow - ARow == shipsize-1 && lastcol == ACol) // вниз
      direction = 1;
      else if (lastcol - ACol == shipsize-1 && lastrow == ARow) // вправо
      direction = 2;
      else if (ACol - lastcol == shipsize-1 && lastrow == ARow) // влево
      direction = 3;
     
     
      // если направление удовлетворяет
      if (direction != -1) {
     
      currentrow = ARow - 1;
      currentcol = ACol - 1;
      shipsize = 0;
      // заполним всё пространство между концом и началом
      while (shipsize != ships[currentship - 1] - 1) {
      playerField[currentrow][currentcol] = currentship;
     
      if (direction == 0) // вверх
      currentrow--;
      else if (direction == 1) // вниз
      currentrow++;
      else if (direction == 2) // вправо
      currentcol++;
      else // влево
      currentcol--;
     
      shipsize++;
      }
     
     
      currentship++;
      firstpoint = FALSE;
      currentGrid->Refresh();
      }
      }
     
      if (currentship > 10 && leftshoots == TRUE)
      NextPlayerSetsCoordinates();
      if (currentship > 10 && leftshoots == FALSE)
      WhoIsFirst();
      } // if (currentship <= 10)
     
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TForm1::NextPlayerSetsCoordinates(void)
    {
    /* правый игрок располагает корабли */
     
    currentship = 1; // начали отсчёт кораблей заново
    leftshoots = FALSE; // ходит правый
     
    // спрячем левое поле если человек
    if (pcopponent == FALSE)
      StringGrid1->Refresh();
     
    StatusBar1->Panels->Items[0]->Text = "";
    StatusBar1->Panels->Items[1]->Text = "Правый игрок располагает корабли";
     
     
    if (pcopponent)
      RandomCoordinates();
    // иначе расставляет человек
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::RandomCoordinates(void)
    {
    int i, j, s;
    int shipsize; // нужен при переборе
    int direction; // направление, 0 - горизонталь, 1 - вертикаль
    int goodpositions[100];
    int goodposcounter = 0;
    int currentline, currentrow;
    bool good;
    currentship = 1;
     
    // десять кораблей
    for (s = 0; s < 10; s++) {
      shipsize = ships[s];
      goodposcounter = 0;
      // выбираем направление
      randomize();
      direction = random(2); // 0 или 1
      // собираем места, куда можем поставить
      // для этого обходим каждую клетку поля
      for (i = 0; i < 10; i++) {
      for (j = 0; j < 10; j++) {
      // и проверяем, помещается ли там корабль или нет
      currentline = i;
      currentrow = j;
      good = TRUE;
      shipsize = ships[s];
      // обходим каждую палубу корабля
      while (shipsize > 0) {
     
      if (currentrow > 9 || currentline > 9) {
      good = FALSE;
      }
      // придётся проверить все 8 сторон
      if (currentline != 0) { // верхний средний
      if (rightField[currentline - 1][currentrow] != 0) {
      good = FALSE;
      }
      }
      if (currentline != 0 && currentrow != 9) { // верхний правый
      if (rightField[currentline - 1][currentrow + 1] != 0) {
      good = FALSE;
      }
      }
      if (currentrow != 9) { // средний правый
      if (rightField[currentline][currentrow + 1] != 0) {
      good = FALSE;
      }
      }
      if (currentline != 9 && currentrow != 9) { // нижний правый
      if (rightField[currentline + 1][currentrow + 1] != 0) {
      good = FALSE;
      }
      }
      if (currentline != 9) { // нижний средний
      if (rightField[currentline + 1][currentrow] != 0) {
      good = FALSE;
     }
      }
      if (currentline != 9 && currentrow != 0) { // нижний левый
      if (rightField[currentline + 1][currentrow - 1] != 0) {
      good = FALSE;
      }
      }
      if (currentrow != 0) { // средний левый
      if (rightField[currentline][currentrow - 1] != 0) {
      good = FALSE;
      }
      }
      if (currentline != 0 && currentrow != 0) { // верхний левый
      if (rightField[currentline - 1][currentrow - 1] != 0) {
      good = FALSE;
      }
      }
     
      if (good == FALSE)
      break;
     
      if (direction == 0)
      currentrow++;
      else
      currentline++;
     
      shipsize--;
      } // while (sizecounter > 0)
     
      if (good == TRUE) {
      goodpositions[goodposcounter] = i*10 + j;
      goodposcounter++;
      }
      } // for j
      } // for i
     
      // выбираем из них одно
      randomize();
      int place = random(goodposcounter); // выбрали место старта
      // теперь поставим корабль
      shipsize = ships[s];
      currentline = (goodpositions[place] - goodpositions[place]%10)/10;
      currentrow = goodpositions[place]%10;
      while (shipsize > 0) {
      rightField[currentline][currentrow] = currentship;
     
      if (direction == 0)
      currentrow++;
      else
      currentline++;
     
      shipsize--;
      }
      currentship++;
    }
     
    // компьютер расставил корабли, решаем, кто ходит первый
    WhoIsFirst();
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::WhoIsFirst(void)
    {
     
    /* выбор, кто ходит первым */
    int randchoice = random(2);
     
    if (randchoice == 0) {
      leftshoots = TRUE;
      StatusBar1->Panels->Items[1]->Text = "";
      StatusBar1->Panels->Items[0]->Text = "Левый игрок ходит";
    }
    else {
      leftshoots = FALSE;
      StatusBar1->Panels->Items[1]->Text = "Правый игрок ходит";
    }
     
    beginduel = TRUE; // игра началась!
     
    if (pcopponent)
      Timer1->Enabled = TRUE;
    // иначе ждём нажатий
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::PlayerShoots(TObject *Sender, int ACol, int ARow)
    {
    int i, j;
    bool killed = TRUE;
    bool win = TRUE;
    int shipnumber;
    int (*opponentField)[10], (*opponentVisible)[10];
    TStatusPanel* playerStatusPanel;
     
    if (((TStringGrid*)Sender)->Name == "StringGrid1") {
      opponentField = leftField;
      opponentVisible = leftVisible;
      playerStatusPanel = StatusBar1->Panels->Items[1];
    } else {
      opponentField = rightField;
      opponentVisible = rightVisible;
      playerStatusPanel = StatusBar1->Panels->Items[0];
    }
     
    shipnumber = opponentField[ARow - 1][ACol - 1];
    if (shipnumber != 0) { // если в этом месте корабль
      opponentVisible[ARow - 1][ACol - 1] = 1;
      // проверяем, попал или убил
      for (i = 0; i < 10; i++)
      for (j = 0; j < 10; j++)
      if (opponentField[i][j] == shipnumber && opponentVisible[i][j] == 0)
     killed = FALSE;
     
      if (killed) {
      playerStatusPanel->Text = "Убил!";
     
      // проверяем, есть ли ещё корабли
      for (i = 0; i < 10; i++)
      for (j = 0; j < 10; j++)
      if (opponentField[i][j] != 0 && opponentVisible[i][j] == 0)
      win = FALSE;
     
      if (beginduel && win) {
      Application->MessageBoxA("Победа!", "", MB_OK);
      StringGrid1->Enabled = false;
      StringGrid2->Enabled = false;
      }
     
      } else
      playerStatusPanel->Text = "Попал!";
    } else {
      opponentVisible[ARow - 1][ACol - 1] = -1;
      playerStatusPanel->Text = "Мимо!";
      if (pcopponent == TRUE) {
      leftshoots = !leftshoots; // смена игрока
      ColorPanels();
      } else {
      Timer1->Enabled = TRUE;
      }
    }
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    if (pcopponent == TRUE) {
      if (leftshoots == FALSE)
      ComputerShoots(); // пли!
    } else {
      if (Timer1->Tag < 2)
      Timer1->Tag++;
      else {
      Timer1->Tag = 0;
      Timer1->Enabled = FALSE;
      leftshoots = !leftshoots; // смена игрока
      ColorPanels();
      }
    }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::ComputerShoots(void)
    {
    int i = random(10);
    int j = random(10);
    if (leftField[i][j] == 0)
      leftVisible[i][j] = -1;
    else
      leftVisible[i][j] = 1;
     
    PlayerShoots(StringGrid1, j+1, i+1);
    StringGrid1->Refresh();
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::ColorPanels(void)
    {
    if (leftshoots == TRUE) {
      Panel1->Color = clNavy;
      Panel2->Color = clBtnFace;
    } else{
      Panel1->Color = clBtnFace;
      Panel2->Color = clNavy;
    }
     
    StringGrid1->Refresh();
    StringGrid2->Refresh();
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::CellColorer(TObject *Sender, int ACol, int ARow, TRect &Rect)
    {
    TColor playerColor, opponentColor;
    TStringGrid* currentGrid = (TStringGrid*)Sender;
    int (*playerField)[10], (*playerVisible)[10], (*opponentVisible)[10], (*opponentField)[10];
     
    if (leftshoots == TRUE) {
      playerField = leftField;
      playerVisible = leftVisible;
      opponentVisible = rightVisible;
      playerColor = clSkyBlue;
      opponentColor = clRed;
    } else {
      playerField = rightField;
      playerVisible = rightVisible;
      opponentVisible = leftVisible;
      playerColor = clRed;
      opponentColor = clSkyBlue;
     
      opponentField = leftField;
    }
     
    // показываем реальное (своё)
    if ((leftshoots && currentGrid->Name == "StringGrid1") ||
      (leftshoots == FALSE && currentGrid->Name == "StringGrid2")) {
      // ^ показываем реальное расположение кораблей для правого поля только если играет человек
      // игрок расставляет корабли или смотрит в игре на свои
      if (playerField[ARow - 1][ACol - 1] != 0 && playerVisible[ARow - 1][ACol - 1] == 0) {
      if ((pcopponent == FALSE || leftshoots == TRUE || currentGrid->Name != "StringGrid2")) {
      // если в этом поле корабль, и в него не стреляли
      currentGrid->Canvas->Brush->Color = playerColor;
      currentGrid->Canvas->FillRect(Rect);
      }
      } else if (playerField[ARow - 1][ACol - 1] != 0 && playerVisible[ARow - 1][ACol - 1] == 1) {
      // если в этом поле корабль, и в него попали
      currentGrid->Canvas->Brush->Color = playerColor;
      currentGrid->Canvas->FillRect(Rect);
      currentGrid->Canvas->TextOut(Rect.Left + 9, Rect.Top + 5, "x");
      } else if (playerField[ARow - 1][ACol - 1] == 0 && playerVisible[ARow - 1][ACol - 1] == -1) {
      // если в этом поле пусто, и в него стреляли и промазали
      currentGrid->Canvas->TextOut(Rect.Left + 9, Rect.Top + 5, "o");
      }
    }
    // показываем видимое (чужое)
    if ((leftshoots && currentGrid->Name == "StringGrid2") ||
      (leftshoots == FALSE && currentGrid->Name == "StringGrid1")) {
     
      if (opponentVisible[ARow - 1][ACol - 1] == 1) {
      currentGrid->Canvas->Brush->Color = opponentColor;
      currentGrid->Canvas->FillRect(Rect);
      currentGrid->Canvas->TextOut(Rect.Left + 9, Rect.Top + 5, "x");
      } else if (opponentVisible[ARow - 1][ACol - 1] == -1) {
      currentGrid->Canvas->TextOut(Rect.Left + 9, Rect.Top + 5, "o");
      } else if (pcopponent == TRUE && leftshoots == FALSE && currentGrid->Name == "StringGrid1" && opponentField[ARow - 1][ACol - 1] != 0) {
      // для игры с компьютером
      currentGrid->Canvas->Brush->Color = opponentColor;
      currentGrid->Canvas->FillRect(Rect);
      }
     
    }
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
    {
    if (ARow > 0 && ACol > 0) {
      CellColorer(Sender, ACol, ARow, Rect);
    }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::StringGrid2DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
    {
    if (ARow > 0 && ACol > 0) {
      CellColorer(Sender, ACol, ARow, Rect);
    }
    }
    //---------------------------------------------------------------------------
    2.5.   Тестирование программы  
    После запуска приложения появляется главное окно программы в центре экрана. Вид программы представлен в приложении 1. Выбираем компьютер в качестве противника и нажимаем кнопку «Начать игру». Появляется поле второго игрока. Расставляем корабли на левом поле. Сначала ставится 4-х палубный корабль: нажимаем на клетку, в которой будет начало корабля, потом на клетку,  в которой будет конец корабля, так чтобы корабль занимал 4 клетки. Подобным образом ставим два 3-х палубных и три 2-х палубных корабля. Однопалубные корабли ставятся одним нажатием.
    Играем с компьютером, нажимая на клетки его поля, когда вокруг поля появляется фиолетовая рамка. Вид окна программы на последнем этапе игры представлен в приложении 1, четвертый рисунок.
    Глава 3. Внедрение В разделе описываются (руководство ГОСТ 19.505-79[2]):
    - Условие выполнения программы;
    - Выполнение программы;
    - Сообщение оператору;
     
    3.1. Условия выполнения программы  
    Данное приложение, разработанное в среде Borland C++ Builder, способно работать на персональных компьютерах с минимальными требованиями Pentium 100, оперативной памятью 32 Мб, операционной средой Windows.
     
    3.2.   Выполнение программы  
    Запустить приложение можно также как и любое другое. Окно приложения загрузится и появится в центре экрана. Для начала игры следует нажать кнопку «Начать игру». Для выхода из программы необходимо нажать Alt+F4 или щелкнуть левой кнопкой мыши по крестику в правом верхнем углу экрана.
     
    3.3.   Сообщение оператору  
    Постоянно на протяжении всей игры в строку состояния выводятся подсказки пользователю. Так, например, в первую панель строки (под левым полем) выводятся сообщения о промахе, попадании или потоплении корабля левым игроком: «Мимо!», «Попал!», «Убил!». Во вторую панель выводятся такие же сообщения для правого игрока.
    Заключение В заключении проведённой разработки игры в рамках курсовой работы можно сделать нижеследующие выводы.
    При разработке небольших логических компьютерных игр для операционной системы Windows следует использовать среды разработки, такие как Borland C++ Builder или Delphi, так как они содержат визуальные компоненты, упрощающие вывод информации и позволяют сосредоточиться на логике работы программы, и не задумываться над визуальной отрисовкой.
    При проектировании игры для нескольких человек, следует определять, какие действия будут выполняться для всех игроков, и при программировании выносить такие действия в отдельные функции, что позволит сократить количество кода и сделать его более понятным. Следует помнить, что при выборе клетки компонента TStringGrid передаётся указатель на StringGrid, который содержит эту клетку. Поэтому в данной курсовой работе нажатия на поле игрока передают  этот указатель в общие для обоих игроков функции установки корабля или стрельбы по кораблю, в которых уже и происходит действие для поля конкретного игрока.
    Несмотря на то, что разработка игры является увлекательным занятием, во время написания приложения следует, по возможности, максимально автоматизировать ввод данных. Во время разработки, данное приложение содержало функцию, которая автоматически расставляло корабли и для левого игрока.
    Список литературы  
    1. Калверт Ч., Рейсдорф К. Borland C++ Builder 5. Энциклопедия программиста. «ДиаСофт», 2001.
    2. В. Ермолаев, Т. Сорока C++ Builder: Книга рецептов. КУДИЦ-Образ, 2006.
    3. А. Я. Архангельский Язык С++ в С++Builder. Бином-Пресс, 2008.
    4. А. Я. Архангельский Компоненты C++Builder. Справочное и методическое пособие. Бином-Пресс, 2008.
     
     
    Приложение 1
    Виды программы, принимаемые во время ее тестирования.
     

     
     


     
     
    Приложение 2
     
    К семестровой курсовой работе прилагаются исходные файлы.
     
    Наименование
    Обозначение
    Размер
    seawar.bpr
    Файл описания проекта
    4,16 Кб
    seawar.cpp
    Файл проекта
    925 байт
    seawar.exe
    Исполняемый файл программы
    649 Кб
    seawar.obj
    Объектный файл для seawar.cpp
    17,2 Кб
    seawar.res
    Файл ресурсов
    876 байт
    seawar.tds
    Служебная информация
    3,12 Мб
    Unit1.cpp
    Файл программного модуля
    16,8 Кб
    Unit1.dfm
    Файл описания формы
    2,50 Кб
    Unit1.h
    Заголовочный файл формы
    2,09 Кб
    Unit1.obj
    Объектный файл для Unit1.cpp
    122 Кб
     
     
    [1] ГОСТ 19.404-79 Установление общих требований к содержанию документации процесса разработки,  МНИЦ, ГНИИ ИТТ, ВНИИ, стандарт принят взамен ГОСТ 19.401-79 до июля 2004г.
    [2] ГОСТ 19.505-79 Установление общих требований к содержанию документации процесса разработки,  МНИЦ, ГНИИ ИТТ, ВНИИ, стандарт принят взамен ГОСТ 19.501-79 до июля 2004г.
Если Вас интересует помощь в НАПИСАНИИ ИМЕННО ВАШЕЙ РАБОТЫ, по индивидуальным требованиям - возможно заказать помощь в разработке по представленной теме - Разработка приложения для Windows, представляющего собой компьютерную игру «Морской бой». ... либо схожей. На наши услуги уже будут распространяться бесплатные доработки и сопровождение до защиты в ВУЗе. И само собой разумеется, ваша работа в обязательном порядке будет проверятся на плагиат и гарантированно раннее не публиковаться. Для заказа или оценки стоимости индивидуальной работы пройдите по ссылке и оформите бланк заказа.