Назад | Начало урока | Вперед
Содержание

Глава 1

Анализ:

Функция OnPaint() перерисовывает поле боя, учитывая все изменения,
которые произошли на поле с кораблями и вокруг них.


void CField::OnPaint() {
CPaintDC dc(this); // device context for painting
int i, j;
RECT rect;
char *let = "abcdefghik";
CPen pn1, *oldpn1;
int count;
CBrush br;

GetClientRect(&rect);
if(m_Mode == OWN_FIELD)
{


//Нарисуем синюю воду
dc.BitBlt(dc.m_ps.rcPaint.left, dc.m_ps.rcPaint.top,
dc.m_ps.rcPaint.right - dc.m_ps.rcPaint.left,
dc.m_ps.rcPaint.bottom - dc.m_ps.rcPaint.top,
&WaterDC, dc.m_ps.rcPaint.left,
dc.m_ps.rcPaint.top, SRCCOPY);

//горизонтальные линии сетки
for(i=(dc.m_ps.rcPaint.top/20)*20; i<=(dc.m_ps.rcPaint.bottom/20)*20; i+=20) {
dc.MoveTo(dc.m_ps.rcPaint.left, i);
dc.LineTo(dc.m_ps.rcPaint.right, i);
}
//вериткальные линии сетки
for(i=(dc.m_ps.rcPaint.left/20)*20; i<=(dc.m_ps.rcPaint.right/20)*20; i+=20) {
dc.MoveTo(i, dc.m_ps.rcPaint.top);
dc.LineTo(i, dc.m_ps.rcPaint.bottom);
}

for(i=0; i<10; i++)

for(j=0; j<10; j++) {
count = 0;
if(m_Event[i][j] == SHIP ||
m_Event[i][j] == SHIPWOUND ||
m_Event[i][j] == SHIPKILLED)
{
if((m_Event[i][j+1] == SHIP ||
m_Event[i][j+1] == SHIPWOUND ||
m_Event[i][j+1] == SHIPKILLED) && j+1 < 10)
{
count = 1;
do {
count++;
} while(
(m_Event[i][j+count] == SHIP ||
m_Event[i][j+count] == SHIPWOUND ||
m_Event[i][j+count] == SHIPKILLED) && j+count<10);

DrawShip
(CRect(j*20, i*20, (j+count)*20, (i+1)*20), &dc);
j+=count;
continue;
}
else {
if(
(m_Event[i+1][j] == SHIP ||
m_Event[i+1][j] == SHIPWOUND ||
m_Event[i+1][j] == SHIPKILLED)
&&
((m_Event[i-1][j] != SHIP &&
m_Event[i-1][j] != SHIPKILLED &&
m_Event[i-1][j] != SHIPWOUND) || i-1<0)
&& i+1<10)
{
count = 1;
do {
count++;
} while(
(m_Event[i+count][j] == SHIP ||
m_Event[i+count][j] == SHIPWOUND ||
m_Event[i+count][j] == SHIPKILLED)
&& i+count<10);

DrawShip(CRect(j*20, i*20, (j+1)*20, (i+count)*20), &dc);
continue;
}
if(((m_Event[i+1][j] != SHIP &&
m_Event[i+1][j] != SHIPKILLED &&
m_Event[i+1][j] != SHIPWOUND) && i+1<10)||(i+1==10))
if(((m_Event[i-1][j] != SHIP &&
m_Event[i-1][j] != SHIPWOUND &&
m_Event[i-1][j] != SHIPKILLED) && i-1 >= 0) || (i-1<0))
if(((m_Event[i][j+1] != SHIP &&
m_Event[i][j+1] != SHIPWOUND &&
m_Event[i][j+1] != SHIPKILLED) && j+1<10) || (j+1==10))
if(((m_Event[i][j-1] != SHIP &&
m_Event[i][j-1] != SHIPWOUND &&
m_Event[i][j-1] != SHIPKILLED) && j-1>=0) || (j-1<0))
DrawShip(CRect(j*20, i*20, (j+1)*20, (i+1)*20), &dc);
}//else
}//if
}//for
if(m_Draw && m_Operation == PLACEMENT)
//клик левой кнопкой на клетке, нарисовать корабль в переданных координатах
DrawShip(GetRect(), &dc);
}//if(m_Mode == OWN_FIELD)

GetClientRect(&rect);
if(m_Mode == FOREIGN_FIELD)
{

dc.BitBlt(dc.m_ps.rcPaint.left, dc.m_ps.rcPaint.top,
dc.m_ps.rcPaint.right - dc.m_ps.rcPaint.left,
dc.m_ps.rcPaint.bottom - dc.m_ps.rcPaint.top,
&WaterDC, dc.m_ps.rcPaint.left,
dc.m_ps.rcPaint.top, SRCCOPY);
for(i=(dc.m_ps.rcPaint.top/20)*20; i<=(dc.m_ps.rcPaint.bottom/20)*20; i+=20) {
dc.MoveTo(dc.m_ps.rcPaint.left, i);
dc.LineTo(dc.m_ps.rcPaint.right, i);
}
for(i=(dc.m_ps.rcPaint.left/20)*20; i<=(dc.m_ps.rcPaint.right/20)*20; i+=20) {
dc.MoveTo(i, dc.m_ps.rcPaint.top);
dc.LineTo(i, dc.m_ps.rcPaint.bottom);
}
for(i=0; i<10; i++)
for(j=0; j<10; j++) {
count = 0;
if(m_Event[i][j] == SHIPKILLED) {
if(m_Event[i][j+1] == SHIPKILLED && j+1<10) {
count = 1;
do {
count++;
} while(m_Event[i][j+count] == SHIPKILLED && j+count<10);

DrawShip(CRect(j*20, i*20, (j+count)*20, (i+1)*20), &dc);
j+=count;
continue;

}
else {
if(m_Event[i+1][j] == SHIPKILLED &&
(m_Event[i-1][j] != SHIPKILLED || i-1==-1)
&& i+1 <10)
{
count = 1;
do {
count++;
} while(m_Event[i+count][j] == SHIPKILLED
&& i+count<10);

DrawShip(CRect(j*20, i*20, (j+1)*20, (i+count)*20), &dc);
continue;

}
if((m_Event[i+1][j] != SHIPKILLED
&& i+1<10)||(i+1==10))
if((m_Event[i-1][j] != SHIPKILLED
&& i-1 >= 0) || (i-1<0))
if((m_Event[i][j+1] != SHIPKILLED
&& j+1<10) || (j+1==10))
if((m_Event[i][j-1] != SHIPKILLED
&& j-1>=0) || (j-1<0))
DrawShip(CRect(j*20, i*20, (j+1)*20, (i+1)*20), &dc);
}//else
}//if
}//for
}//for
pn1.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
oldpn1 = dc.SelectObject(&pn1);
br.CreateSolidBrush(RGB(22, 60, 84));
for(i=0; i<10; i++) {
for(j=0; j<10; j++) {
//где не попали, там рисуем крестик
if(m_Event[i][j] == CANNOT) {
dc.MoveTo(j*20, i*20);
dc.LineTo((j+1)*20, (i+1)*20);
dc.MoveTo(j*20, (i+1)*20);
dc.LineTo((j+1)*20, i*20);
}
//возле убитого корабля - черно-зеленые клетки
if(m_Event[i][j] == NEARKILLEDSHIP)
dc.FillRect(CRect(j*20+1, i*20+1, (j+1)*20, (i+1)*20), &br);
//клетка убита или ранена, рисуем взрыв
if(m_Event[i][j] == SHIPKILLED || m_Event[i][j] == SHIPWOUND)
DrawObject(CRect(j*20, i*20, (j+1)*20, (i+1)*20), &dc, m_bFire);
}
}
dc.SelectObject(oldpn1);
pn1.DeleteObject();
br.DeleteObject();
if(m_Mode == NUMBERS) {
dc.SetBkMode(TRANSPARENT);
dc.TextOut(0, 4, " 1 2 3 4 5 6 7 8 9 10");
}
if(m_Mode == LETTERS) {
dc.SetBkMode(TRANSPARENT);
for(i=0; i < rect.bottom-rect.top; i+=20)
dc.TextOut(8, i+2, let[i/20]);
}
}

Еще пояснения на псевдокоде:

Функция DrawShip(RECT rect, CDC *dc) -
нарисовать корабль - это выбрать рисунок из массива рисунков
и разместить в переданных координатах прямоугольника

Поэтому в функции OnPaint() исследуются координаты вокруг точек.
-------------------------
void CField::OnPaint() {

CPaintDC dc(this); // device context for painting
int i, j;
RECT rect;
char *let = "abcdefghik";
CPen pn1, *oldpn1;
int count;
CBrush br;

GetClientRect(&rect);
if(m_Mode == OWN_FIELD) {

//Нарисуем синюю воду
dc.BitBlt(dc.m_ps.rcPaint.left, dc.m_ps.rcPaint.top,
dc.m_ps.rcPaint.right - dc.m_ps.rcPaint.left,
dc.m_ps.rcPaint.bottom - dc.m_ps.rcPaint.top,
&WaterDC, dc.m_ps.rcPaint.left,
dc.m_ps.rcPaint.top, SRCCOPY);

//горизонтальные линии сетки
for(i=(dc.m_ps.rcPaint.top/20)*20; i<=(dc.m_ps.rcPaint.bottom/20)*20; i+=20) {

dc.MoveTo(dc.m_ps.rcPaint.left, i);
dc.LineTo(dc.m_ps.rcPaint.right, i);
}

//вериткальные линии сетки
for(i=(dc.m_ps.rcPaint.left/20)*20; i<=(dc.m_ps.rcPaint.right/20)*20; i+=20) {

dc.MoveTo(i, dc.m_ps.rcPaint.top);
dc.LineTo(i, dc.m_ps.rcPaint.bottom);
}

//расставим корабли
for(i=0; i<10; i++){

for(j=0; j<10; j++) {
count = 0;
ЕСЛИ (это корабль)
{
ЕСЛИ(
на одну клетку вниз - корабль и это еще поле
//Ясно, что это корабль и он направлен вниз.
{
//сосчитаем двигаясь вниз количество клеток корабля.
// оно не может быть больше 4 но начнем с единицы
count = 1;
ДЕЛАЙ{
count++ (еще одна клетка)
делаем шаг вниз
}ПОКА (следующая клетка вниз - корабль и она еще на поле)
//рисуем корабль в этих координатах вниз
DrawShip(CRect(j*20, i*20, (j+count)*20, (i+1)*20), &dc);
j+=count;
continue;
}
ИНАЧЕ {
ЕСЛИ(
на одну клетку вправо - корабль и
((на одну влево - не корабль или уже не поле) И на одну вправо - еще поле))
//Ясно, что это корабль и он направлен вправо.
{
//сосчитаем двигаясь вправо количество клеток корабля.
// оно не может быть больше 4 но начнем с единицы
count = 1; ДЕЛАЙ{
count++ (еще одна клетка)
делаем шаг вправо
}ПОКА (следующая клетка справа - корабль и она еще на поле)
//рисуем корабль в этих координатах вправо
DrawShip(CRect(j*20, i*20, (j+1)*20, (i+count)*20), &dc);
continue;//вернуться
}

ЕСЛИ (все клетки вокруг исследуемой не являются кораблем
и находятся на поле, не ближе одной клетки от любого его края)
{

//рисуем корабль в этих координатах (естественно это одноклеточный корабль)
DrawShip(CRect(j*20, i*20, (j+1)*20, (i+1)*20), &dc);
}
}//end ИНАЧЕ это корабль вправо или одноклеточный
}//end ЕСЛИ это корабль
}//end for
}//end for

if(m_Draw && m_Operation == PLACEMENT) {

//клик левой кнопкой на клетке,
//нарисовать корабль в переданных координатах
DrawShip(GetRect(), &dc);
}
}//end if(m_Mode == OWN_FIELD)

GetClientRect(&rect);
/////////////////////////
pn1.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
oldpn1 = dc.SelectObject(&pn1);
br.CreateSolidBrush(RGB(22, 60, 84));

Еще раз просмотрим все поле - где крестик, где взрыв,
где черо-зеленая ячейка.

for(i=0; i<10; i++){

for(j=0; j<10; j++) {
//где не попали, там рисуем крестик
if(m_Event[i][j] == CANNOT) {
dc.MoveTo(j*20, i*20);
dc.LineTo((j+1)*20, (i+1)*20);
dc.MoveTo(j*20, (i+1)*20);
dc.LineTo((j+1)*20, i*20);
}
//возле убитого корабля - черно-зеленые клетки
if(m_Event[i][j] == NEARKILLEDSHIP)
dc.FillRect(CRect(j*20+1, i*20+1, (j+1)*20, (i+1)*20), &br);
//клетка убита или ранена, рисуем взрыв
if(m_Event[i][j] == SHIPKILLED || m_Event[i][j] == SHIPWOUND)
DrawObject(CRect(j*20, i*20, (j+1)*20, (i+1)*20), &dc, m_bFire);
}
}
dc.SelectObject(oldpn1);
pn1.DeleteObject();
br.DeleteObject();
//проставим цифры над полем
if(m_Mode == NUMBERS) {
dc.SetBkMode(TRANSPARENT);
dc.TextOut(0, 4, " 1 2 3 4 5 6 7 8 9 10");
}
//проставим буквы
if(m_Mode == LETTERS) {
dc.SetBkMode(TRANSPARENT);
for(i=0; i dc.TextOut(8, i+2, (char*)let[i/20]);
}


Назад | Начало урока | Вверх | Вперед
Содержание

Hosted by uCoz