
Новичок
Профиль
Группа: Участник
Сообщений: 23
Регистрация: 9.12.2007
Репутация: нет Всего: нет
|
| Код | ////////////////////////////////////////////// //main.cpp //////////////////////////////////////////////////////////
#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; }
}
//установить размер корабля ship.size = size;
for( i = 0; i < size; i++) { //установить координат корабля //и помететь определенные клетки на поле как занятые кораблем if(direction == VERTICAL) { ship.coord[i] = coord; setSign(field, coord.X, coord.Y, CSHIP); coord.Y++; } else { ship.coord[i] = coord; setSign(field, coord.X, coord.Y, CSHIP); coord.X++; }
} return SUCCEEDED; }
//функция установки корабля в случайное место int MyShips :: setShipToRandomPlace(SHIP &ship, FIELD &field, int size) { srand(GetTickCount()); COORD coord; //присвоить случайные значения переменным coord и direction coord.X = rand()%10; coord.Y = rand()%10; int direction; if(rand()%2) direction = HORIZONTAL; else direction = VERTICAL;
//попытаться установить корабль на случайные координаты return setShip(ship, field, coord, size, direction); }
//установить статус корабля void MyShips :: setShipStatus(SHIP &ship, int shipStatus) { ship.shipStatus = shipStatus; }
//узнать статус корабля int MyShips :: getShipStatus(SHIP ship) { return ship.shipStatus; }
//узнать размер корабля int MyShips :: getShipSize(SHIP ship) { return ship.size; }
//узнать координаты корабля COORD MyShips :: getShipCoord(SHIP ship, int deck) { return ship.coord[deck]; }
//функция убить корабль void MyShips :: killShip(SHIP &ship, FIELD &field) { COORD coord; //установить статус корабля setShipStatus(ship, DESTROYED); //пометить клетки на поле как "убитый" for(int i = 0; i < ship.size; i++) { coord = ship.coord[i]; setSign(field, coord.X, coord.Y, KILLED); } }
//Вспомогательные функции
//функция проверки того, находится ли данная клетка внутри поля int MyShips :: IsInside(int x, int y) { if((x >=0 )&&(x <=9) && (y >=0 )&&(y <=9)) return 1; else return 0; }
//функция проверки, помечена ли данная клетка как "промах" int MyShips :: IsMissed(FIELD field, int x, int y) { if(getSign(field, x, y) == MISSED) return 1; else return 0; }
//проверка являится ли данная клетка пустой int MyShips :: IsEmpty(FIELD field, int x, int y) { if((((getSign(field, x, y) == EMPTY)||(getSign(field, x, y) == ZERO)||(getSign(field, x, y) == MISSED)) &&(x >=0 )&&(x <=9) && (y >=0 )&&(y <=9))|| ((x <= -1)||(y <= -1)||(x >= 10)||(y >= 10))) return 1; else return 0; }
////////////////////////////////////////////////////////// //gameplace.h //////////////////////////////////////////////////////////
#ifndef __gameplace #define __gameplace
#include "field.h" #include "ships.h"
#define DOUBLE 41
using namespace MyShips; using namespace MyField;
#define FIRSTTIME 50
namespace GamePlace{ struct GAMEPLACE{ FIELD field; SHIP ship[10]; };
//расставить все корабли void setAllShips(GAMEPLACE &gameplace); //организовать выстрел в данную клетку //возвращает: попал, убил, мимо или вторичный выстрел int fire(GAMEPLACE &gameplace, int x, int y); //расставить знаки говорящие о том,
|
Это сообщение отредактировал(а) EnShTe1N - 10.12.2007, 19:17
|