Ocena gry kółko i krzyżyk C++

0

Ahoj!
Ostatnio napisałem konsolową wersję znanej wszystkim gry kółko i krzyżyk. Prosiłbym o ocenę kodu i o ewentualne porady oraz wskazówki.

//main.cpp
#include "../include/functions.h"

using namespace std;

int main()
{
	char again {'Y'};
	while (again == 'Y' || again == 'y')
	{
		string square {"0123456789"};
		char player {'X'};
		int status {-1};
		while (status == -1)
		{
			move(square, player);
			status = check(square);
		}
		player = player == 'X' ? 'O' : 'X';
		draw_board(square);
		if (status == 1)
			cout << "\nPlayer " << player << " won!\n";
		else
			cout << "\nGame draw!\n";
		cout << "\vPlay again? (Y)es, (N)o/(E)xit? ";
		cin >> again;
	}
	return 0;
}
//functions.cpp
#include "../include/functions.h"

using namespace std;

void draw_board(const string& s)
{
	system("clear");
	cout << "Tic-Tac-Toe\n\v";
	for(int i=1; i!=10; ++i)
	{
		cout << ' ' << s[i] << ' ';
		if(i % 3)
		cout << '|';
		else if(i != 9)
		cout << "\n---+---+---\n";
		else cout << endl;
	}
}

void move(string& s, char& player)
{
	draw_board(s);
	cout << "\nPlayer " << player << " moves: ";
	static int choice {0};
	cin >> choice;

	while (choice < 1 || choice > 9 || s[choice] > 57)
	{
		cout << "Invalid move!";
		cin.ignore();
		getchar();
		draw_board(s);
		cout << "\nPlayer " << player << " moves: ";
		cin >> choice;
	}
	s[choice] = player;
	player = player == 'X' ? 'O' : 'X';
}

int check(const string& s)
{
	static const int ways[8][3] {{1,2,3},{4,5,6},{7,8,9},
				     {1,4,7},{2,5,8},{3,6,9},
				     {1,5,9},{3,5,7}};
	for (int i=0; i!=8; ++i)
		if (s[ways[i][0]] == s[ways[i][1]] && s[ways[i][1]] == s[ways[i][2]])
			return 1;	
	int count {};
	for (int i=1; i!=10; ++i)
		if (s[i] != 48+i)
			++count;
	if (count == 9)
		return 0;
	return -1;
}
//functions.h
#include <iostream>

void draw_board(const std::string&);

void move(std::string&, char&);

int check(const std::string&);
1

Nieźle.

W sumie te parę funkcji niepotrzebnie rozbijałeś na pliki functions.h i functions.cpp, jakby to była jakaś klasa to inaczej. Nie powiem jak tu zrobić to na klasach, w takim przypadku klasy chyba by tylko niepotrzebnie ten kod skomplikowały (musiałbyś zrobić klasy board, player, albo te wszystkie funkcje wepchnąć w jedną pod nazwą game etc.)

W funkcji board to cout << "Tic-Tac-Toe\n\v"; zmieniłbym po prostu na cout << "\n"; - czytelniejsza jest wtedy tablica bez tego znaczka sigma i napisów zaraz nad nią.

1
  1. Co to znaczy że "status == -1" ? Nie powinien być enum i przechowywać CONTUE_GAME/END_GAME?
  2. Nawet jeśli jest tylko 1 linia w ciele sekcji if, stosuj nawiasy. Kiedyś się przejedziesz jak zrobisz inne wcięcia lub popełnisz inny błąd.
  3. Masz jeszcze pętlę do{...} while(...); Jest ok do tego przypadku sprawdzenia czy kontynuować grę.
  4. Nie oczekuj działania tabulatora pionowego w MS Windows. Obecnie (z doświadczenia), działa na systemach POSIX i systemach IBM'a.
  5. Nie używaj using namespace std. Mały błąd i kompilator nie będzie wiedział o które move(...) Ci chodzi (a może o std::move(...) ?). Używaj w pełni kawalifikowanych nazw czyli std::cout itp.
  6. Brak makr strażniczych w nagłówku functions.h.
  7. W tym nagłówku powinieneś wczytać wyłącznie <string> a nie iostream. W sygnaturach metod występuje std::string.
  8. Używanie std::system(...) to ogólnie niebezpieczne przyzwyczajenie. Jeśli możesz, unikaj. To mały program więc nie ma co się spierać. Produkcyjnie będziesz miał jednak za takie coś ban'a.
  9. Co oznaczają "magiczne wartości" w funkcji check() ? ( 0, 1, -1). To powinny być enum'y ze statusem sprawdzenia.
  10. Zamiast static const warto rozważyć użycie constexpr.

Zawsze możesz potraktować uwagi jak "czepialstwo". Niemniej jednak o nie prosiłeś :-)
Masz tu przykład przenośnego (trochę bardziej) czyszczenia ekranu:

void draw_board(const std::string& s) {
#ifdef _WIN32
    std::system("cls");
#elif __linux__
    std::system("clear");
#endif
0

Dzięki za odpowiedź, rady, wskazówki i trochę czepialstwa ;) O niedziałającym tabulatorze pionowym nie wiedziałem, bo pracuję na Linuxie - dzięki za info. Resztę przemyślę. Co do std::system() to mógłbyś wyjaśnić dlaczego unikać tej funkcji?

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