E-mail: magikgod@mail.ru
|
Игра Морской Бой (часть 1)
#include <iostream.h>
#include <windows.h>
#include <fstream.h>
#include "field.h"
#include "utils.h"
#include "ships.h"
#include "gameplace.h"
#include "computer.h"
#include "game.h"
using namespace MyField;
using namespace MyUtils;
using namespace MyShips;
using namespace MyComputer;
using namespace GamePlace;
using namespace MyGame;
void main(void)
{
int turn;
char ch;
do
{
cout << "Do you want to move first or second? (1, 2): ";
cin >> turn;
if(turn == 1)
play(PLAYERVSCOMP);
else
play(COMPVSPLAYER);
fill();
cout << endl << "Do you want to continue? (y/n): ";
cin >> ch;
} while (ch == ''y'');
}
//////////////////////////////////////////////////////////
//field.h
//////////////////////////////////////////////////////////
#ifndef __field
#define __field
#define EMPTY 0 //пустая
#define MISSED 1 //мимо
#define WOUNDED 2 //ранен
#define KILLED 3 //убит
#define ZERO 4 //заведомо пустая клетка
#define CSHIP 5 //клетка заняьая кораблем
#define CURSOR 6
#define WITHSHIPS 7
#define WITHOUTSHIPS 8
#define WITHOUTSHIPSANDWOUNDED 9
#define SIDE 10 //длина стороны
#define SHOWSHIPS 11
#define NOSHOWSHIPS 12
namespace MyField{
//структура поле
struct FIELD{
//массив 10х10, которым представленно игровое поле
int field[10][10];
//режим показа поля
int showMode;
};
//функция очистки поля
void clearField(FIELD &field);
//функция прорисовки поля
void drawField(FIELD field, COORD coord);
//функция прорисовки одной клетки
void drawCell(FIELD field, COORD coord, int i, int j);
//функция установки знаков на поле
void setSign(FIELD &field, int x, int y, int sign);
//функция получения знака
int getSign(FIELD field, int x, int y);
//функция установки режима отображения
void setShowMode(FIELD &field, int showMode);
//функция копирования поля
void copyField(FIELD &dfield, const FIELD sfield, int flag);
};
#endif //__field
//////////////////////////////////////////////////////////
//field.cpp
//////////////////////////////////////////////////////////
#include <iostream.h>
#include <windows.h>
#include <fstream.h>
#include <string.h>
#include <stdio.h>
#include "field.h"
//функция очистки поля
void MyField :: clearField(FIELD &field)
{
for(int i = 0; i < SIDE; i++)
for(int j = 0; j < SIDE; j++)
field.field[i][j] = EMPTY;
}
//функция прорисовки поля
void MyField :: drawField(FIELD field, COORD coord)
{
COORD oldCoord = coord;
HANDLE Handle;
LPDWORD lpNumberOfCharsWritten;
LPVOID lpReserved;
Handle = GetStdHandle(STD_OUTPUT_HANDLE);
//нарисовать координаты
SetConsoleCursorPosition(Handle, coord);
WriteConsole(Handle, " A B C D E F G H I J", 33,
lpNumberOfCharsWritten, lpReserved);
char szBuf[3];
int nSize;
for(int i = 0; i < SIDE; i++)
{
coord.Y++;
SetConsoleCursorPosition(Handle, coord);
nSize = sprintf(szBuf, "%d", i + 1);
WriteConsole(Handle, szBuf, nSize,
lpNumberOfCharsWritten, lpReserved);
}
coord = oldCoord;
WORD colour;
char sign[3];
LPDWORD lpdwN;
//просмотреть знака каждой клетки и
//и в зависимости от этого отобразить ее на экране
//в том или ином виде
for(int j = 0; j < SIDE; j++)
{
coord.Y++;
for(int i = 0; i < SIDE; i++)
{
coord.X+=3;
if(field.field[i][j] == CURSOR)
{
colour = BACKGROUND_RED|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " ");
}
//если клетка занята кораблем
//нарисовать плюсик на голубом фоне
if((field.field[i][j] == CSHIP)&&
(field.showMode == SHOWSHIPS))
{
colour = BACKGROUND_GREEN| BACKGROUND_BLUE |
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " + ");
}
if((field.field[i][j] == CSHIP)
&&(field.showMode == NOSHOWSHIPS))
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " ");
}
//если клетка пустая, нарисовать ее зеленым цветом
if(field.field[i][j] == EMPTY)
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " ");
}
//если клетка пустая, поставить точку
if(field.field[i][j] == ZERO)
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " . ");
}
//если в клетку уже стреляли, но не попали
//поставить кружочек
if(field.field[i][j] == MISSED)
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " 0 ");
}
//если на клетке находится раненый корабль,
//поставить звездочку
if(field.field[i][j] == WOUNDED)
{
colour = BACKGROUND_BLUE| BACKGROUND_RED|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " * ");
}
//если на клетке находится убитый корабль,
//нарисовать крестик
if(field.field[i][j] == KILLED)
{
colour = BACKGROUND_RED|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " X ");
}
SetConsoleCursorPosition(Handle, coord);
WriteConsole(Handle, sign, 3,
lpNumberOfCharsWritten, lpReserved);
FillConsoleOutputAttribute(
Handle,
colour,
3,
coord,
lpdwN
);
}
coord.X-=30;
}
}
void MyField :: drawCell(FIELD field, COORD coord, int i, int j)
{
HANDLE Handle;
LPDWORD lpNumberOfCharsWritten;
LPVOID lpReserved;
Handle = GetStdHandle(STD_OUTPUT_HANDLE);
WORD colour;
char sign[3];
LPDWORD lpdwN;
coord.X += (i + 1)*3;
coord.Y += j + 1;
if(field.field[i][j] == CURSOR)
{
colour = BACKGROUND_RED|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " ");
}
//если клетка занята кораблем
//нарисовать плюсик на голубом фоне
if((field.field[i][j] == CSHIP)&&
(field.showMode == SHOWSHIPS))
{
colour = BACKGROUND_GREEN| BACKGROUND_BLUE |
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " + ");
}
if((field.field[i][j] == CSHIP)
&&(field.showMode == NOSHOWSHIPS))
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " ");
}
//если клетка пустая, нарисовать ее зеленым цветом
if(field.field[i][j] == EMPTY)
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " ");
}
//если клетка пустая, поставить точку
if(field.field[i][j] == ZERO)
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " . ");
}
//если в клетку уже стреляли, но не попали
//поставить кружочек
if(field.field[i][j] == MISSED)
{
colour = BACKGROUND_GREEN|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " 0 ");
}
//если на клетке находится раненый корабль,
//поставить звездочку
if(field.field[i][j] == WOUNDED)
{
colour = BACKGROUND_BLUE| BACKGROUND_RED|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " * ");
}
//если на клетке находится убитый корабль,
//нарисовать крестик
if(field.field[i][j] == KILLED)
{
colour = BACKGROUND_RED|
FOREGROUND_BLUE |
FOREGROUND_GREEN | FOREGROUND_RED;
strcpy(sign, " X ");
}
SetConsoleCursorPosition(Handle, coord);
WriteConsole(Handle, sign, 3,
lpNumberOfCharsWritten, lpReserved);
FillConsoleOutputAttribute(
Handle,
colour,
3,
coord,
lpdwN
);
}
//функция установить знак, характеризующий данную клетку
void MyField :: setSign(FIELD &field, int x, int y, int sign)
{
if((x >= 0)&&(x < 10)&&(y >= 0)&&(y < 10))
field.field[x][y] = sign;
}
//функция узнать знак
int MyField :: getSign(FIELD field, int x, int y)
{
if((x >= 0)&&(x < 10)&&(y >= 0)&&(y < 10))
return field.field[x][y];
else
return ERROR;
}
//функция установить режим отображения поля
void MyField :: setShowMode(FIELD &field, int showMode)
{
field.showMode = showMode;
}
//скопировать поле
void MyField :: copyField(FIELD &dfield, const FIELD sfield, int flag)
{
int i, j;
for(i = 0; i < SIDE; i++)
for(j = 0; j < SIDE; j++)
{
if(flag == WITHSHIPS)
dfield.field[i][j] = sfield.field[i][j];
else
if(flag == WITHOUTSHIPS)
{
if(sfield.field[i][j] == CSHIP)
dfield.field[i][j] = EMPTY;
else
dfield.field[i][j] = sfield.field[i][j];
}
else
if(flag == WITHOUTSHIPSANDWOUNDED)
{
if((sfield.field[i][j] == CSHIP)||
(sfield.field[i][j] == WOUNDED))
dfield.field[i][j] = EMPTY;
else
dfield.field[i][j] = sfield.field[i][j];
}
}
dfield.showMode = sfield.showMode;
}
//////////////////////////////////////////////////////////
//ships.h
//////////////////////////////////////////////////////////
#ifndef __ships
#define __ships
#include "field.h"
#define VERTICAL 21
#define HORIZONTAL 22
#define FAILED 0
#define SUCCEEDED 1
#define DESTROYED 23
#define LIVE 24
using namespace MyField;
namespace MyShips{
//структура корабль
struct SHIP {
//количество палуб
int size;
//координаты каждой палубы
COORD coord[4];
//статус корабля (живой, живой, но раненый или убитый
int shipStatus;
};
//поставить корабль на поле в определенную точку
//и в определенном направлении
int setShip(SHIP &ship, FIELD &field, COORD coord,
int size, int direction);
//поставить корабль определенного в случайное место
int setShipToRandomPlace(SHIP &ship, FIELD &feld, int size);
//установить статус корабля
void setShipStatus(SHIP &ship, int shipStatus);
//узнать статус корабля
int getShipStatus(SHIP ship);
//узнать размер корабля
int getShipSize(SHIP ship);
//узнать координаты палубы корабля по ее номеру
COORD getShipCoord(SHIP ship, int deck);
//убить корабль - выполнить все действия связанные с уничтожением
//корабля (установить статус корабля, статус клетки поля и т. д.)
void killShip(SHIP &ship, FIELD &field);
//
//вспомогательные функции проверки
//
//находится ли клетка с такими координатами внутри пол
int IsInside(int x, int y);
//помечена ли данная клетка как "промах"
int IsMissed(FIELD field, int x, int y);
//пуста ли данная клетка
int IsEmpty(FIELD field, int x, int y);
};
#endif
//////////////////////////////////////////////////////////
//ships.cpp
//////////////////////////////////////////////////////////
#include <iostream.h>
#include <windows.h>
#include <stdlib.h>
#include "ships.h"
#include "field.h"
//функция установки корабля на заданную клетку
int MyShips :: setShip(SHIP &ship, FIELD &field, COORD coord,
int size, int direction)
{
int x, y;
for(int i = 0; i < size; i++)
{
if(direction == VERTICAL)
{
x = coord.X;
y = coord.Y + i;
//если на данную клетку нельзя поставить корабль,
//выйти из функции
if(!(IsEmpty(field, x, y)&&IsInside(x, y)
&&!IsMissed(field, x, y)))
return FAILED;
if(!(IsEmpty(field, x - 1, y - 1)&&
IsEmpty(field, x - 1, y )&&
IsEmpty(field, x - 1, y + 1)&&
IsEmpty(field, x , y - 1)&&
IsEmpty(field, x , y + 1)&&
IsEmpty(field, x + 1, y - 1)&&
IsEmpty(field, x + 1, y )&&
IsEmpty(field, x + 1, y + 1)))
return FAILED;
}
else
{
x = coord.X + i;
y = coord.Y;
//если на данную клетку нельзя поставить корабль,
//выйти из функции
if(!(IsEmpty(field, x, y)&&IsInside( x, y)
&&!IsMissed(field, x, y)))
return FAILED;
if(!(IsEmpty(field, x - 1, y - 1)&&
IsEmpty(field, x - 1, y )&&
IsEmpty(field, x - 1, y + 1)&&
IsEmpty(field, x , y - 1)&&
IsEmpty(field, x , y + 1)&&
IsEmpty(field, x + 1, y - 1)&&
IsEmpty(field, x + 1, y )&&
IsEmpty(field, x + 1, y + 1)))
return FAILED;
|