Сапер
Обновлено
2
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ УКРАИНЫ
ХАРЬКОВСКИЙ НАЦИОНАЛЬНЫЙ УНИВЕРСИТЕТ
РАДИОЭЛЕКТРОНИКИ
Кафедра искусственного интеллекта
Пояснительная записка
К курсовой работе по дисциплине:
"Объектно-ориентированное программирование"
Тема:
"Сапер"
Выполнил:
ст. гр.
Проверил:
Комиссия:
Работа защищена с оценкой:
Харьков 2007
РЕФЕРАТ
Пояснительная записка к курсовой работе содержит: 46 стр., 5 рисунков
Предмет исследования - современные методы разработки программ таких, как объектно-ориентированное программирование и визуальное проектирование, а также структурное и модульное программирование.
Цель курсовой работы - систематизация, углубление и активное применение знаний по системному программированию, закрепление знаний, полученных в лекционном курсе, а также на практических и лабораторных занятиях.
Метод исследования - изучение литературы, составление и отладка программ на компьютере.
Данная программа используется для интересного проведения времени за игрой, которая требует развитого логического мышления. Разработан проект "Сапер" соответствующий условию задания и имеющий удобный интерфейс.
Программа разработана в среде Visual studio 2005.
КЛЮЧЕВЫЕ СЛОВА: VISUAL, ФУНКЦИЯ, ПРОЕКТ, ПРОГРАММА, САПЕР, БОМБА, ЯЧЕЙКА
СОДЕРЖАНИЕ
- ВВЕДЕНИЕ 4
- 1. АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ 6
- 2. ПОСТАНОВКА ЗАДАЧИ 6
- 3 ПРОЕКТИРОВАНИЕ СИСТЕМЫ 9
- 4. ПРОГРАММНАЯ РЕАЛИЗАЦИЯ 11
- ВЫВОДЫ 11
- ПЕРЕЧЕНЬ ССЫЛОК 12
- ПРИЛОЖЕНИя 13
13
ПРИЛОЖЕНИяПриложение 1
ДИАГРАММА КЛАССОВ
ПРИЛОЖЕНИЕ 2.
ТЕКСТ ПРОГРАММЫ
Mycell. h
#ifndef MYCELL_H_
#define MYCELL_H_
// defines...
// задаем константы
#define CLOSED 0
#define OPENED 1
#define BLOCK 2
#define SIZE 20
#define WITH_BOMB 0
#define WITHOUT_BOMB 1
// events
#define REDRAW 0x00000001
#define GAMEOVER 0x00000010
#define OPEN_NULL_VALUES 0x00000100
#define WINNER 0x00001000
class CMyCell // базовый класс для ячейки
{
public:
CMyCell(int x = 0, int y = 0, int state = CLOSED); // координаты ячейки, начальное значение - закрытая ячейка
CMyCell(const CMyCell & copy);
~CMyCell();
// задаем координаты ячейки
int GetX() const;
int GetY() const;
int GetState() const;
// устанавливаем значение координат ячейки
void SetX(int x);
void SetY(int y);
void SetState(int state);
// Рисует закрытую ячейку
void DrawClosedCell(CDC * dc);
// Рисует заблокированую ячейку
void DrawBlockedCell(CDC * dc);
// Попадает ли точка, указанная в параметре, в область этой ячейки
bool HitToPoint(const CPoint & point);
// Рисует ячейку
virtual void Draw(CDC * dc) = 0;
// Выполняет действия при щелчке на эту ячейку
virtual int Click(CDC * dc) = 0;
// Возвращает, есть ли тут бомба.
// Необходимо для инициализации поля
virtual bool isBomb() const = 0;
// частные переменные в классе
private:
int cellX;
int cellY;
int cellState;
};
// Класс - указатель(умный указатель) на класс CMyCell
class CPMyCell
{
public:
CPMyCell();
CPMyCell(CMyCell * pMyCell);
void SetPointer(CMyCell * pMyCell);
CMyCell * GetPointer() const;
void Destroy();
operator CMyCell*();
CMyCell * operator->();
private:
CMyCell * pCell;
};
#endif
Mycell. cpp
// mycell. cpp
// Реализация класса CMyCell, т.е. класса ячейка
#include "stdafx. h"
#include "mycell. h"
CMyCell:: CMyCell(int x, int y, int state)
: cellX(x), cellY(y), cellState(state) // доступ к переменным
{
// cellX = x;
// cellY = y;
// cellState = state;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCell:: CMyCell(const CMyCell & copy)
: cellX(copy. GetX()), cellY(copy. GetY()), cellState(copy. GetState()) // копирующий уонструктор
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCell:: ~CMyCell() // деструктор
{
}
int CMyCell:: GetX() const
{
return cellX; // возвращает значение x
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int CMyCell:: GetY() const
{
return cellY; // возвращает значение у
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int CMyCell:: GetState() const
{
return cellState; // возвращает значение позиции
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CMyCell:: SetX(int x) // проверка на то, чтоб координата х была больше нуля
{
if (x >= 0)
cellX = x;
else
cellX = 0; // error
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CMyCell:: SetY(int y) // проверка на то, чтоб координата у была больше нуля
{
if (y >= 0)
cellY = y;
else
cellY = 0; // error
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CMyCell:: SetState(int state) // проверка на то, чтоб значение позиции было больше нуля
{
if (state >= 0)
cellState = state;
else
cellState = 0; // error
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
bool CMyCell:: HitToPoint(const CPoint & point) // создание ячейки
// проверка положения ячейки
{ if ((point. x > 10 + GetY() * (SIZE + 2)) && (point. x < 10 + GetY() * (SIZE + 2) + SIZE) &&
(point. y > 10 + GetX() * (SIZE + 2)) && (point. y < 10 + GetX() * (SIZE + 2) + SIZE))
return true;
return false;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CMyCell:: DrawClosedCell(CDC * dc) // прорисовка закрытой ячейки
{
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CBrush brush(RGB(204, 204, 204));
CPen * oldPen = dc->SelectObject(&pen);
CBrush * oldBrush = dc->SelectObject(&brush);
dc->Rectangle(10 + GetY() * (SIZE + 2), 10 + GetX() * (SIZE + 2),
10 + GetY() * (SIZE + 2) + SIZE, 10 + GetX() * (SIZE + 2) + SIZE);
dc->SelectObject(oldBrush);
dc->SelectObject(oldPen);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CMyCell:: DrawBlockedCell(CDC * dc) // прорисовка заблокированной ячейки
{
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CBrush brush(RGB(204, 204, 204));
// CPen penBlock(PS_SOLID, 4, RGB(0, 0, 0));
CPen * oldPen = dc->SelectObject(&pen);
CBrush * oldBrush = dc->SelectObject(&brush);
dc->Rectangle(10 + GetY() * (SIZE + 2), 10 + GetX() * (SIZE + 2),
10 + GetY() * (SIZE + 2) + SIZE, 10 + GetX() * (SIZE + 2) + SIZE);
// CPen * oldBlockPen = dc->SelectObject(&penBlock);
dc->TextOutA(10 + GetY() * (SIZE + 2) + 6, 10 + GetX() * (SIZE + 2) + 3, "B", 1); // обозначение флажка
// dc->SelectObject(oldBlockPen);
dc->SelectObject(oldBrush); // указатель на обьект ячейки
dc->SelectObject(oldPen);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
// Реализация класса CPMyCell // // // // // // // // // // // // // // // // // /
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CPMyCell:: CPMyCell()
: pCell (NULL) // конструктор по умолчанию
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CPMyCell:: CPMyCell(CMyCell * pMyCell)
: pCell (pMyCell)
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CPMyCell:: SetPointer(CMyCell * pMyCell)
{
pCell = pMyCell; // конструктор копирования, установка указателя
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCell * CPMyCell:: GetPointer() const
{
return pCell; // взятие указателя
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CPMyCell:: Destroy() // удаление ячейки
{
if (pCell! = NULL)
delete pCell;
pCell = NULL;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CPMyCell:: operator CMyCell *()
{
return pCell;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCell * CPMyCell:: operator - >()
{
return pCell;
}
Mycellbomb. h
#ifndef MYCELL_BOMB_H_
#define MYCELL_BOMB_H_
#include "mycell. h"
class CMyCellBomb: public CMyCell // ячейка с бомбой
{
public:
CMyCellBomb(int x = 0, int y = 0, int state = CLOSED); // задаем координаты ячейки с бомбо. изначальный вид - ячейка закрыта
CMyCellBomb(const CMyCellBomb & copy); // конструктор копирования
~CMyCellBomb();
// Рисует ячейку
virtual void Draw(CDC * dc);
// Выполняет действия при щелчке на эту ячейку
virtual int Click(CDC * dc);
// Возвращает значение, по которому определяется, есть ли тут бомба.
// Необходимо для инициализации поля
virtual bool isBomb() const;
};
#endif
Mycellbomb. cpp
// mycellbomb. cpp
// Реализация класса CMyCellBomb, т.е. ячейки с бомбой
#include "stdafx. h"
#include "mycellbomb. h"
CMyCellBomb:: CMyCellBomb(int x, int y, int state)
: CMyCell(x, y, state) // устанавливаем координаты ячейки, конструктор по умолчанию
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCellBomb:: CMyCellBomb(const CMyCellBomb & copy)
: CMyCell(copy) // конструктор копирования
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCellBomb:: ~CMyCellBomb() // деструктор
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CMyCellBomb:: Draw(CDC * dc) // рисуем бомбы
{
if (GetState() == CLOSED) // если закрыто, то рисуем закрытую ячейку
CMyCell:: DrawClosedCell(dc);
else if (GetState() == BLOCK) // если стоит флажок, то рисуем флажок
CMyCell:: DrawBlockedCell(dc);
else
// рисуем бомбы
{
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CBrush brush(RGB(255, 0, 0));
CBrush brushCircle(RGB(0, 0, 0));
CPen * oldPen = dc->SelectObject(&pen);
CBrush * oldBrush = dc->SelectObject(&brush);
dc->Rectangle(10 + GetY() * (SIZE + 2), 10 + GetX() * (SIZE + 2),
10 + GetY() * (SIZE + 2) + SIZE, 10 + GetX() * (SIZE + 2) + SIZE);
CBrush * oldBrushCircle = dc->SelectObject(&brushCircle);
dc->Ellipse(10 + GetY() * (SIZE + 2) + 4, 10 + GetX() * (SIZE + 2) + 4,
10 + GetY() * (SIZE + 2) + SIZE - 4, 10 + GetX() * (SIZE + 2) + SIZE - 4);
dc->SelectObject(oldBrushCircle);
dc->SelectObject(oldBrush);
dc->SelectObject(oldPen);
}
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int CMyCellBomb:: Click(CDC * dc) // проверка на щелчок
if (GetState() == BLOCK) // если стоит флажок, то ячейка не откроется при нажатии
return 0;
SetState(OPENED); // открытие ячейки
Draw(dc);
return REDRAW
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
bool CMyCellBomb:: isBomb() const // есть ли это бомба
{
return true;
}
Mycellwob. h
#ifndef MYCELL_WOB_H_
#define MYCELL_WOB_H_
#include "mycell. h"
class CMyCellWob: public CMyCell // ячейка без бомбы
{
public:
CMyCellWob(int x = 0, int y = 0, int state = CLOSED, int val = 0); // задаем координаты ячейки и значение. начальное положение - закрытая ячейка
CMyCellWob(const CMyCellWob & copy); // копирующий конструктор
~CMyCellWob(); // деструктор
int GetValue() const; // передаем значения
void SetValue(int val);
// Рисует ячейку
virtual void Draw(CDC * dc);
// Выполняет действия при щелчке на эту ячейку
virtual int Click(CDC * dc);
// Возвращает значение, по которому определяется, есть ли тут бомба.
// Необходимо для инициализации поля
virtual bool isBomb() const;
private:
int value;
};
#endif
Mycellwob. cpp
// mycellbomb. cpp
// Реализация класса CMyCellBomb, т.е. ячейки с бомбой
#include "stdafx. h"
#include "mycellbomb. h"
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCellBomb:: CMyCellBomb(int x, int y, int state)
: CMyCell(x, y, state) // устанавливаем координаты ячейки, конструктор по умолчанию
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCellBomb:: CMyCellBomb(const CMyCellBomb & copy)
: CMyCell(copy) // конструктор копирования
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCellBomb:: ~CMyCellBomb() // деструктор
{
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void CMyCellBomb:: Draw(CDC * dc) // рисуем бомбы
{
if (GetState() == CLOSED) // если закрыто, то рисуем закрытую ячейку
CMyCell:: DrawClosedCell(dc);
else if (GetState() == BLOCK) // если стоит флажок, то рисуем флажок
CMyCell:: DrawBlockedCell(dc);
else
// рисуем бомбы
{
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CBrush brush(RGB(255, 0, 0));
CBrush brushCircle(RGB(0, 0, 0));
CPen * oldPen = dc->SelectObject(&pen);
CBrush * oldBrush = dc->SelectObject(&brush);
dc->Rectangle(10 + GetY() * (SIZE + 2), 10 + GetX() * (SIZE + 2),
10 + GetY() * (SIZE + 2) + SIZE, 10 + GetX() * (SIZE + 2) + SIZE);
CBrush * oldBrushCircle = dc->SelectObject(&brushCircle);
dc->Ellipse(10 + GetY() * (SIZE + 2) + 4, 10 + GetX() * (SIZE + 2) + 4,
10 + GetY() * (SIZE + 2) + SIZE - 4, 10 + GetX() * (SIZE + 2) + SIZE - 4);
dc->SelectObject(oldBrushCircle);
dc->SelectObject(oldBrush);
dc->SelectObject(oldPen);
}
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int CMyCellBomb:: Click(CDC * dc) // проверка на щелчок
if (GetState() == BLOCK) // если стоит флажок, то ячейка не откроется при нажатии
return 0;
SetState(OPENED); // открытие ячейки
Draw(dc);
return REDRAW
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
bool CMyCellBomb:: isBomb() const // есть ли это бомба
{
return true;
}
Myfield. h
#ifndef MYFIELD_H_
#define MYFIELD_H_
#include "mycell. h"
class MyField // класс поле, класс-контейнер
{
public:
MyField();
~MyField(); // деструктор
int GetCols() const; // значение колонок
int GetRows() const; // значение строк
int GetBombsCount() const; // количество бомб
int GetFindBombsCount() const; // количество найденных бомб вокруг ячейки
// устанавливаем значения
void SetCols(int c);
void SetRows(int r);
void SetBombsCount(int kol);
void SetFindBombsCount(int kol);
// установка ячеек по индексу
CMyCell * GetCellByIndex(int i, int j);
CPMyCell * GetPCellByIndex(int i, int j);
void SetCellByIndex(int i, int j, CMyCell * cell);
void Init(int cs, int rs, int kb); // инициализация
void ReInit(int cs, int rs, int kb); // перерисовка поля
void DeInit(); // удаление поля
void Draw(CDC * dc);
int Click(CDC * dc, const CPoint & point);
void Block(CDC * dc, const CPoint & point);
void OpenAll();
bool TestOnWin(); // тест на выигрыш
private:
int CalcValueForCell(int i, int j); // подсчитываем цифры для ячейки
bool CheckCell(int i, int j); // проверяем. есть ли это ячейка
void OpenNullValues(int i, int j); // открываем пустую ячейку
void IncFindBombs(); // увеличиваем на еденицу количество бомб
void DecFindBombs(); // уменьшаем на еденицу количество бомб
private:
// вводим переменные
int cols;
int rows;
int kolBombs;
int kolFindBombs;
CPMyCell ** field;
private:
int countItter;
};
#endif
Myfield. cpp
// myfield. cpp
// Класс для работы с полем обьектов CMyCell
#include "stdafx. h"
#include "mycell. h"
#include "mycellbomb. h"
#include "mycellwob. h"
#include "myfield. h"
#include <stdlib. h>
#include <time. h>
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
MyField:: MyField()
: cols(10), rows(10), kolBombs(10), field(NULL) // вводим значения
{
countItter = 0;
srand(time(0)); // задает новое значение для генерации случайных чисел
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
MyField:: ~MyField() // деструктор
{
DeInit(); // удаление поля
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int MyField:: GetCols() const // доступ к колонкам
{
return cols;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int MyField:: GetRows() const // доступ к строкам
{
return rows;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int MyField:: GetBombsCount() const // доступ к количеству бомб
{
return kolBombs;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int MyField:: GetFindBombsCount() const // доступ к значению количества найденных бомб вокруг ячейки
{
return kolFindBombs;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: SetCols(int c) // проверка на то, что колонки больше нуля
{
if (c >= 0)
cols = c;
else
cols = 0; // error
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: SetRows(int r) // проверка на то, что строки больше нуля
{
if (r >= 0)
rows = r;
else
rows = 0; // error
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: SetBombsCount(int kol) // ограничиваем количество бомб
{
int maxVal = GetCols() * GetRows() - GetCols() - GetRows(); // условие количества
if (kol > 0 && kol <= maxVal)
kolBombs = kol;
else if (kol <= 0)
kolBombs = 10; // error
else if (kol > maxVal)
kolBombs = maxVal;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: SetFindBombsCount(int kol)
{
kolFindBombs = kol;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CMyCell * MyField:: GetCellByIndex(int i, int j)
{
if (field == NULL) // если щелчок просто по полю, то ничего не происходит
return NULL; // error
if (i >= 0 && i < GetCols() && j >= 0 && j < GetRows()) // чтоб ячейка не выходила за рамки поля
return field [i] [j] ; // расширение-сужение поля
// error
return NULL;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
CPMyCell * MyField:: GetPCellByIndex(int i, int j) // массив указателей
{
if (field == NULL)
return NULL; // error
if (i >= 0 && i < GetCols() && j >= 0 && j < GetRows())
return &field [i] [j] ;
// error
return NULL;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: SetCellByIndex(int i, int j, CMyCell * cell) // установка ячейки по индексу
{
if (field == NULL) // если поле пустое
return; // error
if (i >= 0 && i < GetCols() && j >= 0 && j < GetRows())
field [i] [j]. SetPointer(cell);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: Init(int cs, int rs, int kb) // задаем значения
{
if (field! = NULL) // поле не пустое
return; // error
if (cs * rs <= kb)
return; // error
SetCols(cs);
SetRows(rs);
SetBombsCount(kb);
if (cols == 0 || rows == 0)
return; // error
// Создаем поле
field = new CPMyCell* [GetCols()] ; // создание двумерного массива в виде строк и столбцов
for (int i = 0; i < GetCols(); i++)
field [i] = new CPMyCell [GetRows()] ;
// Конструктор это делает по умолчанию сам, но если вдруг разкоментировать
// for (int i = 0; i < GetCols() * GetRows(); i++)
// field [i] ->SetPointer(NULL);
// Генерируем, где расспалагаются бомбы
int tmp = GetBombsCount(); // временные переменные
int tmp_cs = 0;
int tmp_rs = 0;
while(tmp! = 0)
{ // выставляем случайно бомбы
tmp_cs = rand()% GetCols();
tmp_rs = rand()% GetRows();
if (field [tmp_cs] [tmp_rs]. GetPointer() == NULL) // если нет бомбы
{
tmp--; // уменьшаем количество бомб на еденицу
field [tmp_cs] [tmp_rs]. SetPointer(new CMyCellBomb(tmp_cs, tmp_rs, CLOSED));
}
else
continue;
}
// Генерируем остальные ячейки
for (int i = 0; i < GetCols(); i++)
for (int j = 0; j < GetRows(); j++)
if (field [i] [j]. GetPointer() == NULL) // Значит не занятая бомбой
field [i] [j]. SetPointer(new CMyCellWob(i, j, CLOSED, CalcValueForCell(i, j)));
SetFindBombsCount(0);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: ReInit(int cs, int rs, int kb) // перерисовка поля
{
DeInit(); // очистка поля
Init(cs, rs, kb); // задаем поле
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: DeInit() // очистка поля
{
if (field == NULL)
return;
for (int i = 0; i < GetCols(); i++)
for (int j = 0; j < GetRows(); j++)
if (field [i] [j]. GetPointer() ! = NULL)
field [i] [j]. Destroy();
for (int i = 0; i < GetCols(); i++) // удаление массива
if (field [i] ! = NULL)
delete [] field [i] ;
if (field! = NULL)
delete [] field;
field = NULL;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: Draw(CDC * dc) // рисуем поле
{
if (field == NULL)
return; // error
for (int i = 0; i < GetCols(); i++)
for (int j = 0; j < GetRows(); j++)
if (field [i] [j] ! = NULL)
field [i] [j] ->Draw(dc);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int MyField:: Click(CDC * dc, const CPoint & point) // проверка, попала ли мышь по ячейке
{
if (field == NULL)
return 0; // error
for (int i = 0; i < GetCols(); i++)
{
for (int j = 0; j < GetRows(); j++)
{
if (field [i] [j] ->HitToPoint(point))
{
int res = field [i] [j] ->Click(dc); // если попала по ячейке, то открываем ее
if (res & OPEN_NULL_VALUES)
{
this->countItter = 0;
OpenNullValues(i, j);
}
if (TestOnWin()) // тест на выигрыш
OpenAll();
res
if (res & GAMEOVER)
OpenAll();
return res;
}
}
}
return 0;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: Block(CDC * dc, const CPoint & point) // возможность ставить флажки по всему полю
{
if (field == NULL)
return; // error
for (int i = 0; i < GetCols(); i++)
{
for (int j = 0; j < GetRows(); j++)
{
if (field [i] [j] ->HitToPoint(point))
{
if (field [i] [j] ->GetState() == OPENED)
return;
if (field [i] [j] ->GetState() == CLOSED)
{
IncFindBombs();
field [i] [j] ->SetState(BLOCK); // проверка на флажок
return;
}
if (field [i] [j] ->GetState() == BLOCK) // правая кнопка убирает флажок
{
DecFindBombs();
field [i] [j] ->SetState(CLOSED);
return;
}
}
}
}
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int MyField:: CalcValueForCell(int i, int j)
{
int value = 0;
// Обходим все соседние ячейки в поисках бомб
if (CheckCell(i, j - 1))
if (GetCellByIndex(i, j - 1) ! = NULL && GetCellByIndex(i, j - 1) - >isBomb())
value++;
if (CheckCell(i - 1, j - 1))
if (GetCellByIndex(i - 1, j - 1) ! = NULL && GetCellByIndex(i - 1, j - 1) - >isBomb())
value++;
if (CheckCell(i - 1, j))
if (GetCellByIndex(i - 1, j) ! = NULL && GetCellByIndex(i - 1, j) - >isBomb())
value++;
if (CheckCell(i - 1, j + 1))
if (GetCellByIndex(i - 1, j + 1) ! = NULL && GetCellByIndex(i - 1, j + 1) - >isBomb())
value++;
if (CheckCell(i, j + 1))
if (GetCellByIndex(i, j + 1) ! = NULL && GetCellByIndex(i, j + 1) - >isBomb())
value++;
if (CheckCell(i + 1, j + 1))
if (GetCellByIndex(i + 1, j + 1) ! = NULL && GetCellByIndex(i + 1, j + 1) - >isBomb())
value++;
if (CheckCell(i + 1, j))
if (GetCellByIndex(i + 1, j) ! = NULL && GetCellByIndex(i + 1, j) - >isBomb())
value++;
if (CheckCell(i + 1, j - 1))
if (GetCellByIndex(i + 1, j - 1) ! = NULL && GetCellByIndex(i + 1, j - 1) - >isBomb())
value++;
return value;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
bool MyField:: CheckCell(int i, int j)
{
if (i >= 0 && j >= 0 && i < GetCols() && j < GetRows())
return true;
return false;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: OpenAll() // открытие ячеек
{
if (field == NULL)
return; // error
// передаем значение номера строки и столбца
for (int i = 0; i < GetCols(); i++)
for (int j = 0; j < GetRows(); j++)
field [i] [j] ->SetState(OPENED);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: OpenNullValues(int i, int j) // пустые ячейки, а вокруг цифры
{
if (! CheckCell(i, j))
return;
if (GetCellByIndex(i, j) == NULL)
return;
if (GetCellByIndex(i, j) - >isBomb())
return;
else
if (countItter! = 0 && (GetCellByIndex(i, j) - >GetState() == OPENED ||
GetCellByIndex(i, j) - >GetState() == BLOCK)) // не может открыть ячейку, если она уже открыта либо стоит с флажком
return;
GetCellByIndex(i, j) - >SetState(OPENED);
countItter++;
// Обходим все соседние ячейки чтобы их открыть
if (((CMyCellWob *) GetCellByIndex(i, j)) - >GetValue() == 0)
{
OpenNullValues(i, j - 1);
OpenNullValues(i - 1, j - 1);
OpenNullValues(i - 1, j);
OpenNullValues(i - 1, j + 1);
OpenNullValues(i, j + 1);
OpenNullValues(i + 1, j + 1);
OpenNullValues(i + 1, j);
OpenNullValues(i + 1, j - 1);
}
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: IncFindBombs()
{
kolFindBombs++; // увеличиваем количество найденных бомб на еденицу
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
void MyField:: DecFindBombs()
{
kolFindBombs--; // уменьшаем количество найденных бомб на еденицу
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
bool MyField:: TestOnWin() // тест на выигрыш
{
for (int i = 0; i < GetCols(); i++)
{
for (int j = 0; j < GetRows(); j++)
if (! field [i] [j] ->isBomb() &&
(field [i] [j] ->GetState() == CLOSED
}
return true;
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
SaperDlg. h
// saperDlg. h: header file
//
#pragma once
#include "myfield. h"
// CsaperDlg dialog
class CsaperDlg: public CDialog
{
// Construction
public:
CsaperDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_SAPER_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
private: // внутренние переменные и функции класса
MyField field;
bool isInitAll;
bool begin;
bool isFirstClick;
void SetPosition();
void ShowFindBombs();
// Implementation
protected:
HICON m_hIcon;
CFont fontFindBombs;
CString nameOfPowered;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point); // функция для щелчка левой кнопкой мыши
public:
afx_msg void OnRButtonDown(UINT nFlags, CPoint point); // функция для щелчка правой кнопкой мыши
public:
int bombsCount; // счетчик бомб
public:
int height; // высота
public:
int width; // ширина
public:
afx_msg void OnBnClickedButtonExit(); // функция выхода из игры
public:
afx_msg void OnBnClickedButtonStart(); // функция для начала игры
};
SaperDlg. cpp
// saperDlg. cpp: implementation file
//
#include "stdafx. h"
#include "saper. h"
#include "saperDlg. h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include "myfield. h"
#include "mycell. h"
// CsaperDlg dialog
CsaperDlg:: CsaperDlg(CWnd* pParent /*=NULL*/)
: CDialog(CsaperDlg:: IDD, pParent), isInitAll(false), begin (false), isFirstClick(true)
, bombsCount(0)
, height(0)
, width(0)
FF_MODERN,
"Courier");
nameOfPowered = "Разработчик: Гаврюшенко Мария Александровна\r\nГруппа: КН-06-4";
void CsaperDlg:: DoDataExchange(CDataExchange* pDX)
{
CDialog:: DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_BOMBS_COUNT, bombsCount);
DDV_MinMaxInt(pDX, bombsCount, 1, 4096);
DDX_Text(pDX, IDC_EDIT_HEIGHT, height);
DDV_MinMaxInt(pDX, height, 10, 40);
DDX_Text(pDX, IDC_EDIT_WIDTH, width);
DDV_MinMaxInt(pDX, width, 10, 50);
}
BEGIN_MESSAGE_MAP(CsaperDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
// }}AFX_MSG_MAP
ON_WM_LBUTTONDOWN()
// ON_WM_MOUSEMOVE()
ON_WM_RBUTTONDOWN()
ON_BN_CLICKED(IDC_BUTTON_EXIT, &CsaperDlg:: OnBnClickedButtonExit)
ON_BN_CLICKED(IDC_BUTTON_START, &CsaperDlg:: OnBnClickedButtonStart)
END_MESSAGE_MAP()
// CsaperDlg message handlers
BOOL CsaperDlg:: OnInitDialog()
{
CDialog:: OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// значения, которые находятся в окне
CRect rect; // задаем значения переменным
GetWindowRect(&rect);
field. Init(10, 10, 15); // поле
height = field. GetCols(); // высота
width = field. GetRows(); // ширина
bombsCount = field. GetBombsCount(); // счетчик бомб
SetPosition(); // устанавливаем позицию
isInitAll = true;
begin = true;
isFirstClick = true;
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CsaperDlg:: OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc. GetSafeHdc()), 0);
// Center icon in client rectangle
// установка иконки
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect. Width() - cxIcon + 1) / 2;
int y = (rect. Height() - cyIcon + 1) / 2;
// Draw the icon
dc. DrawIcon(x, y, m_hIcon);
}
else
{
CDialog:: OnPaint();
CDC * dc = GetDC();
if (isInitAll)
{
// рисуем бомбу
CBrush brush;
brush. CreateSolidBrush(RGB(255, 255, 255));
CBrush * oldBrush = dc->SelectObject(&brush);
dc->Rectangle(8, 8, field. GetRows() * (SIZE + 2) + 10,
field. GetCols() * (SIZE + 2) + 10);
dc->SelectObject(oldBrush);
field. Draw(dc);
}
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CsaperDlg:: OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CsaperDlg:: OnLButtonDown(UINT nFlags, CPoint point)
{
if (! begin)
return;
if (point. x < 10 || point. x > (field. GetRows() * (SIZE + 2) + 3) ||
point. y < 10 || point. y > (field. GetCols() * (SIZE + 2) + 3))
return;
CDC * dc = GetDC();
int result;
result = field. Click(dc, point);
// если при первом щелчке вы проиграли, то поле перерисовуется
if (isFirstClick)
{
while (result & GAMEOVER)
{
field. ReInit(field. GetCols(), field. GetRows(), field. GetBombsCount());
result = field. Click(dc, point);
}
}
ShowFindBombs(); // показывает найденные бомбы
if (result & REDRAW) // перерисовуем поле
{
field. Draw(dc);
CRect rect;
GetWindowRect(&rect);
InvalidateRect(rect, TRUE);
}
if (result & GAMEOVER) // если вы проиграли
{
begin = false;
MessageBox("Вы проиграли!!!: '(", "Конец игры", MB_OK);
}
if (result & WINNER) // если вы выиграли
{
begin = false;
MessageBox("Вы выграли!!!:)))", "Конец игры", MB_OK);
}
isFirstClick = false;
CDialog:: OnLButtonDown(nFlags, point);
}
void CsaperDlg:: OnRButtonDown(UINT nFlags, CPoint point)
point. x > (field. GetRows() * (SIZE + 2) + 3)
void CsaperDlg:: OnBnClickedButtonExit()
{
// Выход
OnOK();
}
void CsaperDlg:: OnBnClickedButtonStart()
{
// Begin
isInitAll = false;
begin = false;
UpdateData(TRUE);
CDC * dc = GetDC();
field. ReInit(height, width, bombsCount); // перерисовка
height = field. GetCols();
width = field. GetRows();
bombsCount = field. GetBombsCount();
SetPosition();
field. Draw(dc);
CRect rect;
GetWindowRect(&rect);
InvalidateRect(rect, TRUE);
isInitAll = true;
begin = true;
isFirstClick = true;
UpdateData(FALSE);
}
void CsaperDlg:: SetPosition()
{
CRect rect;
GetWindowRect(&rect);
// движение окна
MoveWindow(rect. left, rect. top, field. GetRows() * (SIZE + 2) + 230,
field. GetCols() * (SIZE + 2) + 80, TRUE);
ShowFindBombs();
// создание кнопок в окне
GetDlgItem(IDC_STATIC_BOMBS_COUNT) - >SetWindowTextA("Количество бомб: ");
GetDlgItem(IDC_STATIC_BOMBS_COUNT) - >MoveWindow(field. GetRows() * (SIZE + 2) + 30,
70, 130, 15, TRUE);
GetDlgItem(IDC_EDIT_BOMBS_COUNT) - >MoveWindow(field. GetRows() * (SIZE + 2) + 160,
67, 50, 20, TRUE);
GetDlgItem(IDC_STATIC_HEIGHT) - >SetWindowTextA("Высота: ");
GetDlgItem(IDC_STATIC_HEIGHT) - >MoveWindow(field. GetRows() * (SIZE + 2) + 30,
100, 130, 15, TRUE);
GetDlgItem(IDC_EDIT_HEIGHT) - >MoveWindow(field. GetRows() * (SIZE + 2) + 160,
97, 50, 20, TRUE);
GetDlgItem(IDC_STATIC_WIDTH) - >SetWindowTextA("Ширина: ");
GetDlgItem(IDC_STATIC_WIDTH) - >MoveWindow(field. GetRows() * (SIZE + 2) + 30,
130, 130, 15, TRUE);
GetDlgItem(IDC_EDIT_WIDTH) - >MoveWindow(field. GetRows() * (SIZE + 2) + 160,
127, 50, 20, TRUE);
GetDlgItem(IDC_BUTTON_START) - >SetWindowTextA("Начать");
GetDlgItem(IDC_BUTTON_START) - >MoveWindow(field. GetRows() * (SIZE + 2) + 70,
170, 100, 20, TRUE);
GetDlgItem(IDC_BUTTON_EXIT) - >SetWindowTextA("Выход");
GetDlgItem(IDC_BUTTON_EXIT) - >MoveWindow(field. GetRows() * (SIZE + 2) + 70,
200, 100, 20, TRUE);
GetWindowRect(&rect);
GetDlgItem(IDC_STATIC_POWEREDBY) - >SetWindowTextA(nameOfPowered);
GetDlgItem(IDC_STATIC_POWEREDBY) - >MoveWindow(rect. Width() / 2 - 180,
rect. Height() - 65, 350, 50, FALSE);
}
void CsaperDlg:: ShowFindBombs() // показать найденные бомбы
{
char *pNum = NULL;
char num [5] ;
pNum = itoa(field. GetBombsCount() - field. GetFindBombsCount(), num, 10); // перевод цифрового значения в строчный
GetDlgItem(IDC_STATIC_FIND_BOMBS_COUNT) - >SetFont(&fontFindBombs, TRUE);
GetDlgItem(IDC_STATIC_FIND_BOMBS_COUNT) - >SetWindowTextA(pNum);
GetDlgItem(IDC_STATIC_FIND_BOMBS_COUNT) - >MoveWindow(field. GetRows() * (SIZE + 2) + 70,
10, 100, 50, TRUE);
}
ПРИЛОЖЕНИЕ 3.
ИНТЕРФЕЙС ПРОГРАММЫ
РИС.1
РИС.2
РИС.3
РИС.4
РИС.5
