E-mail: magikgod@mail.ru
|
Игра Морской Бой часть 4
{
top.Y = i;
FillConsoleOutputAttribute(
Handle,
colour,
80,
top,
lpdwN
);
}
}
//вывести на экран текст
void MyUtils :: WriteText(char *text, int size, int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
HANDLE Handle;
Handle = GetStdHandle(STD_OUTPUT_HANDLE);
LPDWORD lpNumberOfCharsWritten;
LPVOID lpReserved;
SetConsoleCursorPosition(Handle, coord);
WriteConsole(Handle, text, size,
lpNumberOfCharsWritten, lpReserved);
}
//////////////////////////////////////////////////////////
//computer.h
//////////////////////////////////////////////////////////
#ifndef __computer
#define __computer
#include "field.h"
#include "ships.h"
#include "gameplace.h"
#define FIRSTTIME 50
using namespace MyShips;
using namespace MyField;
using namespace GamePlace;
namespace MyComputer {
//получить рейтинг клетки
int getRatingOfCell(GAMEPLACE gameplace, int x, int y);
COORD chooseTurn(GAMEPLACE gameplace);
//добить корабль
int finishShip(GAMEPLACE &gameplace, int num);
//фукнция находит лучшую клетку для добивания раненого корабля
COORD getBestCellForWoundedShip(GAMEPLACE gameplace,
int x, int y);
//сделать один выстрел
int makeMove(GAMEPLACE &gameplace);
//выбрать ход, если нет раненого корабля
void computerMove(GAMEPLACE &gameplace, COORD fieldCoord);
};
#endif
//////////////////////////////////////////////////////////
//computer.cpp
//////////////////////////////////////////////////////////
#include <iostream.h>
#include <windows.h>
#include <stdlib.h>
#include "computer.h"
//фукнция находит лучшую клетку для добивания раненого корабля
COORD MyComputer ::
getBestCellForWoundedShip(GAMEPLACE gameplace, int x, int y)
{
int tmp;
COORD coord;
int rating = 0;
//находит клетку на одной линии с наилучшим рейтингом
tmp = getRatingOfCell(gameplace, x + 1, y);
coord.X = x + 1;
coord.Y = y;
tmp = getRatingOfCell(gameplace, x - 1, y);
if(tmp > rating)
{
rating = tmp;
coord.X = x - 1;
coord.Y = y;
}
tmp = getRatingOfCell(gameplace, x, y + 1);
if(tmp > rating)
{
rating = tmp;
coord.X = x;
coord.Y = y + 1;
}
tmp = getRatingOfCell(gameplace, x, y - 1);
if(tmp > rating)
{
rating = tmp;
coord.X = x;
coord.Y = y - 1;
}
return coord;
}
//получить рейтинг клетки
int MyComputer :: getRatingOfCell(GAMEPLACE gameplace, int x, int y)
{
int rating;
FIELD field;
//скопировать поле
copyField(field, gameplace.field, WITHOUTSHIPS);
if((getSign(field, x, y) != EMPTY)||(x<0)||(x>9)||(y<0)||(y>9))
return 0;
else
{
COORD coord;
int j, tmp;
rating = 0;
//попытаться поставить каждый из живых кораблей на
//данную клетку при этом подсчитать рейтинг клетки
for(int i = 0; i < 10; i++)
{
for(j = 0; j < getShipSize(gameplace.ship[i]); j++)
{
if(getShipStatus(gameplace.ship[i]) != DESTROYED)
{
copyField(field, gameplace.field, WITHOUTSHIPS);
coord.X = x - j;
coord.Y = y;
if(tmp = setShip(gameplace.ship[i], field,
coord, getShipSize(gameplace.ship[i]),
HORIZONTAL))
rating += getShipSize(gameplace.ship[i]);
clearField(field);
}
}
for(j = 0; j < getShipSize(gameplace.ship[i]); j++)
{
if(getShipStatus(gameplace.ship[i]) != DESTROYED)
{
copyField(field, gameplace.field, WITHOUTSHIPS);
coord.X = x;
coord.Y = y - j;
if(setShip(gameplace.ship[i], field,
coord, getShipSize(gameplace.ship[i]),
VERTICAL)&&
(getShipSize(gameplace.ship[i])!=1))
rating += getShipSize(gameplace.ship[i]);
clearField(field);
}
}
}
}
return rating;
}
//добить корабль
int MyComputer :: finishShip(GAMEPLACE &gameplace, int num)
{
COORD coordMax, coordMin, coordTmp;
int isWoundedDeckFound = 0, i = -1, min, max;
//поиск минимальной раненой палубы
while((!isWoundedDeckFound)&&(getShipSize(gameplace.ship[num]) > i))
{
i++;
coordTmp = getShipCoord(gameplace.ship[num], i);
if(getSign(gameplace.field, coordTmp.X, coordTmp.Y) ==
WOUNDED)
isWoundedDeckFound = 1;
}
min = i;
coordMin = coordTmp;
isWoundedDeckFound = 0;
i = getShipSize(gameplace.ship[num]);
//поиск максимальной раненой палубы
while((!isWoundedDeckFound)&&(i >=0))
{
i--;
coordTmp = getShipCoord(gameplace.ship[num], i);
if(getSign(gameplace.field, coordTmp.X, coordTmp.Y) ==
WOUNDED)
isWoundedDeckFound = 1;
}
max = i;
coordMax = coordTmp;
COORD coord = {5, 5};
GAMEPLACE tmpGameplace;
copyField(tmpGameplace.field, gameplace.field, WITHOUTSHIPSANDWOUNDED);
/////
for(i = 0; i < 10; i++)
tmpGameplace.ship[i] = gameplace.ship[i];
/////
//если ранена всего одна палуба
if(min == max)
{
FIELD field;
coord = getBestCellForWoundedShip(tmpGameplace, coordMax.X, coordMax.Y);
}
else
{
//если раненый корабль расположен вертикально
if(coordMin.X == coordMax.X)
{
if(IsInside( coordMin.X, coordMin.Y - 1)
&&(getSign(tmpGameplace.field, coordMin.X, coordMin.Y - 1)==EMPTY))
{
coord.X = coordMin.X;
coord.Y = coordMin.Y - 1;
}
else
{
coord.X = coordMax.X;
coord.Y = coordMax.Y + 1;
}
}
else
{
if(IsInside( coordMin.X - 1, coordMin.Y)
&&(getSign(tmpGameplace.field, coordMin.X - 1, coordMin.Y) == EMPTY))
{
coord.X = coordMin.X - 1;
coord.Y = coordMin.Y;
}
else
{
coord.X = coordMax.X + 1;
coord.Y = coordMax.Y;
}
}
}
return fire(gameplace, coord.X, coord.Y);
}
//сделать один выстрел
int MyComputer :: makeMove(GAMEPLACE &gameplace)
{
//поиск раненого корабля
int i = -1, isFound = 0;
while((!isFound)&&(i < 10))
{
i++;
if(getShipStatus(gameplace.ship[i]) == WOUNDED)
isFound = 1;
}
if(isFound)
{
return finishShip(gameplace, i);
}
else
{
COORD coord;
coord = chooseTurn(gameplace);
return fire(gameplace, coord.X, coord.Y);
}
}
//выбрать ход, если нет раненого корабля
COORD MyComputer :: chooseTurn(GAMEPLACE gameplace)
{
COORD coord;
int maxRating = 0, tmp, x, y, size;
for(int i = 0; i < 10; i++)
{
size = getShipSize(gameplace.ship[i]);
if(getShipStatus(gameplace.ship[i]) == LIVE)
if(size > 1)
maxRating += 2*size*size;
else
maxRating += size;
}
int isChoosen = 0, rating, attemp = 0;
while(!isChoosen)
{
x = rand()%10;
y = rand()%10;
rating = getRatingOfCell(gameplace, x, y);
if( (getSign(gameplace.field, x, y) != ZERO)&&
(getSign(gameplace.field, x, y) != MISSED)&&
(rating >= maxRating - 0.05*(maxRating*attemp))&&
(rating!=0))
{
coord.X = x;
coord.Y = y;
isChoosen = 1;
}
if(rating > 0) attemp++;
}
return coord;
}
//ходить до первого промаха
void MyComputer :: computerMove(GAMEPLACE &gameplace, COORD fieldCoord)
{
int result = FIRSTTIME;
while(((result == FIRSTTIME)||(result == WOUNDED)||
(result == KILLED))&&(!LOST(gameplace)))
result = makeMove(gameplace);
}
//////////////////////////////////////////////////////////
//game.h
//////////////////////////////////////////////////////////
#ifndef __game
#define __game
#define PLAYERVSCOMP 51
#define COMPVSPLAYER 52
#define FORPLAYER 54
#define FORCOMP 55
namespace MyGame {
//предварительные настройки
void preset(GAMEPLACE &gameplace, int flag);
//играть
|