Форум программистов
 
Регистрация на форуме тут, о проблемах пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail, а тут можно восстановить пароль

Купить рекламу на форуме 15-35 тыс рублей в месяц

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы Поиск в этой теме
Старый 02.08.2022, 18:46   #1
AlexFirefield
Пользователь
 
Регистрация: 22.06.2022
Сообщений: 11
По умолчанию Морской бой для консоли.

В учебных целях написал морской бой, для двух игроков
без игрока компьютера


Код:
#include <iostream>
#include <vector>
#include <ctime>
#include <memory>
#include<Windows.h>

struct position
{
	int x, y;
};
enum
{
	down = 0,
	right = 1,
	Clear = 0,
	lose = 1,	
	hit = 2	
};
const int sizeField = 10;
class Base_Ship;
class Point;
typedef std::vector<std::vector <Point>> vect2D_point;
class Point
{
public:
	Point(position Position_)
	{
		this->Position = Position_;
	}

	position GetPosition()
	{
		return Position;
	}
	int GetShoot()
	{
		return shoot;
	}
	void SetShoot(int var)
	{
		shoot = var;
	}
	int GetClear()
	{
		return clear;
	}
	void SetClear(int var)
	{
		clear = var;
	}
	void Owner(Base_Ship* owner_)
	{
		owner = owner_;
	}
	Base_Ship* GetOwner()
	{
		return owner;
	}

private:
	position Position;
	int shoot = 0;
	int clear = 0;
	Base_Ship* owner = nullptr;
};

class Base_Ship
{
public:

	Base_Ship(std::vector<std::vector <Point>>* field_,  int size_)
	{
		this->sizeShip = size_;
		this->field_ = field_;		
		life = sizeShip;		
		generatePosition();
		CreateBuffer(&Base_Ship::BufferLife);
		createShip();
	}

	void generatePosition()		//определяет рандомные координаты первой точки корабля
	{
		do {
			rotate = rand() % 2;
			Position.x = rand() % (sizeField - sizeShip);//отнимаем размер чтобы корабль не вышел за край поля
			Position.y = rand() % sizeField;
		} while (cheackFreePlace());
	}

	bool cheackFreePlace()//проверка не заняты ли сгенерированные координаты
	{
		if (rotate == right)
		{
			std::swap(Position.x, Position.y);
			for (size_t i = 0; i < sizeShip; i++)
			{
				if ((*field_)[Position.x][Position.y + i].GetClear() > 0)
				{
					return true;
				}
			}
			gorizont_size = sizeShip;
			return false;
		}
		else if (rotate == down)
		{
			for (size_t i = 0; i < sizeShip; i++)
			{
				if ((*field_)[Position.x + i][Position.y].GetClear() > 0)
				{
					return true;
				}
			}
			vertical_size = sizeShip;
			return false;
		}
		else
			return true;
	}
	
	void CreateBuffer(void(Base_Ship::* Life_Death)(int x, int y))//create a buffer around the ship
	{
		for (int x = Position.x - 1; x <= Position.x + vertical_size; x++)
		{
			if (x >= 0 && x < 10)
			{
				for (int y = Position.y - 1; y <= Position.y + gorizont_size; y++)
				{
					if (y >= 0 && y < 10)
					{
						(this->*Life_Death)(x, y);
					}
				}
			}
		}
	}

	void BufferLife(int x, int y)//create a buffer after  ship creation
	{
		(*field_)[x][y].SetClear(1);
	}

	void deathBuffer(int x, int y)//create a buffer after  ship death 
	{
		(*field_)[x][y].SetShoot((*field_)[x][y].GetClear());
	}

	void createShip()//заполняем клетки где будет корабль
	{
		switch (rotate)
		{
		case down:
			for (size_t i = 0; i < sizeShip; i++)
			{
				(*field_)[Position.x + i][Position.y].SetClear(2);
				(*field_)[Position.x + i][Position.y].Owner(this);
			}
			break;
		case right:
			for (size_t i = 0; i < sizeShip; i++)
			{
				(*field_)[Position.x][Position.y + i].SetClear(2);
				(*field_)[Position.x][Position.y + i].Owner(this);
			}
			break;
		default:
			break;
		}
	}

	bool DamageShip()//урон по кораблю -1клетка и проверка остались ли живые клетки у корабля
	{
		if (--life)
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	~Base_Ship()
	{
		CreateBuffer(&Base_Ship::deathBuffer);//вызываем создание буфера после гибели корабля
	}
private:
	std::vector<std::vector <Point>>* field_;
	position Position;
	int sizeShip;
	int rotate = 0;
	int vertical_size = 1;
	int gorizont_size = 1;
	int life;	
};

class InterFacE
{
public:	
	InterFacE();		
	~InterFacE();

	bool Damage()//выстрел
	{		
		if (field_[pointShoot.x][pointShoot.y].GetShoot() == Clear)
		{
			if (field_[pointShoot.x][pointShoot.y].GetClear() == hit)
			{
				field_[pointShoot.x][pointShoot.y].SetShoot(hit);
				//если в клетке был корабль, меняем значение на "поражена", и вызываем обьект корбля,хозяина клетки 
				Base_Ship* owner = field_[pointShoot.x][pointShoot.y].GetOwner();
				//затем проверяем есть ли еще живая клетка у корабля,если нет то обьект уничтожается и указатель на него
				if (owner->DamageShip())
				{					
					delete owner;
					owner = nullptr;
					--CountLivingShips;
				}				
				return true;
			}
			else if (field_[pointShoot.x][pointShoot.y].GetClear() < hit)
			{
				field_[pointShoot.x][pointShoot.y].SetShoot(lose);
				return false;
			}
			//если в клетке пусто, меняем значение на "мимо"
		}
		else
		{
			std::cout << "This point is already damaged.\n";
			return true;
			//если ввели координаты по которым уже стреляли
		}
	}

	void InputPoint()
	{
		bool checkInput;
		do{
			checkInput =false;
			char Ysymbol, Xnumber;
			std::cout << "Enter the coordinates of the shot into Player "<<playersNumber << "\nLetter = ";
			std::cin >> Ysymbol;

			std::cout << " And Number = ";
			std::cin >> Xnumber;

			pointShoot.x = Xnumber - '0';
			pointShoot.y = static_cast<int>(Ysymbol) - 97;
			if (pointShoot.x < 0 && pointShoot.x > 9 && pointShoot.y < 0 && pointShoot.y > 9)
			{
				std::cout << "Input Error!! ";
				checkInput = true;
			}			
		} while (checkInput);
	}

	int Shoot()
	{
		bool CheckPoint = false;
		do {
			InputPoint();
			CheckPoint = Damage();
			ShowBattlefieldEnemy();
			if (!CountLivingShips)
			{
				std::cout << "___Game over___\n";				
				return playersNumber;
			}
		} while (CheckPoint);
		return 0;
	}

	void ShowBattlefieldEnemy()//вывод на экран боевого поля врага
	{
		int j = 0;
		std::cout << "  _FIELD_PLAYER___ "<< playersNumber<< "\n";
		std::cout << "  a b c d e f g h i j\n";
		for (auto& it : field_)
		{
			std::cout << j++ << " ";
			for (auto& el : it)
			{
				if (el.GetShoot() == hit)
				{
					std::cout << "# ";
				}
				else if (el.GetShoot() == lose)
				{
					std::cout << ". ";
				}
				else if (el.GetShoot() == 0)
				{
					std::cout << "  ";
				}
			}
			std::cout << std::endl;
		}
	}
	void CreateShipsEnemy()
	{
		int SizeShips[sizeField] = { 4,3,3,2,2,2,1,1,1,1 };
		for (int k = 0; k < sizeField; k++)
		{
			new Base_Ship(&field_, SizeShips[k]);
			++CountLivingShips;
		}
	}
	void CreateEnemyField()
	{
		for (PointPlace.x = 0; PointPlace.x < sizeField; PointPlace.x++)
		{
			std::vector <Point> tempLine;
			for (PointPlace.y = 0; PointPlace.y < sizeField; PointPlace.y++)
			{
				tempLine.push_back(Point(PointPlace));
			}
			 field_.push_back(tempLine);
		}
	}

protected:
	std::vector<std::vector <Point>> field_;	
	int CountLivingShips=0;
	position PointPlace;
	position pointShoot;	
	 static int count;
	 int playersNumber;
};

int InterFacE::count = 0;

InterFacE::InterFacE()	
{
	playersNumber = (++count);
	CreateEnemyField();
	CreateShipsEnemy();	
}

InterFacE::~InterFacE()
{
}

int main()
{
	srand(time(NULL));
	
	InterFacE User02;
	InterFacE User01;
	int finalUser=0;
	while (!finalUser)
	{
		User02.ShowBattlefieldEnemy();
		
		finalUser=User02.Shoot();
		system("pause");
		system("cls");		
		if (finalUser)
		{
			break;
		}		
		User01.ShowBattlefieldEnemy();
		finalUser=User01.Shoot();
		system("pause");
		system("cls");
	}
	if (finalUser == 1 )
	{		
			std::cout << "WIN Player 2\n";
	}
	else if (finalUser == 2)
	{
		std::cout << "WIN Player 1\n";
	}

	return 0;
}
AlexFirefield вне форума Ответить с цитированием
Старый 02.08.2022, 19:09   #2
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 700
По умолчанию

AlexFirefield, критика нужна?
Алексей1153 вне форума Ответить с цитированием
Старый 02.08.2022, 22:36   #3
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,071
По умолчанию

Цитата:
Поощрение столь же необходимо гениальному писателю, сколь необходима канифоль смычку виртуоза

©Козьма Прутков
digitalis вне форума Ответить с цитированием
Старый 03.08.2022, 10:45   #4
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 700
По умолчанию

ладно, пройдусь по самым-самым верхам

Цитата:
Сообщение от AlexFirefield Посмотреть сообщение
#include<Windows.h>
не используется


Цитата:
Сообщение от AlexFirefield Посмотреть сообщение
typedef std::vector<std::vector <Point>> vect2D_point;
тоже


Цитата:
Сообщение от AlexFirefield Посмотреть сообщение
struct position
{
int x, y;
};
нет инициализации (не ошибка, но провокация себя на ошибку)



Цитата:
Сообщение от AlexFirefield Посмотреть сообщение
enum
{
down = 0,
->
Код:
enum class


Цитата:
Сообщение от AlexFirefield Посмотреть сообщение
Base_Ship* owner = nullptr;
либо делать const и никогда не разыменовывать, либо юзать умные указатели. Опасно оставлять такие торчащие указатели
Алексей1153 вне форума Ответить с цитированием
Старый 03.08.2022, 10:47   #5
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 700
По умолчанию

Цитата:
Сообщение от AlexFirefield Посмотреть сообщение
private:
std::vector<std::vector <Point>>* field_;
лучше сделать ссылкой (как и параметр в конструкторе)
Алексей1153 вне форума Ответить с цитированием
Старый 03.08.2022, 10:51   #6
AlexFirefield
Пользователь
 
Регистрация: 22.06.2022
Сообщений: 11
По умолчанию

спасибо.
за умные указатели тоже подумал, еще напишу часть для игры с компьютером, там их и добавлю
AlexFirefield вне форума Ответить с цитированием
Старый 03.08.2022, 13:26   #7
AlexFirefield
Пользователь
 
Регистрация: 22.06.2022
Сообщений: 11
По умолчанию

Алексей1153,

->

enum class

здесь вы имеете ввиду дать название enum
еще как вариант разделить их на 2 enum
один с направлением второй с состоянием клетки
AlexFirefield вне форума Ответить с цитированием
Старый 04.08.2022, 20:45   #8
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 700
По умолчанию

AlexFirefield,

Код:
enum class e_direction
{
	down,
	right,
};

enum class e_state
{
	Clear,
	lose,	
	hit,	
};
Алексей1153 вне форума Ответить с цитированием
Ответ
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Морской бой manchester_alan Общие вопросы Delphi 3 06.06.2015 12:55
Морской бой, С# Serg94 Помощь студентам 0 25.12.2013 21:23
Морской бой на С# M@@Shk@ Помощь студентам 1 05.06.2012 20:35
Нужно написать 3 игры в консоли на С++: морской бой, пятнашки и крестики-нолики... lewa2424 Помощь студентам 5 14.04.2010 21:33
Морской Бой Fanga C++ Builder 3 30.03.2010 17:03