Форум программистов, компьютерный форум CyberForum.ru

Нужна оценка - C++

Восстановить пароль Регистрация
 
%user_name%
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 4
20.01.2011, 19:42     Нужна оценка #1
Всем доброго времени суток.
Чуть меньше недели назад начал изучать С++ и сегодня написал таки некое подобие программы.

Суть просьбы: нужна чья-нибудь проверка на явный быдлокод/неудачные моменты; хотелось бы услышать мнение от всех, кто пишет больше моего. Сорсы, разумеется, прикреплены.
Буду рад любой критике в свой адрес.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Игра в крестики-нолики.
#include <iostream>
#include <conio.h>
 
using namespace std;
 
// Класс для создания ячеек поля. 
// value - значение: -1 "нолик", 1 "крестик", 0 пусто; prior - приоритет ячейки.
class Cell 
{
    public:
        int getValue () { return value; }
        void setValue ( int val ) { value = val; } 
        int getPrior () { return prior; }
        void setPrior ( int pr ) { prior = pr; }
    private:
        int value, prior;
};
 
void CreateField ( Cell **pField );
int SetPriority ( Cell **pField );
int CheckResultFromLastStep ( Cell **pField );
void Crossing ( Cell **pField );
void Zeroing ( Cell **pField );
 
 
int main()
{
    enum Cycle { UWin, CWin, CycCont, CycBreak };
    int fCycle, fCycle0, UserSc=0, CompSc=0;
    do
    {
        Cell **Field = new Cell*[3]; // Создание массива 3х3.
        for ( int i=0; i<3; i++ )
        {
            Field[i] = new Cell[3];
        }
        CreateField ( &*Field ); // Установка первоначальных значений и приоритетов.
        fCycle=2;
        fCycle0=2;
        while( fCycle==CycCont && fCycle0==CycCont )
        {
            system ("cls");
            cout << "Welcome to Tic-Tac-Toe                                    ";
            cout << "You " << UserSc << " - " << CompSc << " Comp \n\n";
            for ( int i=0; i<3; i++ ) //Вывод поля.
            {
                for ( int j=0; j<3; j++ )
                {
                    if ( Field[i][j].getValue () == 1 )
                        cout << "X ";
                    if ( Field[i][j].getValue () == -1 )
                        cout << "Y ";
                    if ( Field[i][j].getValue () == 0 )
                        cout << "_ ";
                }
                cout << endl;
            }
            cout << endl;
            Crossing ( &*Field ); // Ввод "крестика", изменение значения ячейки и ее приоритета.
            fCycle = SetPriority ( &*Field ); // Поиск наилучшей ячейки для следующего хода ИИ (по приоритету), проверка на выйгрыш пользователя.
            if (fCycle == CycCont)
            {
                Zeroing ( &*Field ); // Ввод "нолика", изменение значения ячейки и ее приоритета.
                fCycle0 = CheckResultFromLastStep ( &*Field ); // Проверка результатов после последнего действия ИИ, переустановка приоритета.
            }
        }
        for (int i=0; i<3; i++) // Удаление массива.
            delete Field[i];
        delete [] Field;
 
        cout << "\n\n";
        if ( fCycle==UWin )
        {
            cout << "You won!!1 \n\n";
            UserSc++;
        }
        if ( fCycle0==CWin )
        {
            cout << "Computer won! \n\n";
            CompSc++;
        }
        if ( fCycle==CycBreak )
        {
            cout << "Nobody won.. \n\n";
        }
        getch();
    } while ( true );
    getch();
    return 0;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Установка значения всех клеток на "0" (пустые) и установка приоритета на 3 для угловых, 4 - центральной, 1 - остальных.
void CreateField ( Cell **pField )
{
    for ( int i=0; i<3; i++ )
        for ( int j=0; j<3; j++ )
        {
            pField[i][j].setValue(0);
            pField[i][j].setPrior(1);
        }
    pField[1][1].setPrior(4);
    pField[0][0].setPrior(3);
    pField[0][2].setPrior(3);
    pField[2][0].setPrior(3);
    pField[2][2].setPrior(3);
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Установка приоритета в случае заполнения пользователем 2-х рядомстоящих клеток.
int SetPriority ( Cell **pField )
{
    int fNoWinner=0, fUser;
    for ( int i=0; i<3; i++ ) // Определение элементов (крестиков и ноликов) по строкам и столбцам.
    {
        fUser=0;
        for ( int j=0; j<3; j++ ) // Поиск элементов по строкам.
            if ( pField[i][j].getValue()==1 )
                fUser++;
        if ( fUser==3 ) // Определение победил ли игрок.
            return 0;
        if ( fUser==2 ) // Есть ли строки/столбцы, в которых пользователю осталось заполнить одну ячейку.
            for ( int j=0; j<3; j++ ) // Если есть - находим эту ячейку и присваиваем ей повышенный приоритет.
                if ( pField[i][j].getValue()==0 )
                    pField[i][j].setPrior(10);
    }
//------------------------------------------------------------------------------------
    for ( int j=0; j<3; j++ ) // Определение элементов (крестиков и ноликов) по строкам и столбцам.
    {
        fUser=0;
        for ( int i=0; i<3; i++ ) // Поиск элементов по столбцам.
            if ( pField[i][j].getValue()==1 )
                fUser++;
        if ( fUser==3 ) // Определение победил ли игрок.
            return 0;
        if ( fUser==2 ) // Есть ли строки/столбцы, в которых пользователю осталось заполнить одну ячейку.
            for ( int i=0; i<3; i++ ) // Если есть - находим эту ячейку и присваиваем ей повышенный приоритет.
                if ( pField[i][j].getValue()==0 )
                    pField[i][j].setPrior(10);
    }
//------------------------------------------------------------------------------------
    fUser=0;
    for ( int i=0; i<3; i++ ) // Определение элементов на диагоналях.
        for ( int j=0; j<3; j++ ) // Определение элементов на главной диагонали.
            if ( i==j && pField[i][j].getValue()==1 )
                fUser++;
    if ( fUser==3 ) // Определение победил ли игрок.
        return 0;
    if ( fUser==2 ) // Осталось ли пользователю заполнить одну ячейку на диагонали.
        for ( int i=0; i<3; i++ ) // Если такая ячейка есть - находим ее и присваиваем ей повышенный приоритет.
            for ( int j=0; j<3; j++ )
                if ( pField[i][j].getValue()==0 && i==j )
                    pField[i][j].setPrior(10);
//------------------------------------------------------------------------------------
    fUser=0;
    for ( int i=0; i<3; i++ ) // Определение элементов на диагоналях.
        for ( int j=0; j<3; j++ ) // Определение элементов на побочной диагонали диагонали.
            if ( i+j==2 && pField[i][j].getValue()==1 )
                fUser++;
    if ( fUser==3 ) // Определение победил ли игрок.
        return 0;
    if ( fUser==2 ) // Осталось ли пользователю заполнить одну ячейку на диагонали.
        for ( int i=0; i<3; i++ ) // Если такая ячейка есть - находим ее и присваиваем ей повышенный приоритет.
            for ( int j=0; j<3; j++ )
                if ( pField[i][j].getValue()==0 && i+j==2 )
                    pField[i][j].setPrior(10);
//------------------------------------------------------------------------------------
    for ( int i=0; i<3; i++ ) // Проверка на заполненность всего поля.
        for ( int j=0; j<3; j++ )
            if ( pField[i][j].getPrior()==-1 )
                fNoWinner++;
    if ( fNoWinner==9 )
        return 3;
    else
        return 2;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Проверка результатов после последнего действия ИИ.
int CheckResultFromLastStep ( Cell **pField )
{
    int fNoWinner=0, fComp;
    for ( int i=0; i<3; i++ ) // Определение элементов (крестиков и ноликов) по строкам и столбцам.
    {
        fComp=0;
        for ( int j=0; j<3; j++ ) // Поиск элементов по строкам.
            if ( pField[i][j].getValue()==-1 )
                fComp++;
        if ( fComp==3 ) // Победил ли ИИ.
            return 1; 
        if ( fComp==2 ) // Есть ли строки/столбцы, в которых ИИ осталось заполнить одну ячейку.
            for ( int j=0; j<3; j++ ) // Если есть - находим эту ячейку и присваиваем ей повышенный приоритет.
                if ( pField[i][j].getValue()==0 )
                    pField[i][j].setPrior(12);
    }
//------------------------------------------------------------------------------------
    for ( int j=0; j<3; j++ ) // Определение элементов (крестиков и ноликов) по строкам и столбцам.
    {
        fComp=0;
        for ( int i=0; i<3; i++ ) // Поиск элементов по столбцам.
            if ( pField[i][j].getValue()==-1 )
                fComp++;
        if ( fComp==3 ) // Победил ли ИИ.
            return 1; 
        if ( fComp==2 ) // Есть ли строки/столбцы, в которых ИИ осталось заполнить одну ячейку.
            for ( int i=0; i<3; i++ ) // Если есть - находим эту ячейку и присваиваем ей повышенный приоритет.
                if ( pField[i][j].getValue()==0 )
                    pField[i][j].setPrior(12);
    }
//------------------------------------------------------------------------------------
    fComp=0;
    for ( int i=0; i<3; i++ ) // Определение элементов на диагоналях.
        for ( int j=0; j<3; j++ ) // Определение элементов на главной диагонали.
            if ( i==j && pField[i][j].getValue()==-1 )
                fComp++;
    if ( fComp==3 ) // Победил ли ИИ.
        return 1; 
    if ( fComp==2 ) // Осталось ли ИИ заполнить одну ячейку на диагонали.
        for ( int i=0; i<3; i++ ) // Если такая ячейка есть - находим ее и присваиваем ей повышенный приоритет.     
            for ( int j=0; j<3; j++ ) 
                if ( pField[i][j].getValue()==0 && i==j )
                    pField[i][j].setPrior(12);
//------------------------------------------------------------------------------------
    fComp=0;
    for ( int i=0; i<3; i++ ) // Определение элементов на диагоналях.
        for ( int j=0; j<3; j++ ) // Определение элементов на побочной диагонали диагонали.
            if ( i+j==2 && pField[i][j].getValue()==-1 )
                fComp++;
    if ( fComp==3 ) // Победил ли ИИ.
        return 1; 
    if ( fComp==2 ) // Осталось ли ИИ заполнить одну ячейку на диагонали.
        for ( int i=0; i<3; i++ ) // Если такая ячейка есть - находим ее и присваиваем ей повышенный приоритет.     
            for ( int j=0; j<3; j++ ) 
                if ( pField[i][j].getValue()==0 && i+j==2 )
                    pField[i][j].setPrior(12);
//------------------------------------------------------------------------------------
    return 2;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Ввод координат для хода пользователя; перерасчет значений и приоритета для хода ИИ.
void Crossing ( Cell **pField )
{
    bool fl=0;
    int X,Y;
    while ( fl==0 ) // Ввод, изменение значения ячейки и ее приоритета.
    {
        cout << "Enter coords X: ";
        cin >> X;
        X--;
        cout << "Enter coords Y: ";
        cin >> Y;
        Y--;
        if ( X<=2 && Y<=2 )
            if ( pField[X][Y].getValue() == 0 )
            {
                fl=1;
                pField[X][Y].setValue(1);
                pField[X][Y].setPrior(-1);
            }
            else
                cout << "Incorrect coords" << endl;
        else
            cout << "Incorrect coords" << endl;
    }
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Нахождение наибольшего приоритета, ход компьютера.           
void Zeroing ( Cell **pField )
{
    int max=0, X=0, Y=0;
    for ( int i=0; i<3; i++ ) // Поиск максимального значения приоритета с запоминанием индексов.
        for ( int j=0; j<3; j++ )
            if ( max<pField[i][j].getPrior() )
            {
                max = pField[i][j].getPrior();
                X = i;
                Y = j;
            }
    pField[X][Y].setValue(-1);
    pField[X][Y].setPrior(-1);
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
20.01.2011, 19:52     Нужна оценка #2
%user_name%, Первое замечение. Функции с префиксом get должны быть константные.
+ Я бы использовал побольше перечислений. Магические числа не украшают код
killboss
 Аватар для killboss
57 / 57 / 2
Регистрация: 18.12.2010
Сообщений: 127
20.01.2011, 20:07     Нужна оценка #3
Вы используете в классе геттеры и сеттеры (функции). Отделяйте спецификацию от реализации (инкапсуция в каком-то роде). Т.е. header file постовляет только своего рода заглушки на функции, а cpp-файл реализует эти же функции.

А так если вы действительно работаете с С++ только неделю, то довольно не плохо!!!

Добавлено через 3 минуты
Впредь не выкладывайте код целиком, а только отдельные "интересные" кусочки (рассматривать 300 строчек чужого кода особой радости не приносит!!!)
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
20.01.2011, 20:47     Нужна оценка #4
killboss, стиль написания кода это личное дело каждого и никакого отношения к ООП не имеет. К тому же функции действительно небольшие.
ForEveR, в Java вообще нет понятия заголовочных файлов, по другому просто нельзя писать, в C# вроде бы тоже не принято.

%user_name%, если вы пишете на C++ с использованием STL (а я разглядел строку using namespace std), то пользоваться динамическим выделением памяти в чистом виде не совсем хороший путь. Пользуйтесь контейнерами vector, list и так далее.
Отдельные функции CreateField и ей подобные лучше выделить в класс Field.

И еще все таки лучше обойтись без использования using namespace, а писать путь полностью, то есть std::cout, std::cin, std::vector и так далее, иначе вся прелесть и смысл пространств имен теряется.
%user_name%
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 4
20.01.2011, 21:21  [ТС]     Нужна оценка #5
Цитата Сообщение от ForEveR Посмотреть сообщение
%user_name%, Первое замечение. Функции с префиксом get должны быть константные.
Учту.

Цитата Сообщение от ForEveR Посмотреть сообщение
+ Я бы использовал побольше перечислений. Магические числа не украшают код
Мм.. использование enum - признак хорошего тона?
Спасибо


Цитата Сообщение от killboss Посмотреть сообщение
Вы используете в классе геттеры и сеттеры (функции). Отделяйте спецификацию от реализации (инкапсуция в каком-то роде). Т.е. header file постовляет только своего рода заглушки на функции, а cpp-файл реализует эти же функции.
Ага, знаем, но просто здесь класс маленький, поэтому не решился отделять от тела основной программы.
Вопрос: как подключать хеадеры? #include <file_name.h>?

Цитата Сообщение от killboss Посмотреть сообщение
Впредь не выкладывайте код целиком, а только отдельные "интересные" кусочки (рассматривать 300 строчек чужого кода особой радости не приносит!!!)
Не подумал, больше не буду. )
Спасибо
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
20.01.2011, 21:22     Нужна оценка #6
%user_name%, #include "file_name.h"
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
20.01.2011, 21:24     Нужна оценка #7
Цитата Сообщение от %user_name% Посмотреть сообщение
Мм.. использование enum - признак хорошего тона?
Использование магических чисел - признак плохого тона
%user_name%
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 4
20.01.2011, 21:24  [ТС]     Нужна оценка #8
Цитата Сообщение от fasked Посмотреть сообщение
%user_name%, если вы пишете на C++ с использованием STL (а я разглядел строку using namespace std), то пользоваться динамическим выделением памяти в чистом виде не совсем хороший путь. Пользуйтесь контейнерами vector, list и так далее.
Отдельные функции CreateField и ей подобные лучше выделить в класс Field.
Этот момент понятен..

Цитата Сообщение от fasked Посмотреть сообщение
И еще все таки лучше обойтись без использования using namespace, а писать путь полностью, то есть std::cout, std::cin, std::vector и так далее, иначе вся прелесть и смысл пространств имен теряется.
..а вот этот как-то не очень.
Можно разъяснить?)
Escapable
53 / 53 / 1
Регистрация: 09.11.2010
Сообщений: 120
20.01.2011, 21:26     Нужна оценка #9
Цитата Сообщение от fasked Посмотреть сообщение
И еще все таки лучше обойтись без использования using namespace, а писать путь полностью, то есть std::cout, std::cin, std::vector и так далее, иначе вся прелесть и смысл пространств имен теряется.
Объясните мне пожалуйста почему "лучше обходиться" без using namespace'a и полностью писать std::? Не удобно же ...
killboss
 Аватар для killboss
57 / 57 / 2
Регистрация: 18.12.2010
Сообщений: 127
20.01.2011, 21:29     Нужна оценка #10
Цитата Сообщение от %user_name% Посмотреть сообщение
#include <file_name.h>
Эти файлы расположены где-то c:\program files\vs\ и так далее.
Вам же нужно (как я понял) открыть файл, который находится в проекте. Поэтому

C++
1
#include "file_name.h"
Да и необходимо что этот файл был прикреплён к проекту: Project->Add Existing Item или New Item (что вам подходит)
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
20.01.2011, 21:29     Нужна оценка #11
Escapable, Неудобно спать на потолке. А прямое использование std::
1) Явно видно использование пространтсва имен.
2) Нет возможности колизий.
asics
Freelance
Эксперт C++
 Аватар для asics
2838 / 1775 / 144
Регистрация: 09.09.2010
Сообщений: 3,842
20.01.2011, 21:30     Нужна оценка #12
Escapable, Вот напишите проект на С++, строк так, на пару тисяч и тогда посмотрите удобно или нет.
killboss
 Аватар для killboss
57 / 57 / 2
Регистрация: 18.12.2010
Сообщений: 127
20.01.2011, 21:32     Нужна оценка #13
Цитата Сообщение от Escapable Посмотреть сообщение
Объясните мне пожалуйста почему "лучше обходиться" без using namespace'a и полностью писать std::? Не удобно же ...
Во избежание конфликта имён!
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
20.01.2011, 21:35     Нужна оценка #14
Цитата Сообщение от Escapable Посмотреть сообщение
Объясните мне пожалуйста почему "лучше обходиться" без using namespace'a и полностью писать std::? Не удобно же ...
Для избежания конфликтов. Если во всем пространстве попадется две функции (класса, переменных и так далее) с одинаковыми именами, то возникнет конфликт. Например, в пространстве std существует класс vector. Допустим, что программист создал класс с аналогичным именем. И получаем такой код.

C++
1
2
3
4
5
6
7
8
9
#include <vector> // это вектор библиотеки STL
#include "myvector" // а это вектор, созданный нашим программистом
 
using namespace std;
 
int main()
{
     vector<int> v; // ошибка
}
В таком коде возникнет ошибка, потому как неизвестно экземпляр какого из двух классов создавать. Если же исключить строку using namespace и написать конкретно std::vector<int> или mynamespace::vector<int>, то конфликта соответственно не возникнет.
В небольших проектах, конечно это несущественно, так как весь объем кода довольно легко контролируется, но использование явного указания считается хорошей привычкой.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.01.2011, 21:58     Нужна оценка
Еще ссылки по теме:

C++ оценка быстродействия
Программы - оценка труда C++
Оценка стиля кода C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
%user_name%
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 4
20.01.2011, 21:58  [ТС]     Нужна оценка #15
На ~10 часу прослушивания одной песни появилась мысль: "А сколько я уже это слушаю?" отсюда же вопрос: я так понимаю, что С++ позволяет писать плагины под приложения поддерживающие их (Aimp, WinAmp, etc)?

fasked, спасибо за разъяснение с примером.

ADDED: а ф-ии CheckResultFromLastStep() и SetPriority() оказывается-то практически идентичны и вполне можно было обойтись одной с некоторыми правками.
Yandex
Объявления
20.01.2011, 21:58     Нужна оценка
Ответ Создать тему
Опции темы

Текущее время: 15:14. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru