Funkcjonalność mojego obiektowego kodu

0

Napisałem grę kółko krzyżyk przy użyciu biblioteki SFML 2.1
Nie miałem na celu stworzenie jak najlepszej gry lecz jak najlepszy kod, przez co nie dodałem napisu który gracz aktualnie wykonuje ruch itd.
Umieszczam tu obiektowy kod, i proszę o zastrzeżenia,rady,pokazanie błędów jakie popełniłem przy tworzeniu kodu. Chcę nauczyć się tworzyć dobre obiektowe programy, i większe projekty, przez co na tym małym przykładzie chcę dowiedzieć się jak Wy byście to zmienili. Co sądzicie o tej budowie programu?

#include "Menu.h"
#include <SFML\Graphics.hpp>
#include <vector>
#include <functional>

int main()
{
	Menu menu;
	menu.createMenu("data/menu/menu.txt");
	menu.select();
}
#pragma once

#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <SFML\Graphics.hpp>
#include <Windows.h>
#include "MenuView.h"
#include "Game.h"

class Menu
{
public:
	Menu(void);
	~Menu(void);

	void createMenu(const char *filename);
	void select();

private:
	sf::Font font;

	std::vector < sf::Text > menuItems;

	MenuView menuView;

	bool state;

	void game();
};
#pragma once

#include <vector>
#include <SFML\Graphics.hpp>

class MenuView
{
public:
	MenuView(void);
	~MenuView(void);

	void view(sf::RenderWindow &win, std::vector < sf::Text > menuItems);
};
#pragma once

#include <SFML\Graphics.hpp>
#include <Windows.h>
#include<iostream>
#include "GameViev.h"

class Game
{
public:
	Game(void);
	~Game(void);

	void createGame(sf::RenderWindow &win);

private:
	int board[3][3];

	void move(sf::RenderWindow &win);

	bool state;
	bool player;

	sf::Sprite sprite;
	sf::Texture texture;
	
	GameViev gameViev;

	void conditions();
};
#pragma once

#include <SFML\Graphics.hpp>
#include<iostream>

class GameViev
{
public:
	GameViev(void);
	~GameViev(void);

	void view(sf::RenderWindow &win, int board[3][3],sf::Sprite sprite);
};
#include "Menu.h"

sf::RenderWindow window(sf::VideoMode(800,600),"Mechanized Techno Explorer");

Menu::Menu(void)
{
	if(!font.loadFromFile("data/fonts/font.ttf"))
	{
		MessageBox(NULL,"Font not found!","ERROR",NULL);
		return;
	}

	state = 1;
}


Menu::~Menu(void)
{
}

void Menu::createMenu(const char *filename)
{
	std::ifstream openfile(filename);

	if( openfile.good() == true )
	{
		if(openfile.is_open())
		{
			std::string line;
			int i = 0;

			while(!openfile.eof())
			{
				getline(openfile,line);
				menuItems.emplace_back( line, font );
				menuItems[i].setCharacterSize(65);
				menuItems[i].setPosition(800/2-menuItems[i].getGlobalBounds().width/2,200+i*120);
				i++;
			}
		}
	}
	else
		MessageBox(NULL,"File not found!","ERROR",NULL);
}

void Menu::select()
{
	while(state == 1)
	{
		sf::Vector2f mouse(sf::Mouse::getPosition(window));
		sf::Event event;

		while(window.pollEvent(event))
		{
			if(event.type == sf::Event::Closed || event.type == sf::Event::KeyPressed &&
				event.key.code == sf::Keyboard::Escape)
					state = 0;
			else if(menuItems[menuItems.size() - 1].getGlobalBounds().contains(mouse) &&
				event.type == sf::Event::MouseButtonReleased && event.key.code == sf::Mouse::Left)
					state = 0;
			else if(menuItems[0].getGlobalBounds().contains(mouse) &&
				event.type == sf::Event::MouseButtonReleased && event.key.code == sf::Mouse::Left)
					game();
		}

		for(int i=0; i<menuItems.size(); i++)
			if(menuItems[i].getGlobalBounds().contains(mouse))
				menuItems[i].setColor(sf::Color::Cyan);
			else 
				menuItems[i].setColor(sf::Color::White);
 
		menuView.view(window,menuItems);
	}
}

void Menu::game()
{
   Game *pointer = new Game;
   
   pointer -> createGame(window);
   
   delete pointer;
}
#include "MenuView.h"


MenuView::MenuView(void)
{
}


MenuView::~MenuView(void)
{
}

void MenuView::view(sf::RenderWindow &win, std::vector < sf::Text > menuItems)
{
	win.clear();

	for(int i=0; i<menuItems.size(); i++)
		win.draw(menuItems[i]);

	win.display();
}
#include "Game.h"


Game::Game(void)
{
	state = 1;
	player = 0;
}


Game::~Game(void)
{
}

void Game::createGame(sf::RenderWindow &win)
{
	for( int i=0; i<3; i++)
	for( int j=0; j<3; j++)
		board[i][j] = 0;

	if(!texture.loadFromFile("data/images/tileset.png"))
	{
		MessageBox(NULL,"Textures not found!","ERROR",NULL);
		return;
	}

	sprite.setTexture(texture);

	while(state == 1)
	{
		move(win);
		gameViev.view(win,board,sprite);
		conditions();
	}
}

void Game::move(sf::RenderWindow &win)
{
		sf::Event event;

		while(win.pollEvent(event))
		{
			if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape )
				state = 0;
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num1 )
			{
				if( board[0][0] == 0)
				{
					board[0][0] = player + 1;
					
					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num2 )
			{
				if( board[1][0] == 0)
				{
					board[1][0] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num3 )
			{
				if( board[2][0] == 0)
				{
					board[2][0] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num4 )
			{
				if( board[0][1] == 0)
				{
					board[0][1] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num5 )
			{
				if( board[1][1] == 0)
				{
					board[1][1] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num6 )
			{
				if( board[2][1] == 0)
				{
					board[2][1] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			}
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num7 )
			{
				if( board[0][2] == 0)
				{
					board[0][2] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num8 )
			{
				if( board[1][2] == 0)
				{
					board[1][2] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
			else if( event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Num9 )
			{
				if( board[2][2] == 0)
				{
					board[2][2] = player + 1;

					if(player == 0)
						player = 1;
					else 
						player = 0;
				}
			} 
		}
}

void Game::conditions()
{
	for(int i=1; i<3; i++)
		{
			if(board[0][0] == i)
				if(board[0][1] == i)
					if(board[0][2] == i)
						state = 0;

			if(board[1][0] == i)
				if(board[1][1] == i)
					if(board[1][2] == i)
						state = 0;

			if(board[2][0] == i)
				if(board[2][1] == i)
					if(board[2][2] == i)
						state = 0;

			if(board[0][0] == i)
				if(board[1][0] == i)
					if(board[2][0] == i)
						state = 0;

			if(board[0][1] == i)
				if(board[1][1] == i)
					if(board[2][1] == i)
						state = 0;

			if(board[0][2] == i)
				if(board[1][2] == i)
					if(board[2][2] == i)
						state = 0;

			if(board[0][0] == i)
				if(board[1][1] == i)
					if(board[2][2] == i)
						state = 0;

			if(board[0][2] == i)
				if(board[1][1] == i)
					if(board[2][0] == i)
						state = 0;

		}

		int c = 0;

		for( int i=0; i<3; i++)
		for( int j=0; j<3; j++)
		{
			if(board[i][j] == 0)
				c++;
		}

		if(c == 0)
			state = 0;
}
#include "GameViev.h"


GameViev::GameViev(void)
{
}


GameViev::~GameViev(void)
{
}

void GameViev::view(sf::RenderWindow &win, int board[3][3],sf::Sprite sprite)
{
	win.clear();

	for( int i=0; i<3; i++)
	for( int j=0; j<3; j++)
	{
		sprite.setTextureRect(sf::IntRect(board[i][j]*50,0,50,50));
		sprite.setPosition((i+6.5)*50,(j+4)*50);
		win.draw(sprite);
	}

	win.display();
}

:)

2

menuItems[i].setPosition(800/2-menuItems[i].getGlobalBounds().width/2,200+i*120); - Magic numbers tu
i sprite.setPosition((i+6.5)*50,(j+4)*50); tu, i w innych miejscach.
void Game::move(sf::RenderWindow &win) - To raczej zły pomysł , lepiej dziedziczyć z sf::Drawable, sf::Transformable
Poza tym klasa gry powinna zajmować sie stricte grą a nie obsługą zdarzeń.

1
menuItems[i].setPosition(800/2-menuItems[i].getGlobalBounds().width/2,200+i*120);
  • Sam dziś za to dostałem upomnienie mianowicie magiczne cyferki. Możesz do tego użyć jakiejś zmiennej offset.
GameViev::~GameViev(void)
{
}
  • Puste destruktory (i kilka konstruktorów); pewnie to IDE stworzyło.
  1. Brak komentarzy.

Nie zagłębiałem się mocno w kod ale z tego co widzę to jest całkiem dobrze napisany (pod względem stylu oraz zaplanowania).

0

Co do ostatniej uwagi, stworzyłem klasę MenuView dziedziczącą właśnie tak jak mówisz, ale po stworzeniu obiektu tej klasy w klasie Menu wyskakiwał błąd że nie można tak tworzyć obiektu klasy wirtualnej czy coś. W każdym razie następnym razem lepiej się temu przyjże i już tak będę robił.

0

Tak, IDE samo stworzyło te puste destruktory i konstruktory, nie wiem czy gdybym usunął je w .cpp to by kod się kompilował, w każdym razie nie wiem czemu miał bym je usuwać :D

0

Tylko rzuciłem okiem na kod. Same ify-elsy. Pomyśl nad innym rozwiązaniem.

2
  1. Niepotrzebnie rozległy kod.
  2. Mało obiektowy.
  3. Kiss&Dry złamane
  4. Magiczne liczby.
  5. Mieszanie przenośnego SFML z winapi, serio?
  6. Straszne drabinki ifów.
  7. Brak odpowiednich algorytmów, zamiast tego wszystko jest sprawdzane z ręki.
  8. Brak odpowiednich wzorców projektowych typowych dla gier(zamiast tego drabinki ifów)
0
  1. Jeśli chodzi o dużą ilość ifów to tak, starałem się dużo nie myśleć nad algorytmami, a raczej stworzyć samą strukturę programu, pod ocenę poddaje więc kod nie algorytmy :)
  2. Mało obiektowy - Trudno mi tutaj coś zmienić, bo nie wiem co powinienem :)
  3. Kiss&Dry złamane - Zdecydowanie, wiem jak to naprawić.
  4. Magiczne liczby.
  5. Mieszanie przenośnego SFML z winapi, serio? - Chodzi o funkcję "Windows.h"? Nie wiedziałem że tak się nie powinno robić, raczej każdy poradnik tego używa.
  6. Straszne drabinki ifów. -Jak już wspomniałem moim zamierzeniem było poddanie pod ocenę budowy programu nie algorytmów
  7. Brak odpowiednich algorytmów, zamiast tego wszystko jest sprawdzane z ręki. -Jak wyżej

1 użytkowników online, w tym zalogowanych: 0, gości: 1