Я решил сделать игру-змейку своим первым проектом на C ++ (с использованием ООП), и я не следил ни за одним обучающим курсом, пока делал это, теперь я разочарован и мне нужно знать, хороший это код или нет и что можно улучшить в этом?
Заголовочный файл класса карты:
#pragma once
#include <vector>
#include <iostream>
#include "Snake.h"
#include "Wall.h"
#include "Food.h"
class Map
{
public:
void display_map(Snake& snake, Wall& wall, Food& food);
};
Исходный файл класса карты:
#include "Map.h"
void Map :: display_map(Snake& snake, Wall& wall, Food& food)
{
system("cls");
for (int i = 0; i < wall.get_height(); i++)
{
for (int j = 0; j < wall.get_width(); j++)
{
vector<int> temp = { j,i };
int flag = 1;
{
for (auto& elm : snake.coor)
{
if (elm[0] == j && elm[1] == i)
{
for (auto& elm1 : snake.body)
{
if (elm1.pos == elm)
{
cout << elm1.symbol;
j++;
}
}
}
}
}
if (food.pos[0] == j && food.pos[1] == i)cout << food.symbol;
else if ((i == 0 || i == wall.get_height() - 1) || (j == 0 || j == wall.get_width() - 2))
{
for (int k = 0; k < wall.wall_coor.size(); k++)
{
if (wall.wall_coor[k] == temp)
{
flag = 0;
}
}
if (flag == 1)
wall.wall_coor.push_back(temp);
cout << wall.get_symbol();
}
else cout << " ";
}
cout << endl;
}
}
Заголовочный файл класса Snake:
#pragma once
#include <vector>
#include <conio.h>
using namespace std;
class Snake
{
//Attributes
public:
struct Body
{
char symbol;
vector <int> pos;
};
vector <vector<int>> coor;
vector <Body> body;
int dir = 1;
//Behaviors
void add_to_body(char ch, int x, int y);
int change_dir();
//Constructor
Snake(char ch="X", int x = 40, int y = 10);
};
Исходный файл класса Snake:
#include "Snake.h"
void Snake :: add_to_body(char ch, int x, int y)
{
Body temp;
temp.symbol = ch;
temp.pos = { x,y };
coor.push_back(temp.pos);
body.push_back(temp);
}
int Snake :: change_dir()
{
switch (_getch())
{
case 'w':
dir = 1;
return dir;
break;
case 'a':
dir = 2;
return dir;
break;
case 's':
dir = 3;
return dir;
break;
case 'd':
dir = 4;
return dir;
break;
default:;
}
}
Snake :: Snake(char ch , int x , int y)
{
add_to_body(ch, x, y);
add_to_body('o', x, y + 1);
add_to_body('o', x, y + 2);
add_to_body('o', x, y + 3);
add_to_body('o', x, y + 4);
};
Заголовочный файл класса еды:
#pragma once
#include <vector>
#include <ctime>
using namespace std;
class Food
{
public:
//Attributes
char symbol="@";
vector <int> pos;
//Behavior
vector <int> generate_food_x_y_coordinates(int x, int y);
//Constructor
Food(char symbol="@", vector<int> position = { 78,4 });
};
Исходный файл класса еды:
#include "Food.h"
vector <int> Food :: generate_food_x_y_coordinates(int x, int y)
{
srand(time(NULL));
vector <int> position = {(rand() * 2 % (x-4)) + 2 , (rand() * 2 % (y - 4)) + 2 };
return position;
}
Food :: Food(char symbol, vector<int> position )
:symbol{ symbol }, pos{ position } {};
Заголовочный файл класса стены:
#pragma once
#include <vector>
using namespace std;
class Wall
{
char symbol;
int width;
int height;
public:
vector <vector<int>> wall_coor = { {0,0} };
int get_width()
{
return width;
}
int get_height()
{
return height;
}
char get_symbol()
{
return symbol;
}
Wall(char wall="https://codereview.stackexchange.com/questions/259332/#", int width = 81, int height = 21)
:symbol{ wall }, width{ width }, height{ height }{}
};
По какой-то причине я решил обернуть весь класс стены в файл заголовка, потому что в поведении класса не так уж много; только функции получения.
Ну наконец то:
Основная функция (игровая логика):
#include "Map.h"
#include "Snake.h"
#include "Wall.h"
#include "Food.h"
using namespace std;
void main()
{
bool game_over = false;
Snake snake ('X' , 78 , 12);
Wall wall("https://codereview.stackexchange.com/questions/259332/#", 82, 22);
Food food('@');
Map map;
while (!game_over)
{
if (_kbhit())
snake.change_dir();
switch (snake.dir)
{
case 1:
while (!_kbhit())
{
for (int i = snake.coor.size() - 1; i >= 0; i--)
{
if (i - 1 >= 0)
snake.coor[i] = snake.coor[i - 1];
else if (i == 0)
snake.coor[0][1]--;
}
for (int j = 0; j < snake.body.size(); j++)
{
snake.body[j].pos = snake.coor[j];
}
for (int k = 0; k < wall.wall_coor.size(); k++)
{
if (snake.coor[0] != wall.wall_coor[k])
{
continue;
}
else if (snake.coor[0] == wall.wall_coor[k])
{
game_over = true;
break;
}
break;
}
for (int k = 1; k < snake.coor.size(); k++)
{
if (snake.coor[0] != snake.coor[k])
{
continue;
}
else if (snake.coor[0] == snake.coor[k])
{
game_over = true;
break;
}
break;
}
if (snake.coor[0] == food.pos)
{
food.pos = food.generate_food_x_y_coordinates(wall.get_width(), wall.get_height() );
snake.add_to_body('o', snake.coor.back()[0] , snake.coor.back()[1]);
}
else
{
food.pos = food.pos;
}
map.display_map(snake, wall, food);
}
if (snake.change_dir() == 3)
{
snake.dir = 1;
continue;
}
break;
case 2:
while (!_kbhit())
{
for (int i = snake.coor.size() - 1; i >= 0; i--)
{
if (i - 1 >= 0)
snake.coor[i] = snake.coor[i - 1];
else if (i == 0)
snake.coor[0][0] -= 2;
}
for (int j = 0; j < snake.body.size(); j++)
{
snake.body[j].pos = snake.coor[j];
}
for (int k = 0; k < wall.wall_coor.size(); k++)
{
if (snake.coor[0] != wall.wall_coor[k])
{
continue;
}
else if (snake.coor[0] == wall.wall_coor[k])
{
game_over = true;
break;
}
break;
}
for (int k = 1; k < snake.coor.size(); k++)
{
if (snake.coor[0] != snake.coor[k])
{
continue;
}
else if (snake.coor[0] == snake.coor[k])
{
game_over = true;
break;
}
break;
}
if (snake.coor[0] == food.pos)
{
food.pos = food.generate_food_x_y_coordinates(wall.get_width() - 4, wall.get_height() - 4);
snake.add_to_body('o', snake.coor.back()[0] , snake.coor.back()[1] );
}
else
{
food.pos = food.pos;
}
map.display_map(snake, wall, food);
}
if (snake.change_dir() == 4)
{
snake.dir = 2;
continue;
}
break;
case 3:
while (!_kbhit())
{
for (int i = snake.coor.size() - 1; i >= 0; i--)
{
if (i - 1 >= 0)
snake.coor[i] = snake.coor[i - 1];
else if (i == 0)
snake.coor[i][1]++;
}
for (int j = 0; j < snake.body.size(); j++)
{
snake.body[j].pos = snake.coor[j];
}
for (int k = 0; k < wall.wall_coor.size(); k++)
{
if (snake.coor[0] != wall.wall_coor[k])
{
continue;
}
else if (snake.coor[0] == wall.wall_coor[k])
{
game_over = true;
break;
}
break;
}
for (int k = 1; k < snake.coor.size(); k++)
{
if (snake.coor[0] != snake.coor[k])
{
continue;
}
else if (snake.coor[0] == snake.coor[k])
{
game_over = true;
break;
}
break;
}
if (snake.coor[0] == food.pos)
{
food.pos = food.generate_food_x_y_coordinates(wall.get_width() - 4, wall.get_height() - 4);
snake.add_to_body('o', snake.coor.back()[0] , snake.coor.back()[1]);
}
else
{
food.pos = food.pos;
}
map.display_map(snake, wall, food);
}
if (snake.change_dir() == 1)
{
snake.dir = 3;
continue;
}
break;
case 4:
while (!_kbhit())
{
for (int i = snake.coor.size() - 1; i >= 0; i--)
{
if (i - 1 >= 0)
snake.coor[i] = snake.coor[i - 1];
else if (i == 0)
{
snake.coor[i][0] += 2;
}
}
for (int j = 0; j < snake.body.size(); j++)
{
snake.body[j].pos = snake.coor[j];
}
for (int k = 0; k < wall.wall_coor.size(); k++)
{
if (snake.coor[0] != wall.wall_coor[k])
{
continue;
}
else if (snake.coor[0] == wall.wall_coor[k])
{
game_over = true;
break;
}
break;
}
for (int k = 1; k < snake.coor.size(); k++)
{
if (snake.coor[0] != snake.coor[k])
{
continue;
}
else if (snake.coor[0] == snake.coor[k])
{
game_over = true;
break;
}
break;
}
if (snake.coor[0] == food.pos)
{
food.pos = food.generate_food_x_y_coordinates(wall.get_width() - 4, wall.get_height() - 4);
snake.add_to_body('o',snake.coor.back()[0] , snake.coor.back()[1] );
}
else
{
food.pos = food.pos;
}
map.display_map(snake, wall, food);
}
if (snake.change_dir() == 2)
{
snake.dir = 4;
}
break;
}
}
system("pause");
}